@import url('fonts.css');

/* ---------------------------------------------------------------
   Tokens
---------------------------------------------------------------- */
:root {
  --ink: #1a1a1a;
  --ink-soft: #4a4a4a;
  --accent: #e859b5;
  --accent-deep: #c73d96;   /* passes AA on light backgrounds; --accent does not */
  --charcoal: #363636;
  --cream: #f6e4cb;
  --offwhite: #f8f8f7;
  --brick: #d82713;
  --gold: #e4af63;
  --teal: #0e7169;        /* scripture; brightest teal clearing AA on white, cream and gold */
  --gold-light: #f8ebd8;   /* the gold at ~25% over white */
  --white: #fff;
  --grey-light: #f4f4f3;

  --nav-h: 56px;
  --container: 1020px;
  --gutter: clamp(1.25rem, 5vw, 5.5rem);

  /* set-apart blocks (quotes, scripture, contributor voice) step in from the
     body measure on both sides so they read as interruptions in the text */
  --inset: clamp(1rem, 6vw, 7rem);
  /* vertical rhythm between a block and the prose around it */
  --block-gap: clamp(1.75rem, 3.5vw, 2.75rem);

  /* Each step interpolates linearly between its size at 375px and at 1200px,
     so mid-range widths get a real value instead of sitting on the floor. */
  --step-hero: clamp(1.875rem, calc(1.4773rem + 1.697vw), 2.75rem);   /* 30 → 44 */
  --step-h2: clamp(1.875rem, calc(1.4773rem + 1.697vw), 2.75rem);
  --step-h3: clamp(1.0625rem, calc(1.0057rem + 0.242vw), 1.1875rem);  /* 17 → 19 */
  --step-body: clamp(1rem, calc(0.9432rem + 0.242vw), 1.125rem);      /* 16 → 18 */
  --step-link: clamp(0.9375rem, calc(0.9091rem + 0.121vw), 1rem);     /* 15 → 16 */
  --step-nav: clamp(0.8125rem, calc(0.7841rem + 0.121vw), 0.875rem);  /* 13 → 14 */

  --ease: cubic-bezier(.22, .61, .36, 1);
}

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

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

body {
  margin: 0;
  font-family: 'DM Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: var(--step-body);
  line-height: 1.6;
  color: var(--ink);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
}

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

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: -0.045em;
}

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

a { color: inherit; }

:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* --gutter is the minimum side breathing room, not added padding — so on wide
   screens the content box lands at the same x as the original design. */
.container {
  width: min(var(--container), 100% - (2 * var(--gutter)));
  margin-inline: auto;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  padding: .75rem 1.25rem;
  background: var(--white);
  color: var(--ink);
  font-weight: 700;
}
.skip-link:focus { left: 0; }

/* ---------------------------------------------------------------
   Navigation
---------------------------------------------------------------- */
.nav {
  position: fixed;
  inset: 0 0 auto;
  z-index: 100;
  background: transparent;
  min-height: var(--nav-h);
  transition: background .3s var(--ease), box-shadow .3s var(--ease);
}

/* Once the page scrolls, content would run under the transparent bar. A light
   frosted panel keeps the links legible while preserving the transparent look
   at the top of the page. */
.nav--scrolled {
  background: rgba(248, 248, 247, .85);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  box-shadow: 0 1px 0 rgba(0, 0, 0, .07);
}

.nav__inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(1rem, 2.5vw, 2rem);
  min-height: var(--nav-h);
  width: min(var(--container), 100% - (2 * var(--gutter)));
  margin-inline: auto;
}

.nav__toggle {
  display: none;
  align-items: center;
  gap: .6rem;
  margin-left: auto;
  padding: .55rem .35rem;
  border: 0;
  background: none;
  color: var(--charcoal);
  font: 700 var(--step-nav)/1 'DM Sans', system-ui, sans-serif;
  letter-spacing: .08em;
  text-transform: uppercase;
  cursor: pointer;
}

.nav__burger { display: block; width: 22px; height: 14px; position: relative; }
.nav__burger span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  background: currentColor;
  transition: transform .3s var(--ease), opacity .2s linear;
}
.nav__burger span:nth-child(1) { top: 0; }
.nav__burger span:nth-child(2) { top: 6px; }
.nav__burger span:nth-child(3) { top: 12px; }

[aria-expanded='true'] .nav__burger span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
[aria-expanded='true'] .nav__burger span:nth-child(2) { opacity: 0; }
[aria-expanded='true'] .nav__burger span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

.nav__list {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.6vw, 2.1rem);
  margin: 0;
  padding: 0;
  list-style: none;
}

.nav__item { position: relative; }

.nav__link {
  display: inline-flex;
  align-items: center;
  gap: .3em;
  padding: .5rem 0;
  color: var(--charcoal);
  font-family: 'DM Sans', system-ui, sans-serif;
  font-size: var(--step-nav);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: color .15s linear;
}

.nav__link:hover { color: var(--accent-deep); }
.nav__link[aria-current='page'] { color: var(--accent-deep); }

.nav__caret {
  width: .55em;
  height: .55em;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform .25s var(--ease);
}

/* Desktop dropdown */
.nav__submenu {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translate(-50%, 6px);
  min-width: 15rem;
  margin: 0;
  padding: .5rem 0;
  list-style: none;
  background: var(--white);
  border-radius: 10px;
  box-shadow: 0 12px 34px rgba(0, 0, 0, .14), 0 0 0 1px rgba(0, 0, 0, .05);
  opacity: 0;
  visibility: hidden;
  transition: opacity .2s var(--ease), transform .2s var(--ease), visibility .2s;
}

.nav__item:hover > .nav__submenu,
.nav__item:focus-within > .nav__submenu {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
}

.nav__sublink {
  display: block;
  padding: .55rem 1.25rem;
  color: var(--charcoal);
  font-family: 'DM Sans', system-ui, sans-serif;
  font-size: .875rem;
  font-weight: 500;
  text-decoration: none;
}

.nav__sublink:hover { color: var(--accent-deep); background: rgba(0, 0, 0, .04); }

@media (max-width: 860px) {
  .nav__inner { justify-content: flex-start; }
  .nav__toggle { display: inline-flex; }

  .nav__list {
    position: fixed;
    inset: var(--nav-h) 0 auto;
    display: block;
    max-height: calc(100dvh - var(--nav-h));
    overflow-y: auto;
    padding: .5rem 0 1.5rem;
    background: rgba(248, 248, 247, .97);
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
    border-top: 1px solid rgba(0, 0, 0, .08);
    transform: translateY(-12px);
    opacity: 0;
    visibility: hidden;
    transition: opacity .25s var(--ease), transform .25s var(--ease), visibility .25s;
  }

  .nav__list { pointer-events: none; }
  .nav__list[data-open='true'] { opacity: 1; visibility: visible; transform: none; pointer-events: auto; }

  .nav__item { border-bottom: 1px solid rgba(0, 0, 0, .07); }
  .nav__item:last-child { border-bottom: 0; }

  .nav__link {
    justify-content: space-between;
    width: 100%;
    padding: 1rem var(--gutter);
    font-size: 1rem;
  }

  .nav__item--has-menu > .nav__link[aria-expanded='true'] .nav__caret {
    transform: translateY(2px) rotate(-135deg);
  }

  .nav__submenu {
    position: static;
    transform: none;
    min-width: 0;
    padding: 0;
    background: rgba(0, 0, 0, .035);
    border-radius: 0;
    box-shadow: none;
    opacity: 1;
    display: none;
  }

  /* The submenu's visibility is tied to the menu being open. Declared on the
     submenu itself it would override the closed menu's own visibility:hidden —
     a child can always declare itself visible inside a hidden parent — and the
     links then sat over the page, swallowing taps meant for the content. */
  .nav__list[data-open='true'] .nav__submenu { visibility: visible; }

  /* Must match the desktop hover/focus selectors' specificity, or the
     translate(-50%) centering from those rules drags the panel off-screen. */
  .nav__item:hover > .nav__submenu,
  .nav__item:focus-within > .nav__submenu {
    transform: none;
  }

  .nav__submenu[data-open='true'] { display: block; }

  .nav__sublink { padding: .85rem var(--gutter) .85rem calc(var(--gutter) + 1rem); }
}

/* ---------------------------------------------------------------
   Sections
---------------------------------------------------------------- */
/* No top padding on main — the hero's gradient runs up behind the transparent
   bar. Any page whose first block isn't a hero gets the clearance instead. */
main > .section:first-child { padding-top: calc(var(--nav-h) + clamp(2rem, 6vw, 4rem)); }

.section {
  padding-block: clamp(2.75rem, 7vw, 5.5rem);
  background: var(--white);
}
/* The modifier classes are kept as no-ops: the artwork wash inherits its
   colour from the section, and that colour is now white everywhere. */

main > .section { position: relative; }

/* Divider sits at the section boundary but only spans the content column,
   matching the rule that used to run under the opening quotes. */
main > .section + .section:not(.section--no-rule)::after {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  translate: -50% 0;
  width: min(var(--container), 100% - (2 * var(--gutter)));
  height: 1px;
  background: rgba(0, 0, 0, .12);
}

.hero {
  position: relative;
  padding-top: calc(var(--nav-h) + clamp(2.5rem, 8vw, 6rem));
  padding-bottom: clamp(2.75rem, 9vw, 6.5rem);
  background:
    radial-gradient(52% 78% at 2% 10%, rgba(242, 176, 128, .95) 0%, rgba(242, 176, 128, 0) 72%),
    radial-gradient(54% 85% at 52% 108%, rgba(74, 240, 224, 1) 0%, rgba(74, 240, 224, 0) 70%),
    #f2f2f1;
}

.hero__title {
  /* the large size used to live on .hero--art, so only Learn got it */
  font-size: clamp(2.5rem, calc(1.4rem + 4.7vw), 4.5rem);
  margin-bottom: .75rem;
  letter-spacing: -.045em;
  line-height: 1.02;
}

.hero__meta {
  font-size: clamp(1rem, 1.5vw, 1.375rem);
  font-weight: 500;
  letter-spacing: 0;
}

.hero__date { color: var(--accent-deep); font-weight: 700; }

.section__title {
  font-size: var(--step-h2);
  margin-bottom: clamp(1.75rem, 4vw, 3rem);
}

.section__subtitle {
  font-size: var(--step-h3);
  margin-bottom: 1.25rem;
}

.prose { max-width: none; }
.prose strong { font-weight: 700; }

.prose a,
.inline-link {
  color: inherit;
  font-weight: 700;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .18em;
  transition: color .15s linear;
}

.prose a:hover,
.inline-link:hover { color: var(--accent-deep); }

.bio { margin-bottom: 1.75rem; }
.bio__contact { display: block; margin-top: .15rem; }
.bio__label { color: var(--ink-soft); }

/* ---------------------------------------------------------------
   Resource lists
---------------------------------------------------------------- */
/* Category accent colours — assigned per group via data-tone */
[data-tone='a'] { --tone: #c73d96; }
[data-tone='b'] { --tone: #34716f; }
[data-tone='c'] { --tone: #b8601f; }
[data-tone='d'] { --tone: #5b4bb8; }
[data-tone='e'] { --tone: #b03a2e; }

.resource-group { margin-bottom: clamp(2rem, 4.5vw, 3rem); }
.resource-group:last-child { margin-bottom: 0; }

.resource-cat {
  display: flex;
  align-items: baseline;
  gap: .5rem;
  margin-bottom: .9rem;
  padding-bottom: .5rem;
  border-bottom: 2px solid color-mix(in srgb, var(--tone) 28%, transparent);
  color: var(--tone);
  font-size: .8125rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
}

.resource-count {
  font-size: .6875rem;
  font-weight: 500;
  letter-spacing: 0;
  opacity: .55;
}

/* The dot lives on the li so the anchor can slide right on hover without
   dragging the dot along with it. The anchor is a block whose left padding
   covers the dot, so hovering or clicking the dot counts as the link —
   bullet and text always react together. --row-pad keeps the dot's vertical
   offset in step with the anchor's padding. */
.resource-list {
  --row-pad: 0rem;
  margin: 0;
  padding: 0;
  list-style: none;
  columns: 2;
  column-gap: 2.75rem;
}

@media (max-width: 760px) {
  .resource-list {
    columns: 1;
    --row-pad: .4rem;   /* roomier tap targets; the dot tracks it via --row-pad */
  }
  .resource-list li { margin-bottom: .2rem; }
}

.resource-list li {
  position: relative;
  break-inside: avoid;
  margin-bottom: .55rem;
}

.resource-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: calc(var(--row-pad) + .62em);
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--tone);
  /* The dot paints above the anchor, so without this it swallows the pointer
     and the bullet would highlight while the text stayed put. */
  pointer-events: none;
  transition: transform .18s var(--ease);
}

.resource-list a {
  display: block;
  padding: var(--row-pad) 0 var(--row-pad) 1rem;
  color: var(--ink);
  font-size: var(--step-link);
  font-weight: 500;
  line-height: 1.45;
  text-decoration: none;
  transition: color .15s linear, transform .18s var(--ease);
}

.resource-list a::after {
  content: '↗';
  /* inline, not inline-block. An inline-block is a line-break opportunity, so
     a title that filled its line exactly pushed the arrow onto a line of its
     own and left what read as a blank line under the link. As plain inline
     text the arrow stays glued to the last word and wraps down with it. */
  display: inline;
  margin-left: .32em;
  font-size: .85em;
  opacity: 0;
  /* relative offsets, not a transform — transform does nothing on a
     non-replaced inline box, and these shift paint without reflowing text */
  position: relative;
  left: -3px;
  top: 2px;
  transition: opacity .18s var(--ease), left .18s var(--ease), top .18s var(--ease);
}

.resource-list a:hover,
.resource-list a:focus-visible {
  color: var(--tone);
  transform: translateX(5px);
}

.resource-list li:hover::before,
.resource-list li:focus-within::before { transform: scale(1.8); }

.resource-list a:hover::after,
.resource-list a:focus-visible::after { opacity: .8; left: 0; top: 0; }

/* Touch devices get no hover, so without the underline the arrow is the only
   thing marking these as links — keep it visible there permanently. */
@media (hover: none) {
  .resource-list a::after { opacity: .55; left: 0; top: 0; }
}

.resource-list cite { font-style: italic; }

/* ---------------------------------------------------------------
   Footer
---------------------------------------------------------------- */
.footer {
  background: var(--charcoal);
  color: var(--white);
  padding-block: clamp(.8rem, 1.5vw, 1rem);
}

.footer__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .75rem 1.5rem;
}

.footer__brand {
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: -0.01em;
}

.footer__link {
  font-size: .875rem;
  font-weight: 500;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .2em;
  text-decoration-color: rgba(255, 255, 255, .5);
}

.footer__link:hover { text-decoration-color: currentColor; }

/* ---------------------------------------------------------------
   Scroll reveal — content is visible by default, JS only animates in
---------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  .js-reveal [data-reveal] {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity .7s var(--ease), transform .7s var(--ease);
  }
  .js-reveal [data-reveal].is-visible {
    opacity: 1;
    transform: none;
  }
}

[id] { scroll-margin-top: calc(var(--nav-h) + 1.5rem); }

/* ---------------------------------------------------------------
   Learn page
---------------------------------------------------------------- */

/* Hero over artwork */
.hero--art {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: min(58svh, 420px);
  /* Pure CSS mesh — nothing to download, no banding, and no artwork to
     re-flatten if the palette moves. Red stands in for the anger theme. */
  background:
    radial-gradient(54% 72% at 16% 24%, rgba(201, 42, 30, .95) 0%, rgba(208, 48, 34, .88) 22%, rgba(214, 48, 34, 0) 72%),
    radial-gradient(42% 58% at 78% 8%, rgba(232, 137, 189, .80) 0%, rgba(232, 137, 189, 0) 70%),
    radial-gradient(52% 70% at 62% 98%, rgba(92, 232, 222, .90) 0%, rgba(92, 232, 222, 0) 68%),
    radial-gradient(40% 56% at 22% 92%, rgba(173, 151, 240, .72) 0%, rgba(173, 151, 240, 0) 70%),
    #f5f4f3;
  padding-top: calc(var(--nav-h) + clamp(2.5rem, 8vw, 6rem));
  padding-bottom: clamp(3.5rem, 9vw, 7rem);
}

/* faint grain, the one thing the old bitmap hero gave that flat CSS doesn't */
.hero--art::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .45;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.3'/%3E%3C/svg%3E");
}

/* Light wash so the dark title holds against the busiest parts of the gradient */
.hero--art::before {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, .22);
}

.hero--art > .container { position: relative; z-index: 1; }

.hero__title, .hero--art .hero__title {
  font-size: clamp(2.5rem, calc(1.4rem + 4.7vw), 4.5rem);
  margin-bottom: .75rem;
}

.hero__standfirst {
  max-width: min(72ch, 100%);
  font-size: clamp(1rem, calc(.93rem + .3vw), 1.1875rem);
  line-height: 1.5;
}

@keyframes cue {
  0%, 100% { transform: scaleY(.45); opacity: .4; }
  50%      { transform: scaleY(1);   opacity: 1; }
}

/* Section artwork — decorative, sits on the section's solid colour */
.section--art {
  position: relative;
  background-repeat: no-repeat;
  background-position: var(--art-pos, 50% 0%);
  background-size: var(--art-size, 90%) auto;
}

.section--art > .container { position: relative; z-index: 1; }

/* A wash in the section's own colour keeps the artwork present but lets the
   text carry. `inherit` picks up whichever section colour is in play.
   Stronger on narrow screens, where the art scales up behind the words. */
.section--art::before {
  content: '';
  position: absolute;
  inset: 0;
  background-color: inherit;
  opacity: .82;
}

@media (max-width: 860px) {
  .section--art::before { opacity: .88; }
}

/* The epigraphs lead straight into the intro rather than forming their own
   scroll stop, so they sit as a band above it with a rule between. */
.quote-overlap {
  position: relative;
  z-index: 2;
  margin-top: calc(-1 * clamp(2rem, 5vw, 3.5rem));
}

.quote-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: clamp(1rem, 2.5vw, 1.75rem);
}

.qcard {
  margin: 0;
  padding: clamp(1rem, 2.4vw, 1.4rem) clamp(1.1rem, 2.6vw, 1.6rem);
  border-radius: 6px;
  background: #fff;
  box-shadow: 0 8px 26px rgba(0, 0, 0, .12);
}

.qcard p { margin: 0 0 .25rem; font-size: .9375rem; font-weight: 700; line-height: 1.5; }
.qcard cite { font-style: normal; font-size: .8125rem; opacity: .7; }

/* "You are not alone" — the artwork sits behind the questions rather than
   below them, scaled down and softened so the text stays the focus. */
.not-alone { position: relative; }
}

/* "You are not alone" question list */
.question-list { list-style: none; margin: 0; padding: 0; max-width: none; }
.question-list li { margin-bottom: .85rem; }
.question-list strong { font-weight: 700; }

/* Quote cards over gradient artwork */
/* One card at a time. Scroll-snap does the work, so swipe on touch and
   trackpads is native; the buttons just scroll the viewport. */
.carousel { position: relative; }

/* The controls anchor to the card area, not the whole carousel — otherwise
   the dots row below drags them over the card's bottom edge. */
.carousel__stage { position: relative; }

.carousel__viewport {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  border-radius: 4px;
}

.carousel__viewport::-webkit-scrollbar { display: none; }
@media (prefers-reduced-motion: reduce) { .carousel__viewport { scroll-behavior: auto; } }

.quote-card {
  position: relative;
  flex: 0 0 100%;
  /* flex items default to min-width:auto, which lets a slide grow past its
     basis; <figure> also carries a default 40px side margin. Both throw the
     snap maths off. */
  min-width: 0;
  margin: 0;
  scroll-snap-align: center;
  scroll-snap-stop: always;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1.25rem;
  min-height: clamp(320px, 38vw, 430px);
  /* extra room at the bottom for the carousel controls sitting over the card */
  padding: clamp(1.75rem, 5vw, 3.25rem) clamp(1.5rem, 8vw, 6rem) clamp(4.25rem, 6.5vw, 5.25rem);
  background-size: cover;
  background-position: center;
  color: var(--white);
  text-align: center;
  overflow: hidden;
}

/* Wash over the artwork so the text carries rather than competes with it */
.quote-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, .34);
}

/* The controls sit inside the card, where the source button used to be */
.carousel__nav {
  position: absolute;
  left: 50%;
  bottom: clamp(1.5rem, 3.5vw, 2.5rem);
  transform: translateX(-50%);
  z-index: 2;
  display: flex;
  gap: .75rem;
}

.carousel__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  color: var(--white);
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
  transition: background .15s linear, transform .18s var(--ease), opacity .2s linear;
}

.carousel__btn:hover { background: var(--accent-deep); transform: scale(1.12); }
.carousel__btn[disabled] { opacity: .35; cursor: default; }
.carousel__btn[disabled]:hover { background: var(--accent); transform: none; }

.carousel__status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 1rem;
}

.carousel__dots { display: flex; flex-wrap: wrap; gap: .5rem; }

.carousel__dot {
  width: 9px;
  height: 9px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(26, 26, 26, .25);
  cursor: pointer;
  transition: background .15s linear, transform .18s var(--ease);
}

.carousel__dot[aria-selected='true'] { background: var(--accent); transform: scale(1.3); }
.carousel__dot:hover { background: var(--accent-deep); }

.carousel__count { margin: 0; font-size: .8125rem; opacity: .65; }

.quote-card > * { position: relative; }

.quote-card blockquote {
  margin: 0;
  font-size: clamp(.9375rem, calc(.88rem + .25vw), 1.0625rem);
  line-height: 1.5;
  text-shadow: 0 1px 10px rgba(0, 0, 0, .35);
}

.quote-card blockquote p:first-child { font-weight: 700; }

.quote-card__cite {
  display: block;
  margin-top: .75rem;
  font-size: .875em;
  font-style: normal;
  opacity: .92;
}

/* Same behaviour as the Resources links — no underline at rest, slides right
   with an arrow on hover — but tuned to read on a dark card. */
.quote-card__cite a {
  display: inline-block;
  color: inherit;
  text-decoration: none;
  transition: color .15s linear, transform .18s var(--ease);
}

.quote-card__cite a::after {
  content: '↗';
  display: inline-block;
  margin-left: .32em;
  font-size: .9em;
  opacity: 0;
  transform: translate(-3px, 2px);
  transition: opacity .18s var(--ease), transform .18s var(--ease);
}

.quote-card__cite a:hover,
.quote-card__cite a:focus-visible {
  color: #ffc2e8;
  transform: translateX(5px);
}

.quote-card__cite a:hover::after,
.quote-card__cite a:focus-visible::after { opacity: 1; transform: none; }

@media (hover: none) {
  .quote-card__cite a::after { opacity: .7; transform: none; }
}

/* More / Less shift list. The grid lives on the <ul> with the <li>s set to
   display:contents, so all three columns line up across rows — sizing each
   row independently would stagger the arrows. */
.shift-list {
  display: grid;
  grid-template-columns: max-content auto max-content;
  justify-content: start;
  align-items: center;
  column-gap: clamp(.5rem, 1.5vw, .9rem);
  row-gap: .15rem;
  list-style: none;
  margin: var(--block-gap) 0;
  padding: 0;
}

.shift-list li { display: contents; }

.shift-list li > span {
  padding-block: .4rem;
  font-size: var(--step-body);
  text-align: right;          /* left column ends flush at the arrow */
}

.shift-list li > span:last-child { text-align: left; }

/* Arrows are an inline SVG sprite rather than images, so they stay crisp at
   any size and take their colour from here. */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.arrow {
  display: block;
  width: clamp(48px, 7.5vw, 80px);
  height: auto;
  aspect-ratio: 80 / 16;
  color: var(--accent);
  flex: none;
}

.arrow--annot { width: clamp(52px, 8vw, 86px); }

.arrow--curve {
  width: clamp(64px, 11vw, 104px);
  aspect-ratio: 104 / 54;
}

@media (max-width: 560px) {
  .shift-list { column-gap: .45rem; }
  .shift-list li > span { font-size: .9375rem; }
}

/* Scripture — reference hangs in the left margin, verse to the right, so a
   stack of verses reads as one passage with the references lining up. */
.scripture {
  display: grid;
  grid-template-columns: 8.5rem 1fr;
  gap: .45rem clamp(1rem, 2.5vw, 1.75rem);
  align-items: baseline;
  max-width: none;
  margin: var(--block-gap) var(--inset);
  padding: 0;
  border: 0;
}

.scripture cite {
  grid-column: 1;
  color: var(--teal);
  font-size: .72rem;
  font-style: normal;
  font-weight: 700;
  letter-spacing: .13em;
  text-transform: uppercase;
  text-align: right;
}

.scripture p {
  grid-column: 2;
  margin: 0;
  color: var(--teal);
  font-size: clamp(.9375rem, calc(.909rem + .121vw), 1rem);
  font-weight: 500;
  line-height: 1.55;
}

@media (max-width: 640px) {
  .scripture { grid-template-columns: 1fr; gap: .2rem; }
  .scripture cite { grid-column: 1; text-align: left; }
  .scripture p { grid-column: 1; margin-bottom: .9rem; }
  .scripture p:last-of-type { margin-bottom: 0; }
}

/* Pull quote — accent rule down the left */
.pullquote {
  margin: var(--block-gap) var(--inset);
  padding-left: clamp(1rem, 2.5vw, 1.75rem);
  border-left: 3px solid var(--accent);
  /* deliberately a step below body copy — the rule and weight carry it */
  font-size: clamp(.9375rem, calc(.909rem + .121vw), 1rem);
  font-weight: 700;
  line-height: 1.45;
}

/* A quotation running over two paragraphs: each paragraph opens with a quote
   mark, only the last one closes. Kill the UA margins and space them by hand. */
.pullquote p { margin: 0; }
.pullquote p + p { margin-top: .7rem; }

.pullquote cite {
  display: block;
  margin-top: .5rem;
  font-size: .7em;
  font-style: normal;
  font-weight: 500;
  opacity: .7;
}

/* Closing questions — the authors speaking, so no quote furniture */
.closing-question {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: clamp(.75rem, 2vw, 1.4rem);
  margin: var(--block-gap) 0;
}

/* adjacent margins collapse to the larger, so the first one's bottom margin
   has to come down too or the pair stays block-gap apart */
.closing-question:has(+ .closing-question) { margin-bottom: .6rem; }
.closing-question + .closing-question { margin-top: 0; }

.closing-question p {
  margin: 0;
  font-size: var(--step-body);
  font-weight: 500;
  line-height: 1.6;
}

.closing-question strong { font-weight: 700; }

@media (max-width: 560px) {
  .closing-question { gap: clamp(.6rem, 2.5vw, 1.1rem); }
}

/* Topic subheads that open a named idea */
.subhead-major {
  margin-top: clamp(2.75rem, 5.5vw, 4rem);
  margin-bottom: 1.1rem;
  font-size: clamp(1.5rem, calc(1.25rem + 1vw), 2.125rem);
  font-weight: 500;
  letter-spacing: -0.035em;
}

/* Contributor voice — the one place the handwritten face is used.
   Caveat runs small and is already slanted, so it is sized up and set
   upright rather than italic. */
.contributor {
  margin: var(--block-gap) var(--inset);
  font-family: 'Caveat', 'DM Sans', cursive;
  font-size: clamp(1.2rem, calc(1rem + .62vw), 1.6rem);
  line-height: 1.5;
}

.contributor strong { font-weight: 700; }
.contributor__attrib { display: block; margin-top: .75rem; font-weight: 700; }

/* Journal prompt */
.prompt {
  max-width: none;
  margin-block: clamp(1.5rem, 4vw, 2.5rem);
  padding: clamp(1.25rem, 3vw, 2rem);
  background: var(--gold-light);
  border: 1px solid rgba(180, 130, 50, .3);
  border-radius: 3px;
}

.prompt p { font-weight: 700; text-align: center; margin-bottom: 1.25rem; }

.prompt__line {
  height: 1px;
  margin-block: 1.6rem;
  background: rgba(0, 0, 0, .45);
}

/* ---------------------------------------------------------------
   Triggers bubble chart (replaces the old Flourish embed)
---------------------------------------------------------------- */
.bubbles { position: relative; }

.bubbles__svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;   /* bubbles lift slightly past the viewBox on hover */
}

.bub {
  /* --bx/--by come from the packing; --dx/--dy are the live hover nudge */
  transform-box: view-box;
  transform-origin: 0 0;
  transform:
    translate(calc(var(--bx) + var(--dx, 0px)), calc(var(--by) + var(--dy, 0px)))
    scale(var(--s, 1));
  transition: transform .45s var(--ease);
  cursor: pointer;
}

.bub circle { transition: filter .25s var(--ease); }
.bub:is(:hover, :focus-visible) circle { filter: drop-shadow(0 4px 14px rgba(0, 0, 0, .22)); }
.bub:focus { outline: none; }
.bub:focus-visible circle { stroke: var(--charcoal); stroke-width: 2; }

.bub__label--out { fill: var(--ink); font-weight: 600; }

.bub__label {
  fill: #1a1a1a;
  font-family: 'DM Sans', system-ui, sans-serif;
  font-weight: 500;
  pointer-events: none;
  user-select: none;
}

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

/* Tooltip is anchored to its bubble rather than chasing the pointer, which
   keeps it from jittering as the cursor moves inside a circle. */
.bubbles__tip,
.bars__tip {
  position: absolute;
  z-index: 3;
  /* An absolutely positioned shrink-to-fit box is limited by the containing
     block's width minus its own left offset, so the tooltip narrowed into a
     tall column as the pointer approached the right edge. max-content ignores
     the available space, so the box keeps one shape wherever it is placed and
     the JS flips it to the other side of the cursor instead. */
  width: max-content;
  max-width: min(22rem, 70vw);
  padding: .7rem .85rem;
  border: 1px solid rgba(0, 0, 0, .16);
  border-radius: 6px;
  background: #fff;
  color: var(--ink);
  box-shadow: 0 6px 22px rgba(0, 0, 0, .13);
  font-size: .8125rem;
  line-height: 1.45;
  pointer-events: none;
  opacity: 0;
  transition: opacity .18s var(--ease);
}

.bubbles__tip[data-show='true'],
.bars__tip[data-show='true'] { opacity: 1; }
.bubbles__tip p,
.bars__tip p { margin: 0; }
.bubbles__tip-head,
.bars__tip-head { font-weight: 700; margin-bottom: .3rem !important; }
.bubbles__tip-needs,
.bars__tip-need { opacity: .75; }

/* The same detail as the tooltip, but reachable by keyboard and screen
   reader — SVG groups never fire focus events, so the chart itself cannot
   carry this content on its own. */
.trigger-key { margin-top: 1rem; font-size: .875rem; }

.trigger-key summary {
  cursor: pointer;
  color: var(--accent-deep);
  font-weight: 700;
}

.trigger-key summary:hover { text-decoration: underline; }

.trigger-key__list { margin: .9rem 0 0; }

.trigger-key__row {
  display: grid;
  grid-template-columns: 11rem 1fr;
  gap: .25rem 1rem;
  padding-block: .5rem;
  border-top: 1px solid rgba(0, 0, 0, .09);
}

.trigger-key__row dt { font-weight: 700; }
.trigger-key__row dt span { display: block; font-weight: 500; opacity: .55; font-size: .8125rem; }
.trigger-key__row dd { margin: 0; opacity: .8; line-height: 1.5; }

@media (max-width: 640px) {
  .trigger-key__row { grid-template-columns: 1fr; }
}

/* Two-column prose split */
.split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: clamp(1.25rem, 3vw, 2.5rem);
}

.split h3 { font-size: var(--step-h3); font-weight: 700; margin-bottom: .5rem; }

/* Shared spacing helpers, so vertical rhythm comes from two values rather
   than ad-hoc margins scattered through the markup. */
.block-gap { margin-top: var(--block-gap); }
.topic-break { margin-top: clamp(2.5rem, 5vw, 3.75rem); }
.cta-wrap { margin-top: clamp(2.25rem, 4.5vw, 3rem); }

/* Aim rows — arrow sits right against its text */
.aim {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: start;
  gap: clamp(.65rem, 1.6vw, 1.1rem);
  margin-top: var(--block-gap);
}

.aim .arrow { margin-top: .45em; }

@media (max-width: 560px) {
  .aim { grid-template-columns: 1fr; gap: .4rem; }
}

/* Figure with decorative arrow.

   Three rows. The chart and arrow span rows 1-2 and are centred, so grid
   splits that height between the two rows and the boundary falls on the
   chart's middle. The heading sits at the bottom of row 1 and the disclosure's
   summary at the top of row 2, so the pair meets on that line and reads as
   centred beside the chart. The open list is row 3, which nothing else
   occupies — so opening it only grows downward and the chart, arrow, heading
   and summary all stay exactly where they are.

   The list spans the full width on purpose: eleven rows of trigger text would
   be cramped in a third of the measure. */
.annotated {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  grid-template-rows: auto auto auto;
  gap: clamp(.75rem, 2vw, 1.5rem);
}

.annotated > .bubbles,
.annotated > .arrow--annot {
  grid-row: 1 / span 2;
  align-self: center;
}

.annotated > .bubbles { grid-column: 1; }
.annotated > .arrow--annot { grid-column: 2; }

.annotated > .section__subtitle {
  grid-row: 1;
  grid-column: 3;
  align-self: end;
  margin: 0;
}

.annotated > .trigger-key {
  grid-row: 2 / span 2;
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  grid-template-rows: subgrid;
  margin-top: 0;
}

.annotated > .trigger-key > summary {
  grid-row: 1;
  grid-column: 3;
  align-self: start;
}

/* Chrome wraps everything after the summary in a ::details-content box, so
   that pseudo-element is the real grid item and placing the list itself does
   nothing. Place both: the pseudo where it exists, the list where it doesn't. */
.annotated > .trigger-key::details-content { grid-row: 2; grid-column: 1 / -1; }
.annotated > .trigger-key > .trigger-key__list { grid-column: 1 / -1; }

/* width is set on .arrow / .arrow--annot above */

@media (max-width: 760px) {
  .annotated { grid-template-columns: 1fr; }
  .annotated .arrow--annot { display: none; }
  /* single column, and the sentence leads rather than follows: with no arrow
     to tie it to the chart it has to sit where it will be read first */
  .annotated > .section__subtitle { grid-row: 1; grid-column: 1; align-self: auto; margin-bottom: 1.1rem; }
  .annotated > .bubbles { grid-row: 2; grid-column: 1; }
  .annotated > .trigger-key { grid-row: 3; grid-column: 1; display: block; }
}

/* Next-page call to action */
.cta-next {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  padding: .85rem 1.6rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--white);
  font-size: var(--step-link);
  font-weight: 700;
  text-decoration: none;
  transition: background .15s linear, transform .18s var(--ease);
}

.cta-next:hover { background: var(--accent-deep); transform: translateX(4px); }

/* ===========================================================================
   Reflect page
   ======================================================================== */

/* The Vev original opened with a 6.5MB rainbow star. These gradients take its
   palette — magenta, violet, blue, yellow, orange — so the page keeps its own
   identity without the download. */
.hero--reflect {
  background:
    radial-gradient(44% 60% at 26% 6%, rgba(233, 56, 140, .82) 0%, rgba(233, 56, 140, 0) 70%),
    radial-gradient(46% 64% at 84% 24%, rgba(138, 94, 232, .74) 0%, rgba(138, 94, 232, 0) 70%),
    radial-gradient(44% 62% at 70% 102%, rgba(78, 170, 240, .72) 0%, rgba(78, 170, 240, 0) 68%),
    radial-gradient(42% 58% at 14% 94%, rgba(248, 206, 74, .80) 0%, rgba(248, 206, 74, 0) 70%),
    radial-gradient(38% 54% at 2% 48%, rgba(242, 130, 48, .70) 0%, rgba(242, 130, 48, 0) 72%),
    #f5f4f3;
}

/* A figure carried by one number. */
.statline {
  margin: var(--block-gap) var(--inset);
  font-size: var(--step-body);
  line-height: 1.5;
}

.statline__figure {
  display: block;
  margin-bottom: .2rem;
  font-size: clamp(2.25rem, calc(1.6rem + 2.8vw), 3.5rem);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1;
  color: var(--accent-deep);
}

.statline__figure a { color: inherit; text-decoration: none; }
.statline__figure a:hover { text-decoration: underline; }
.statline cite { display: block; margin-top: .5rem; font-style: normal; font-size: .8125rem; opacity: .7; }

/* Two quotes set against each other. The number is the only furniture that
   says they are a pair, so it sits in the margin rather than in the text. */
.quote-pair { margin: var(--block-gap) 0; }

.quote-pair .pullquote {
  display: grid;
  grid-template-columns: 2.25rem 1fr;
  gap: 0 clamp(.5rem, 1.5vw, .9rem);
  border-left: 0;
  padding-left: 0;
}

.quote-pair .pullquote::before {
  content: counter(qp);
  grid-row: 1 / span 2;
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1;
  color: var(--accent);
}

.quote-pair { counter-reset: qp; }
.quote-pair .pullquote { counter-increment: qp; }
.quote-pair .pullquote + .pullquote { margin-top: var(--block-gap); }

@media (max-width: 560px) {
  .quote-pair .pullquote { grid-template-columns: 1.5rem 1fr; }
}

/* Tendency on the left, the correction on the right. Unlike .shift-list both
   sides here run to several lines, so the columns are fluid, not max-content. */
.swap {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: clamp(.65rem, 2vw, 1.25rem);
  /* inset from both edges like the quotes and scripture, so the pair reads as
     a set-apart block rather than more body copy */
  margin: var(--block-gap) var(--inset);
}

.swap + .swap { margin-top: calc(-1 * var(--block-gap) + clamp(1rem, 2.5vw, 1.75rem)); }
.swap p { margin: 0; font-size: var(--step-body); line-height: 1.5; }

@media (max-width: 640px) {
  .swap { grid-template-columns: 1fr; gap: .4rem; }
  /* pointing down is the only honest direction once the columns stack */
  .swap .arrow { transform: rotate(90deg); margin-inline: auto; }
}

/* The physical-neglect cycle, drawn as a ring the way the original did.
   Three steps sit at 12, 4 and 8 o'clock on one circle, joined by three arcs
   of that same circle so the path really is circular rather than three
   separate arrows. The ring turns slowly, which is the point of the diagram. */
.cycle {
  position: relative;
  aspect-ratio: 1;
  width: min(100%, 30rem);
  margin: var(--block-gap) auto;
}

.cycle__ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  color: var(--accent);
  overflow: visible;
}

/* The same curved arrow the rest of the site uses, placed three times around
   the ring. Each one draws itself on: the line first, then the head, and the
   three stagger clockwise so the eye follows the cycle round. */
.cycle__arrow {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Without JS nothing adds .is-visible, so the arrows must be drawn already —
   the dash offset is only applied once the reveal script is running. */
body.js-reveal .cycle__line { stroke-dasharray: 92; stroke-dashoffset: 92; }
body.js-reveal .cycle__head { stroke-dasharray: 32; stroke-dashoffset: 32; }

body.js-reveal .cycle.is-visible .cycle__line { animation: cycle-draw .55s ease forwards; }
body.js-reveal .cycle.is-visible .cycle__head { animation: cycle-draw .22s ease forwards; }

/* These have to outrank the shorthand above, which resets animation-delay */
body.js-reveal .cycle.is-visible .cycle__arrow:nth-of-type(1) .cycle__line { animation-delay: .05s; }
body.js-reveal .cycle.is-visible .cycle__arrow:nth-of-type(1) .cycle__head { animation-delay: .55s; }
body.js-reveal .cycle.is-visible .cycle__arrow:nth-of-type(2) .cycle__line { animation-delay: .75s; }
body.js-reveal .cycle.is-visible .cycle__arrow:nth-of-type(2) .cycle__head { animation-delay: 1.25s; }
body.js-reveal .cycle.is-visible .cycle__arrow:nth-of-type(3) .cycle__line { animation-delay: 1.45s; }
body.js-reveal .cycle.is-visible .cycle__arrow:nth-of-type(3) .cycle__head { animation-delay: 1.95s; }

@keyframes cycle-draw { to { stroke-dashoffset: 0; } }

@media (prefers-reduced-motion: reduce) {
  body.js-reveal .cycle__line,
  body.js-reveal .cycle__head { stroke-dashoffset: 0; animation: none; }
}

.cycle__step {
  position: absolute;
  /* 40% left the two lower cards almost touching, which squeezed the bottom
     arrow against one of them while the other two sat clear */
  width: 32%;
  padding: clamp(.6rem, 1.8vw, .85rem) clamp(.7rem, 2vw, 1rem);
  border-radius: 10px;
  background: var(--step-tint, var(--white));
  box-shadow: 0 4px 18px rgba(0, 0, 0, .08);
  text-align: center;
  font-size: clamp(.8125rem, calc(.77rem + .19vw), .9375rem);
  line-height: 1.35;
}

.cycle__step p { margin: .35rem 0 0; }

/* 12, 4 and 8 o'clock on a circle of radius 45 in a 100-unit box */
.cycle__step--a { left: 50%; top: 5%;  --pos: translate(-50%, -50%); --step-tint: #fde4d2;
                  --out: translate(0, -7px); }
.cycle__step--b { left: 89%; top: 72%; --pos: translate(-50%, -50%); --step-tint: #fbd8e8;
                  --out: translate(6px, 4px); }
.cycle__step--c { left: 11%; top: 72%; --pos: translate(-50%, -50%); --step-tint: #e3e0fb;
                  --out: translate(-6px, 4px); }

/* Below phone width the ring has no room, so the steps become a plain column
   and a bracket carries the return instead. */
@media (max-width: 560px) {
  .cycle {
    aspect-ratio: auto;
    width: 100%;
    display: grid;
    gap: clamp(1.5rem, 6vw, 2rem);
    padding-left: clamp(1.5rem, 7vw, 2.25rem);
  }
  .cycle__ring { display: none; }
  .cycle__step {
    position: static;
    width: auto;
    --pos: translate(0, 0);
    text-align: left;
  }
  .cycle__step p { margin: 0; }

  .cycle::before {
    content: '';
    position: absolute;
    left: 0;
    top: 1.9rem;
    bottom: 2.6rem;
    width: clamp(.9rem, 3.5vw, 1.4rem);
    border: 1.5px solid var(--accent);
    border-right: 0;
    border-radius: 10px 0 0 10px;
  }

  .cycle::after {
    content: '';
    position: absolute;
    left: clamp(.9rem, 3.5vw, 1.4rem);
    top: 1.9rem;
    width: 0;
    height: 0;
    border-top: 4.5px solid transparent;
    border-bottom: 4.5px solid transparent;
    border-left: 7px solid var(--accent);
    transform: translate(-1px, -4.5px);
  }
}

/* Numbered tips */
.tip-list { margin: var(--block-gap) 0; padding-left: 1.3rem; }
.tip-list li { margin-bottom: .6rem; font-size: var(--step-body); line-height: 1.55; }
.tip-list li::marker { font-weight: 700; color: var(--accent-deep); }

/* A row of verse references to look up, rather than a quoted verse — teal to
   match scripture, but without the hanging-citation grid. */
.verse-refs {
  margin: var(--block-gap) var(--inset);
  color: var(--teal);
  font-size: var(--step-body);
  font-weight: 500;
  line-height: 1.6;
}

/* Arrows leading into the reflection questions */
.question-list--arrows li {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: clamp(.65rem, 1.8vw, 1.1rem);
}

/* These stay side by side at every width, unlike .aim — the questions are
   short enough that the arrow costs one extra wrapped line at most, and
   stacking left the arrow marooned on a row of its own. */

/* Stacked column chart — one block per logged event, so the column height is
   literally a count and the blocks stay individually hoverable. */
.bars { position: relative; margin: var(--block-gap) 0; }
.bars__svg { display: block; width: 100%; height: auto; overflow: visible; }

.bars__seg { cursor: default; transition: fill-opacity .12s linear; }
/* driven by a class rather than :hover, so a tap dims the rest on touch too */
.bars.is-focused .bars__seg { fill-opacity: .3; }
.bars.is-focused .bars__seg[data-on] { fill-opacity: 1; }

.bars__grid { stroke: rgba(0, 0, 0, .08); stroke-width: 1; }
.bars__axis { stroke: rgba(0, 0, 0, .25); stroke-width: 1; }

.bars__ytick,
.bars__xtick,
.bars__total {
  font-family: 'DM Sans', system-ui, sans-serif;
  fill: var(--ink);
}

.bars__ytick { font-size: 10px; opacity: .55; }
.bars__xtick { font-size: 12px; font-weight: 700; }
.bars__total { font-size: 11px; font-weight: 700; opacity: .75; }

.bars__caption {
  margin-top: .6rem;
  font-size: .8125rem;
  text-align: center;
  opacity: .65;
}

/* The chart and the sentence that reads it. Side by side while there is room,
   stacked below phone width where a half-width chart would be unreadable. */
.chart-row {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) auto minmax(0, .85fr);
  align-items: center;
  gap: clamp(.75rem, 2.5vw, 1.75rem);
}

/* points back at the chart the sentence is reading */
.chart-row__arrow { align-self: center; }

.chart-row__note {
  font-size: var(--step-h3);
  font-weight: 400;
  margin: 0;
}

@media (max-width: 720px) {
  .chart-row { grid-template-columns: 1fr; }
  .chart-row__arrow { display: none; }
}

/* The four "masking" sections as tabs. The strip is built by JS and starts
   hidden, so without JS the page is simply the four headings and all their
   content in a row — nothing is lost, and nothing has to be kept in sync
   between the markup and the labels. */
.masking__tabs { display: none; flex-wrap: wrap; gap: .5rem; margin-bottom: 1.6rem; }
.masking__lead { display: none; margin-top: clamp(2.25rem, 5vw, 3.5rem); font-size: var(--step-body); opacity: .6; margin-bottom: .6rem; }

.masking.is-tabbed .masking__tabs { display: flex; }
.masking.is-tabbed .masking__lead { display: block; }
/* the panel keeps its full heading; it just sits tight under the strip rather
   than carrying .subhead-major's usual space above it */
.masking.is-tabbed .masking__panel .subhead-major { margin-top: 0; margin-bottom: 1rem; }

.masking__tab {
  border: 1px solid rgba(0, 0, 0, .18);
  border-radius: 999px;
  background: var(--white);
  padding: .5rem 1rem;
  font: inherit;
  font-size: .875rem;
  color: var(--ink);
  cursor: pointer;
  transition: background .15s linear, color .15s linear, border-color .15s linear;
}

.masking__tab:hover { border-color: var(--accent); color: var(--accent-deep); }

.masking__tab[aria-selected="true"] {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--white);
  font-weight: 700;
}

.masking.is-tabbed .masking__panel { padding-top: .25rem; }
.masking.is-tabbed .masking__panel > *:first-child { margin-top: 0; }
.masking__panel:focus { outline: none; }
.masking__panel:focus-visible { outline: 2px solid var(--accent); outline-offset: 6px; }

/* ===========================================================================
   Try page
   ======================================================================== */

/* Warm mesh, taking its palette from this page's own artwork. */
.hero--try {
  background:
    radial-gradient(44% 60% at 14% 10%, rgba(248, 196, 74, .82) 0%, rgba(248, 196, 74, 0) 70%),
    radial-gradient(46% 62% at 72% 4%, rgba(240, 110, 92, .78) 0%, rgba(240, 110, 92, 0) 70%),
    radial-gradient(44% 60% at 92% 56%, rgba(214, 74, 150, .66) 0%, rgba(214, 74, 150, 0) 70%),
    radial-gradient(44% 62% at 34% 100%, rgba(60, 190, 190, .74) 0%, rgba(60, 190, 190, 0) 68%),
    #f5f4f3;
}

.step-num {
  display: grid;
  place-items: center;
  flex: none;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--white);
  font-size: .875rem;
}

.shift-list--numbered { counter-reset: shift; }
.shift-list--numbered li > span:first-child::before {
  counter-increment: shift;
  content: counter(shift) '. ';
  font-weight: 700;
  color: var(--accent);
}

/* Judgment versus neutral language. The examples are things people say to a
   child, so they are set as dialogue: the judging line, then the neutral reply
   indented under it. The label sits in the margin on wide screens and drops
   under the line when there is no margin to put it in. */
.says { margin: var(--block-gap) 0; }
.says__row + .says__row { margin-top: clamp(1.5rem, 3.5vw, 2.25rem); }

.says__scene {
  margin: 0 0 .7rem;
  font-size: .8125rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink);
}

.says__line {
  position: relative;
  max-width: 38rem;
  margin: 0;
  padding: .8rem 1.1rem;
  border-radius: 16px;
  border-bottom-left-radius: 4px;
  font-size: var(--step-link);
  line-height: 1.45;
}

.says__line + .says__line { margin-top: .6rem; }
.says__line--judge { background: #efeeec; }
.says__line--neutral { background: #fbdcea; margin-left: clamp(1rem, 4vw, 3rem); }

.says__line::after {
  position: absolute;
  top: 50%;
  right: calc(100% + .6rem);
  transform: translateY(-50%);
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.says__line--judge::after { content: 'judging'; color: #7a7a7a; }
.says__line--neutral::after { content: 'neutral'; color: var(--accent-deep); }

@media (max-width: 760px) {
  .says__line::after { position: static; transform: none; display: block; margin-top: .3rem; opacity: .85; }
  .says__line--neutral { margin-left: 0; }
}

/* Four-step variant of the cycle: steps at 12, 3, 6 and 9 o'clock. */
.cycle--4 .cycle__step--n { left: 50%; top: 4%;  --pos: translate(-50%, -50%); --step-tint: #fde4d2;  --out: translate(0, -7px); }
.cycle--4 .cycle__step--e { left: 96%; top: 50%; --pos: translate(-50%, -50%); --step-tint: #fbd8e8;  --out: translate(7px, 0); }
.cycle--4 .cycle__step--s { left: 50%; top: 96%; --pos: translate(-50%, -50%); --step-tint: #e3e0fb;  --out: translate(0, 7px); }
.cycle--4 .cycle__step--w { left: 4%;  top: 50%; --pos: translate(-50%, -50%); --step-tint: #d6eef0;  --out: translate(-7px, 0); }

@media (max-width: 560px) {
  .cycle--4 .cycle__step--n,
  .cycle--4 .cycle__step--e,
  .cycle--4 .cycle__step--s,
  .cycle--4 .cycle__step--w { left: auto; top: auto; --pos: translate(0, 0); }
}

/* Counselor directories and the like: the resource-list look, laid out inline */
.resource-list--inline { columns: 1; }

/* Share row */
.share { margin-top: var(--block-gap); }
.share__title { font-size: var(--step-h3); margin-bottom: .75rem; }
.share__list { display: flex; flex-wrap: wrap; gap: .5rem; list-style: none; margin: 0; padding: 0; }

.share__link {
  display: inline-block;
  border: 1px solid transparent;
  background: var(--grey-light);
  border-radius: 999px;
  padding: .45rem 1.1rem;
  font-size: .875rem;
  color: var(--ink);
  text-decoration: none;
  transition: border-color .15s linear, color .15s linear;
}

.share__link:hover { border-color: var(--accent); color: var(--accent-deep); background: var(--white); }

/* A cartoon we point to rather than reproduce. The drawing is Sofia Warren's
   and belongs to The New Yorker, so the frame carries only the caption, the
   credit and a link out. If the cartoon is ever licensed for this site, the
   artwork drops straight into this frame. */
.cartoon-ref {
  margin: var(--block-gap) var(--inset);
  padding: 0;
  text-align: center;
}

.cartoon-ref__frame { max-width: 400px; margin: 0 auto; }

.cartoon-ref__embed {
  display: block;
  width: 100%;
  height: 560px;
  border: 0;
  background: var(--white);
}

.cartoon-ref__credit {
  margin-top: clamp(.9rem, 2.4vw, 1.3rem);
  font-size: .8125rem;
  opacity: .72;
}

.cartoon-ref__credit strong { font-weight: 700; }

/* The three communication steps as an accordion, with the shift list above
   acting as the way in: same numbers, and each row opens its step. */
.shift-list--numbered a {
  display: contents;
  color: inherit;
  text-decoration: none;
}

.shift-list--numbered li > a > span { padding-block: .4rem; font-size: var(--step-body); text-align: right; }
.shift-list--numbered li > a > span:last-child { text-align: left; }
.shift-list--numbered li:hover > a > span,
.shift-list--numbered li:focus-within > a > span { color: var(--accent-deep); }
.shift-list--numbered li:hover .arrow,
.shift-list--numbered li:focus-within .arrow { color: var(--accent-deep); }

/* the number gets a column of its own, otherwise right-aligning the left-hand
   phrase staggers the numbers down the list */
.shift-list--numbered { grid-template-columns: auto max-content auto max-content; }

.shift-list--numbered li > a::before {
  counter-increment: shift;
  content: counter(shift) '.';
  padding-block: .4rem;
  font-size: var(--step-body);
  font-weight: 700;
  color: var(--accent);
}

.steps { margin-top: var(--block-gap); }

.step { border-top: 1px solid rgba(0, 0, 0, .14); scroll-margin-top: 5rem; }
/* the last step closes the group at the same rhythm as the rules between the
   others; the section after it carries .section--no-rule so the divider that
   used to sit below this doesn't read as a second bar */
.step:last-of-type { border-bottom: 1px solid rgba(0, 0, 0, .14); }

.step > summary {
  display: flex;
  align-items: center;
  gap: clamp(.7rem, 2vw, 1rem);
  padding: clamp(1rem, 2.5vw, 1.3rem) 0;
  cursor: pointer;
  list-style: none;
}

.step > summary::-webkit-details-marker { display: none; }

.step > summary::after {
  content: '+';
  margin-left: auto;
  padding-left: .75rem;
  font-size: 1.4rem;
  font-weight: 700;
  line-height: 1;
  color: var(--accent);
}

.step[open] > summary::after { content: '–'; }

.step__names { display: grid; gap: .1rem; }
.step__shift { font-size: .8125rem; font-weight: 700; color: var(--accent-deep); }

.step__title {
  font-size: clamp(1.25rem, calc(1.1rem + .6vw), 1.6rem);
  font-weight: 500;
  letter-spacing: -.03em;
}

.step__body { padding-bottom: clamp(1rem, 3vw, 1.75rem); }
.step__body > *:first-child { margin-top: 0; }

/* the step that was jumped to, so the link above clearly landed somewhere */
.step.is-target > summary { background: var(--gold-light); }

/* The two dopamine cycles read against each other: the first is the one to get
   out of, the second the one to move toward. Warm reds for the first, cool
   blues and violets for the second, in the ring's backdrop and its cards. */
.cycle--hot,
.cycle--calm {
  padding: clamp(1rem, 3vw, 2rem);
  border-radius: 50%;
}

.cycle--hot {
  background: radial-gradient(circle at 50% 50%,
    rgba(232, 96, 72, .20) 0%,
    rgba(238, 140, 110, .13) 45%,
    rgba(240, 180, 150, 0) 72%);
}

.cycle--calm {
  background: radial-gradient(circle at 50% 50%,
    rgba(120, 150, 232, .20) 0%,
    rgba(150, 140, 230, .13) 45%,
    rgba(170, 170, 235, 0) 72%);
}

.cycle--hot .cycle__step--n { --step-tint: #fbd9cc; }
.cycle--hot .cycle__step--e { --step-tint: #f9cbbb; }
.cycle--hot .cycle__step--s { --step-tint: #f7bdab; }
.cycle--hot .cycle__step--w { --step-tint: #f5b0a0; }

.cycle--calm .cycle__step--n { --step-tint: #e7e0fb; }
.cycle--calm .cycle__step--e { --step-tint: #d3d9fa; }
.cycle--calm .cycle__step--s { --step-tint: #cbe4f7; }
.cycle--calm .cycle__step--w { --step-tint: #c7eff0; }

/* a circular wash needs no shape once the ring is gone */
@media (max-width: 560px) {
  .cycle--hot, .cycle--calm { border-radius: 14px; padding: clamp(1rem, 4vw, 1.5rem); }
}

/* the second cycle leads straight into body copy, so it needs its own room */
.cycle--calm { margin-bottom: calc(var(--block-gap) * 1.8); }

/* Avoid orphans. text-wrap: pretty keeps a last line from being a single word,
   balance evens out the lines of a heading. Both are progressive — anything
   that doesn't support them just wraps the way it did before. */
p, li, dd, figcaption, blockquote, .prose, .says__line { text-wrap: pretty; }

/* the standfirst is a paragraph, not a heading: balance would even the lines
   by narrowing the measure, which is the opposite of what it wants */
.hero__standfirst { text-wrap: pretty; }

/* The Grove invitation */
.grove {
  margin: var(--block-gap) 0 0;
  padding: clamp(1.4rem, 4vw, 2.4rem);
  border-radius: 14px;
  text-align: center;
  background:
    radial-gradient(70% 120% at 18% 0%, rgba(232, 137, 189, .30) 0%, rgba(232, 137, 189, 0) 70%),
    radial-gradient(70% 120% at 86% 100%, rgba(92, 232, 222, .32) 0%, rgba(92, 232, 222, 0) 70%),
    var(--gold-light);
}

.grove__text {
  max-width: 48ch;
  margin: 0 auto;
  font-size: var(--step-body);
  line-height: 1.5;
}

.grove__cta {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  margin-top: 1.1rem;
  padding: .8rem 1.6rem;
  border-radius: 999px;
  background: var(--charcoal);
  color: var(--white);
  font-size: var(--step-link);
  font-weight: 700;
  text-decoration: none;
  transition: background .15s linear, transform .18s var(--ease);
}

.grove__cta:hover { background: var(--accent-deep); transform: translateY(-2px); }

/* Embedded clip, cued to the passage the text points at */
.clip { margin: var(--block-gap) 0; }

.clip__frame {
  max-width: 44rem;
  margin: 0 auto;
  aspect-ratio: 16 / 9;
  border-radius: 8px;
  overflow: hidden;
  background: var(--charcoal);
}

.clip__embed { display: block; width: 100%; height: 100%; border: 0; }

.clip__credit {
  max-width: 44rem;
  margin: .7rem auto 0;
  font-size: .8125rem;
  text-align: center;
  opacity: .75;
}

/* Cards lift a little under the pointer. `scale` is its own property, so it
   composes with the translate that positions each card on the ring instead of
   overwriting it. */
.cycle__step {
  /* position and nudge ride in one chain: the position is a percentage of the
     card's own box, so anything applied after it would drag the card off the
     ring */
  transform: var(--pos, translate(0, 0)) var(--nudge, translate(0, 0));
  transition: transform .22s var(--ease), box-shadow .22s var(--ease);
}

/* Only the card under the pointer moves: it eases out along its own radius. */
.cycle__step:hover { --nudge: var(--out); z-index: 2; box-shadow: 0 8px 22px rgba(0, 0, 0, .13); }

@media (prefers-reduced-motion: reduce) {
  .cycle__step { transition: none; }
  .cycle__step:hover { --nudge: translate(0, 0); }
}

/* Section boundaries were varying from 150px to 260px because whatever
   happened to be first or last inside a section added its own margin on top of
   the section's padding. The padding alone governs the gap now. */
.section > .container > *:first-child,
.section > .container > *:first-child *:first-child { margin-top: 0; }

.section > .container > *:last-child,
.section > .container > *:last-child *:last-child { margin-bottom: 0; }

/* Zeroing the outer children is not enough on its own: a margin deeper inside
   can still collapse out through the container and reappear as extra gap.
   flow-root makes the container its own formatting context, so nothing escapes
   and the padding is the only thing setting the distance. */
.section > .container { display: flow-root; }

/* The accordion draws its own rule at the bottom of the last step, and that
   rule reads as the break between sections. So the section ends there and the
   next one supplies the usual single gap, rather than both adding their half. */
.section--ends-on-rule { padding-bottom: 0; }

/* The caret only means something where a submenu can be toggled. */
@media (max-width: 860px) {
  .nav__caret { display: none; }
}

/* Arrows stay beside their text at every width — stacking left the arrow
   stranded on a line of its own. */
@media (max-width: 560px) {
  .aim { grid-template-columns: auto 1fr; gap: clamp(.6rem, 2.5vw, 1.1rem); }
}

/* Background artwork should read as background on a phone, not as a stray
   picture, so it spans the full width there. The per-section size is an inline
   custom property, which no rule can outrank, so this sets background-size
   itself. .section--art-keep opts a section out. */
@media (max-width: 760px) {
  /* Deliberately wider than the screen so the artwork bleeds off both sides
     rather than sitting in the middle of the column. The section is exactly
     the width of the screen, so the only place it can be cut is the screen
     edge — never partway in. */
  .section--art:not(.section--art-keep) { background-size: 150% auto; }

  /* This section's artwork landed behind the embedded cartoon on a phone,
     where the column is tall enough to put the two in the same place. The
     inline --art-pos cannot be overridden, so set the position directly. */
  #eGcg0D8jIK- { background-position: 96% 88%; }
}

/* The tendency/consider pairs: an arrow pointing sideways makes no sense once
   the two halves stack, so on a phone the correction hangs off a bar instead. */
@media (max-width: 640px) {
  .swap { grid-template-columns: 1fr; gap: 0; }
  .swap .arrow { display: none; }
  .swap > p:last-child {
    margin-top: .55rem;
    padding-left: clamp(.8rem, 3.5vw, 1.1rem);
    border-left: 3px solid var(--accent);
    font-weight: 700;
  }
}

/* Stacked cycles need the connectors the ring normally provides. */
@media (max-width: 560px) {
  /* relative so the connector can hang off it — left/top have to go with it,
     or the ring's own offsets come back the moment the box stops being static */
  .cycle__step { position: relative; left: auto; top: auto; }
  .cycle__step + .cycle__step::before {
    content: '';
    position: absolute;
    left: clamp(1.1rem, 5vw, 1.6rem);
    top: calc(-1 * clamp(1.5rem, 6vw, 2rem));
    width: 2px;
    height: clamp(1.5rem, 6vw, 2rem);
    background: var(--accent);
  }
  .cycle__step + .cycle__step::after {
    content: '';
    position: absolute;
    left: clamp(1.1rem, 5vw, 1.6rem);
    top: -7px;
    width: 0;
    height: 0;
    border-left: 4.5px solid transparent;
    border-right: 4.5px solid transparent;
    border-top: 7px solid var(--accent);
    transform: translateX(-3.5px);
  }
}

/* A soft red wash behind the two trope headings — the anger they name, sitting
   behind the words rather than around them. */
.subhead-major--blob { position: relative; isolation: isolate; }

.subhead-major--blob::before {
  content: '';
  position: absolute;
  z-index: -1;
  left: -6%;
  top: 50%;
  translate: 0 -50%;
  width: min(26rem, 72%);
  aspect-ratio: 1.9 / 1;
  /* closest-side makes the ellipse inscribe its box, so the gradient reaches
     full transparency exactly at every edge. The default farthest-corner
     sizing left it still coloured where the box ended, which showed as a hard
     vertical cut down the left. */
  background: radial-gradient(ellipse closest-side at 50% 50%,
    rgba(214, 48, 34, .28) 0%,
    rgba(222, 86, 60, .15) 55%,
    rgba(230, 120, 90, 0) 100%);
  pointer-events: none;
}

@media (max-width: 560px) {
  .subhead-major--blob::before { width: min(20rem, 110%); }
}

/* A section that continues the one above it rather than starting a new idea.
   The questions and the examples that answer them are one unit, so they get a
   single gap between them instead of each contributing its own — and a smaller
   one than usual, so the top of the cards shows before the reader scrolls. */
main > .section + .section--continues { padding-top: 0; }
main > .section:has(+ .section--continues) { padding-bottom: clamp(1.25rem, 4vw, 3.375rem); }

/* On a phone the hero used nearly the whole screen, so "You are not alone"
   and its questions sat below the fold and nothing invited a scroll. The hero
   gives back its reserved height and some padding, and the opening quote cards
   tighten, so the section underneath shows on arrival. */
@media (max-width: 560px) {
  .hero {
    padding-top: calc(var(--nav-h) + clamp(1.75rem, 6vw, 3rem));
    padding-bottom: clamp(1.75rem, 6vw, 2.5rem);
  }

  /* enough reserved height for the hero to still feel like one, but not so
     much that it fills the screen */
  .hero--art { min-height: min(44svh, 320px); }
  .hero__standfirst { font-size: 1rem; line-height: 1.5; }

  .quote-overlap { margin-top: calc(-1 * clamp(1.5rem, 5vw, 2.25rem)); }
  .quote-row { gap: .7rem; }

  .qcard { padding: .85rem 1.05rem; }
  .qcard p { font-size: .9375rem; line-height: 1.45; }

  #start { padding-top: clamp(1.75rem, 6vw, 2.5rem); }
}

/* Chrome focuses an <svg> itself when you tap inside it and paints its own
   amber focus ring, which looked like a gold border round the whole chart.
   These are decorative containers, not controls: drop the ring for pointer
   focus and keep the site's own one for keyboard users. */
.bubbles__svg:focus,
.bars__svg:focus,
.cycle__ring:focus { outline: none; }

.bubbles__svg:focus-visible,
.bars__svg:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
}
