/*
Theme Name: Wellington Heart
Theme URI: https://wellingtonheart.com
Author: Wellington Heart Ltd
Description: Block theme for Wellington Heart, the interventional cardiology practice of Prof Scott Harding. Built from the approved 2026 design.
Requires at least: 6.5
Tested up to: 6.8
Requires PHP: 8.0
Version: 1.3.9
License: GNU General Public License v2 or later
Text Domain: wellington-heart
*/

:root{
  --wh-maroon:#6E121C;
  --wh-maroon-dark:#3D080D;
  --wh-red:#A32330;
  --wh-amber:#FFC46B;
  --wh-amber-light:#FFD79A;
  --wh-cream:#FDF6F4;
  --wh-line:#F0DDD9;
  --wh-line-soft:#F5E6E2;
  --wh-body:#5E4A4A;
  --wh-muted:#8A6260;
  --wh-on-dark:#F2D2CD;
  --wh-pad-y:clamp(48px,6vw,84px);
  --wh-pad-x:clamp(20px,4vw,56px);
}

body{
  font-family:Figtree,system-ui,-apple-system,"Segoe UI",sans-serif;
  color:var(--wh-body);
  -webkit-font-smoothing:antialiased;
}
a{color:var(--wh-maroon);text-decoration:none}
a:hover{color:var(--wh-red)}

/* ---------- bands ---------- */
.wh-band{padding:var(--wh-pad-y) var(--wh-pad-x)}
.wh-band--tight{padding-top:clamp(24px,3vw,40px)}
.wh-band--white{background:#FFF}
.wh-band--cream{background:var(--wh-cream)}
.wh-band--stone{background:linear-gradient(100deg,#EFEDE9 0%,#E2DED8 100%)}
.wh-band--red{background:var(--wh-maroon);color:#FFF}
.wh-band--dark{background:linear-gradient(112deg,#2B0609 0%,#5C0F17 42%,#8E1A26 78%,#B8404E 100%);color:#FFF}
.wh-band--dark.wh-band{padding-top:clamp(36px,4vw,64px)}
.wh-rule-top{border-top:1px solid var(--wh-line)}
.wh-rule-bottom{border-bottom:1px solid var(--wh-line)}

.wh-panel{border-radius:16px;padding:clamp(28px,3.4vw,48px)}
.wh-panel--stone{background:linear-gradient(100deg,#EFEDE9 0%,#E2DED8 100%)}
.wh-panel--white{background:#FFF;border:1px solid var(--wh-line)}
.wh-panel--red{background:var(--wh-maroon);color:#FFF}

/* ---------- type ---------- */
.wh-eyebrow{
  display:block;font-size:12px;font-weight:600;line-height:1;
  letter-spacing:.14em;text-transform:uppercase;color:var(--wh-muted);margin:0;
}
.wh-band--dark .wh-eyebrow,.wh-band--red .wh-eyebrow,.wh-panel--red .wh-eyebrow{color:#F7C2A8}
.wh-band--stone .wh-eyebrow,.wh-panel--stone .wh-eyebrow{color:var(--wh-red)}

h1,h2,h3,h4{font-weight:600;letter-spacing:-.02em;text-wrap:balance;color:var(--wh-maroon)}
.wh-h1{font-size:clamp(34px,4.4vw,58px);line-height:1.1;letter-spacing:-.025em;margin:0}
.wh-h2{font-size:clamp(28px,3.2vw,40px);line-height:1.15;margin:0}
.wh-h3{font-size:clamp(21px,2vw,26px);line-height:1.25;margin:0}
.wh-band--dark h1,.wh-band--dark h2,.wh-band--dark h3,
.wh-band--red h1,.wh-band--red h2,.wh-band--red h3,
.wh-panel--red h3{color:#FFF}
.wh-band--stone h2,.wh-band--stone h3,.wh-panel--stone h2,.wh-panel--stone h3{color:var(--wh-maroon-dark)}

.wh-lead{font-size:clamp(17px,1.4vw,19px);line-height:1.6;max-width:54ch;text-wrap:pretty}
.wh-band--dark .wh-lead,.wh-band--red .wh-lead,.wh-panel--red p{color:var(--wh-on-dark)}
.wh-band--stone .wh-lead,.wh-panel--stone .wh-lead{color:#4E4845}
.wh-prose p{font-size:18px;line-height:1.7;max-width:66ch;text-wrap:pretty}
.wh-meta{font-size:14px;color:var(--wh-muted);margin:0}
.wh-fineprint{font-size:13px;line-height:1.55;color:var(--wh-muted)}

/* header row: title left, link right */
.wh-headrow{display:flex;align-items:flex-end;justify-content:space-between;gap:40px;flex-wrap:wrap}
.wh-linkarrow a,a.wh-linkarrow{
  font-size:15px;font-weight:600;color:var(--wh-red);
  border-bottom:1px solid #E3B5B9;padding-bottom:3px;
}
.wh-linkarrow a:hover,a.wh-linkarrow:hover{color:var(--wh-maroon)}

/* ---------- buttons ---------- */
.wp-block-button .wp-block-button__link{
  border-radius:8px;padding:16px 30px;font-size:16px;font-weight:600;
  transition:background-color .15s ease,color .15s ease,border-color .15s ease;
}
.is-style-wh-amber .wp-block-button__link{background:var(--wh-amber);color:var(--wh-maroon-dark)}
.is-style-wh-amber .wp-block-button__link:hover{background:var(--wh-amber-light);color:var(--wh-maroon-dark)}
.is-style-wh-maroon .wp-block-button__link{background:var(--wh-maroon);color:#FFF}
.is-style-wh-maroon .wp-block-button__link:hover{background:var(--wh-maroon-dark);color:var(--wh-amber)}
.is-style-wh-outline .wp-block-button__link{background:transparent;border:1px solid var(--wh-maroon);color:var(--wh-maroon)}
.is-style-wh-outline .wp-block-button__link:hover{background:var(--wh-maroon);color:#FFF}
.is-style-wh-outline-light .wp-block-button__link{background:transparent;border:1px solid rgba(255,255,255,.45);color:#FFF}
.is-style-wh-outline-light .wp-block-button__link:hover{border-color:var(--wh-amber);color:var(--wh-amber)}

/* ---------- cards ---------- */
.wh-card{
  padding:clamp(24px,2.2vw,32px);border:1px solid var(--wh-line);
  border-radius:14px;background:#FFF;
}
/* Stretch a card to fill its cell only where it is the sole occupant.
   A column holding two stacked cards must NOT give each of them height:100%,
   or the second overflows the column and lands on the section below. */
.is-layout-grid > .wh-card,
.wp-block-column > .wh-card:only-child{height:100%}
.wh-card h3{margin:0;font-size:21px;line-height:1.3}
.wh-card p{margin:12px 0 0;font-size:16px;line-height:1.65;color:var(--wh-body);text-wrap:pretty}
a.wh-card:hover,.wh-card--link:hover{border-color:var(--wh-maroon);background:var(--wh-cream)}
.wh-card--maroon{background:var(--wh-maroon);border-color:transparent;color:#FFF}
.wh-card--maroon h3{color:#FFF}
.wh-card--maroon p{color:var(--wh-on-dark)}
.wh-card--maroon:hover{background:var(--wh-maroon-dark)}
.wh-card--flat{background:var(--wh-cream);border-color:var(--wh-line)}
.wh-step{padding:clamp(24px,2.2vw,32px);border-radius:12px;background:#7C1B25;height:100%}
.wh-step .wh-num{font-size:15px;font-weight:600;line-height:1;letter-spacing:.1em;color:var(--wh-amber)}
.wh-step h3{margin:18px 0 0;font-size:20px;line-height:1.3;color:#FFF}
.wh-step p{margin:10px 0 0;font-size:16px;line-height:1.6;color:var(--wh-on-dark)}
.wh-note{
  margin-top:18px;padding-top:16px;border-top:1px solid var(--wh-line-soft);
  font-size:14px;line-height:1.6;color:var(--wh-muted);
}
.wh-note strong{color:var(--wh-red);font-weight:600}

/* ---------- media ---------- */
.wh-media img{border-radius:12px;display:block;width:100%;height:auto}
.wh-media video{border-radius:12px;display:block;width:100%;height:auto;background:#000}
.wh-media.wp-block-video{margin:0}
.wh-media--square img{aspect-ratio:1/1;object-fit:cover}
.wh-media--portrait img{aspect-ratio:3/4;object-fit:cover}
.wh-media--wide img{aspect-ratio:16/9;object-fit:cover}
.wh-media--photo img{aspect-ratio:4/3;object-fit:cover}
.wh-media--bleed img{border-radius:0}
figure.wh-media{margin:0}
figure.wh-media figcaption{
  margin:14px 0 0;font-size:15px;line-height:1.6;color:var(--wh-muted);max-width:70ch;
}
.wh-band--dark figure.wh-media figcaption,.wh-band--red figure.wh-media figcaption{color:var(--wh-on-dark)}

/* ---------- definition rows / tables ---------- */
.wh-rows{display:flex;flex-direction:column}
.wh-row{
  display:flex;gap:24px;padding:18px 0;border-bottom:1px solid var(--wh-line);
  font-size:17px;line-height:1.5;
}
.wh-row:last-child{border-bottom:0}
.wh-row dt,.wh-row .wh-row__k{flex:0 0 130px;font-size:14px;color:var(--wh-muted);margin:0}
.wh-row dd,.wh-row .wh-row__v{margin:0;color:var(--wh-maroon);font-weight:500}
.wh-band--dark .wh-row{border-color:rgba(255,255,255,.16)}
.wh-band--dark .wh-row dt,.wh-band--dark .wh-row .wh-row__k{color:#E0A9A3}
.wh-band--dark .wh-row dd,.wh-band--dark .wh-row .wh-row__v{color:#FFF}

/* Appointment-style rows put the role first and the place second, rather than
   the muted key first. Without a basis on that first cell every row sizes its
   own first column to its text, so each row's second column starts at a
   different x. A fixed basis lines them all up on the widest role. Baseline
   alignment settles the 17px role against the 14px place beside it. */
.wh-rows .wh-row{align-items:baseline}
.wh-rows .wh-row > .wh-row__v:first-child{flex:0 0 38%}

/* One appointment row carries eleven professional roles, which will not sit in
   the 38% split beside its label. --stack drops the label above and gives the
   list the full panel width; the list itself runs in two columns so it reads as
   a block rather than a long thin column. Specificity matches the rule above,
   so this has to stay after it. */
.wh-rows .wh-row--stack{flex-direction:column;gap:10px}
.wh-rows .wh-row--stack > .wh-row__v:first-child{flex:0 0 auto}
.wh-rolelist{columns:2;column-gap:32px;padding-left:18px;margin:0}
.wh-rolelist li{break-inside:avoid;margin:0 0 8px;line-height:1.45}

/* Tables are hooked from the figure, not the table element. core/table's
   save() writes class="has-fixed-layout" on <table> and nothing else, so a
   wh-table class put there made the block invalid in the editor. The figure is
   ours to class, the table is core's. */
.wh-table-wrap table{width:100%;border-collapse:collapse;background:#FFF;border:1px solid var(--wh-line);border-radius:14px;overflow:hidden}
.wh-table-wrap th{
  text-align:left;padding:18px 28px;background:#FBF1EE;border-bottom:1px solid var(--wh-line);
  font-size:12px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--wh-muted);
}
.wh-table-wrap td{padding:18px 28px;border-bottom:1px solid var(--wh-line-soft);font-size:16px;color:var(--wh-maroon);vertical-align:baseline}
.wh-table-wrap tr:last-child td{border-bottom:0}
.wh-table-wrap td:first-child{font-weight:600;color:var(--wh-red);white-space:nowrap}

/* ---------- pills / tags ---------- */
.wh-pills{display:flex;flex-wrap:wrap;gap:10px}
.wh-pill{
  display:inline-flex;align-items:center;padding:10px 16px;border-radius:8px;
  background:var(--wh-cream);border:1px solid var(--wh-line);font-size:15px;color:var(--wh-maroon);
}
.wh-band--dark .wh-pill{background:rgba(255,255,255,.14);border-color:transparent;color:#FBEAE7}
.wh-tag{
  display:inline-flex;align-items:center;padding:6px 12px;border-radius:999px;
  background:var(--wh-maroon);color:#FFF;font-size:12px;font-weight:600;letter-spacing:.06em;
}
.wh-filters{display:flex;flex-wrap:wrap;gap:10px}
.wh-filters a{
  padding:11px 20px;border-radius:999px;border:1px solid rgba(255,255,255,.4);
  color:#FBEAE7;font-size:15px;font-weight:500;
}
.wh-filters a:hover{border-color:var(--wh-amber);color:var(--wh-amber)}
.wh-filters a.is-current{background:var(--wh-amber);border-color:var(--wh-amber);color:var(--wh-maroon-dark)}

/* ---------- header ---------- */
.wh-topbar{
  display:flex;align-items:center;justify-content:space-between;gap:24px;flex-wrap:wrap;
  padding:14px var(--wh-pad-x);font-size:13px;color:#EBC4C0;
  border-bottom:1px solid rgba(255,255,255,.12);
}
.wh-topbar a{color:#EBC4C0}
.wh-topbar a:hover{color:var(--wh-amber)}
.wh-topbar strong{color:#FFF;font-weight:600}
.wh-masthead{padding:24px var(--wh-pad-x)}
.wh-masthead .wp-block-site-title a{
  font-size:25px;font-weight:700;line-height:1;letter-spacing:-.02em;color:#FFF;
}
.wh-masthead .wp-block-site-title a:hover{color:#FFF}
.wh-strapline{
  margin:4px 0 0;font-size:10px;font-weight:600;line-height:1;
  letter-spacing:.18em;text-transform:uppercase;color:#E0A9A3;
}
.wh-nav a{font-size:15px;font-weight:500;color:#FBEAE7}
.wh-nav a:hover{color:var(--wh-amber)}
/* the open overlay is styled in block 17; a rule here cannot win against core */
.wh-nav .wp-block-navigation__responsive-container-open,
.wh-nav .wp-block-navigation__responsive-container-close{color:#FFF}

/* ---------- footer ---------- */
.wh-footer{
  background:linear-gradient(180deg,#3D080D 0%,#7A1620 100%);
  color:#EBC4C0;padding:64px var(--wh-pad-x) 44px;
}
.wh-footer a{color:#EBC4C0;font-size:15px}
.wh-footer a:hover{color:var(--wh-amber)}
.wh-footer .wp-block-site-title a{font-size:24px;font-weight:700;letter-spacing:-.02em;color:#FFF}
.wh-footer h2,.wh-footer .wh-foot-head{
  font-size:13px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#FFF;margin:0 0 4px;
}
.wh-footer p{font-size:15px;line-height:1.6}
.wh-footer .wh-disclaimer{font-size:13px;line-height:1.6;color:#E7C3BF;max-width:100ch}
.wh-footer-top{padding-bottom:44px;border-bottom:1px solid rgba(255,255,255,.14)}

/* ---------- post / archive ---------- */
.wh-postmeta{font-size:14px;color:var(--wh-muted);margin:0 0 10px}
.wh-entry h1{margin:0 0 18px}
.wh-entry p,.wh-entry li{font-size:18px;line-height:1.7;max-width:70ch}
.wh-entry h2{font-size:28px;margin:40px 0 12px}
.wh-entry h3{font-size:22px;margin:32px 0 10px}
.wh-entry blockquote{
  margin:32px 0;padding:4px 0 4px 24px;border-left:3px solid var(--wh-amber);
  font-size:20px;line-height:1.6;color:var(--wh-maroon);
}
.wh-entry img{border-radius:12px}
.wh-loop-card .wp-block-post-featured-image img{border-radius:12px;aspect-ratio:3/2;object-fit:cover}
.wh-loop-card .wp-block-post-title{font-size:21px;line-height:1.3;margin:8px 0 0}
.wh-loop-card .wp-block-post-title a{color:var(--wh-maroon)}
.wh-loop-card .wp-block-post-excerpt__excerpt{font-size:16px;line-height:1.6;color:var(--wh-body)}
.wh-loop-card .wp-block-post-date{font-size:14px;color:var(--wh-muted);margin-top:14px}

.wh-loop-row{
  display:grid;grid-template-columns:180px 1fr 130px;gap:32px;align-items:baseline;
  padding:24px 0;border-bottom:1px solid var(--wh-line);
}
.wh-loop-row:hover{background:var(--wh-cream)}
.wh-loop-row .wp-block-post-title{font-size:18px;font-weight:500;margin:0}
.wh-loop-row .wp-block-post-date,.wh-loop-row .wp-block-post-terms{font-size:15px;color:var(--wh-muted);margin:0}

/* ---------- query pagination ---------- */
/* Core ships this unstyled, which on Talks read as "1 2 3 … 5Next Page" in
   default link blue: no gaps, no hit targets, the next link welded to the last
   number because the numbers div and the next link are plain flex siblings.

   Styled here rather than in a template because the block appears in four
   places, Talks and Case studies as query blocks in page content, News and
   search from their templates, and page content cannot carry theme CSS.

   Sizes are the theme's existing ones: 8px radius and 15px/600 text, matching
   .wh-pill and the buttons, so the row reads as part of the same set. 42px
   targets clear the 24x24 minimum comfortably. */
.wp-block-query-pagination{
  gap:8px;margin-top:44px;padding-top:26px;
  border-top:1px solid var(--wh-line);
  align-items:center;flex-wrap:wrap;
}
.wp-block-query-pagination-numbers{
  display:flex;align-items:center;gap:6px;flex-wrap:wrap;justify-content:center;
}
/* box-sizing is content-box here, so without this the 12px padding and the
   border are added outside min-width and a single digit renders in a 68px box
   with the row spread out to match. */
.wp-block-query-pagination .page-numbers,
.wp-block-query-pagination-previous,
.wp-block-query-pagination-next{box-sizing:border-box}
.wp-block-query-pagination .page-numbers{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:42px;height:42px;padding:0 12px;border-radius:8px;
  font-size:15px;font-weight:600;line-height:1;
  color:var(--wh-maroon);border:1px solid transparent;text-decoration:none;
  transition:background-color .15s ease,border-color .15s ease,color .15s ease;
}
.wp-block-query-pagination a.page-numbers:hover{
  background:var(--wh-cream);border-color:var(--wh-line);
}
.wp-block-query-pagination .page-numbers.current{
  background:var(--wh-maroon);color:#FFF;
}
/* the ellipsis is not a control: no box, no target, and out of the tab order
   already because core renders it as a span */
.wp-block-query-pagination .page-numbers.dots{
  min-width:20px;padding:0 2px;font-weight:400;color:var(--wh-muted);
}

.wp-block-query-pagination-previous,
.wp-block-query-pagination-next{
  display:inline-flex;align-items:center;gap:9px;
  height:42px;padding:0 18px;border-radius:8px;
  border:1px solid var(--wh-line);background:#FFF;
  font-size:15px;font-weight:600;color:var(--wh-maroon);text-decoration:none;
  transition:background-color .15s ease,border-color .15s ease,color .15s ease;
}
.wp-block-query-pagination-previous:hover,
.wp-block-query-pagination-next:hover{
  background:var(--wh-maroon);border-color:var(--wh-maroon);color:#FFF;
}
/* Arrows are decoration, so they are generated rather than written into the
   markup: a screen reader still hears "Previous Page", and the label stays
   translatable. */
.wp-block-query-pagination-previous::before{content:"\2190";font-size:17px;line-height:1}
.wp-block-query-pagination-next::after{content:"\2192";font-size:17px;line-height:1}

.wp-block-query-pagination a:focus-visible{
  outline:2px solid var(--wh-red);outline-offset:2px;
}

/* On a dark band the same row has to invert: Case studies uses one. */
.wh-band--dark .wp-block-query-pagination,
.wh-band--red .wp-block-query-pagination{border-top-color:rgba(255,255,255,.18)}
.wh-band--dark .wp-block-query-pagination .page-numbers,
.wh-band--red .wp-block-query-pagination .page-numbers,
.wh-band--dark .wp-block-query-pagination-previous,
.wh-band--dark .wp-block-query-pagination-next,
.wh-band--red .wp-block-query-pagination-previous,
.wh-band--red .wp-block-query-pagination-next{
  color:#FFF;background:transparent;border-color:rgba(255,255,255,.28);
}
.wh-band--dark .wp-block-query-pagination .page-numbers.current,
.wh-band--red .wp-block-query-pagination .page-numbers.current{
  background:var(--wh-amber);color:var(--wh-maroon-dark);border-color:var(--wh-amber);
}
.wh-band--dark .wp-block-query-pagination a.page-numbers:hover,
.wh-band--red .wp-block-query-pagination a.page-numbers:hover,
.wh-band--dark .wp-block-query-pagination-previous:hover,
.wh-band--dark .wp-block-query-pagination-next:hover,
.wh-band--red .wp-block-query-pagination-previous:hover,
.wh-band--red .wp-block-query-pagination-next:hover{
  background:rgba(255,255,255,.12);border-color:var(--wh-amber);color:var(--wh-amber);
}

@media(max-width:781px){
  .wh-loop-row{grid-template-columns:1fr;gap:6px}
  .wh-row{flex-direction:column;gap:4px}
  /* flex-basis sizes the main axis, and the main axis is now vertical, so
     every basis set for the desktop two-column row has to be unset here or it
     turns into a height. The wh-row__v line was already doing that for the
     appointment rows; wh-row__k was missed, and its 0 0 130px was drawing a
     130px tall empty box under Phone, Email, Clinics and Referrals in the
     contact cards on Home and Contact. */
  .wh-rows .wh-row > .wh-row__v:first-child{flex:0 0 auto}
  .wh-row dt,.wh-row .wh-row__k{flex:0 0 auto}
  /* core's .is-layout-flex sets align-items:center and prints after this
     stylesheet, so one class ties and loses; the class is doubled to win
     without !important. Centred is right for a horizontal row and wrong for a
     stacked one, where it centres each label over its value and shrinks both
     to their text. .wh-rows overrides it to baseline on desktop, which has the
     same problem once the row turns vertical. */
  .wh-row.wh-row{align-items:flex-start}
  .wh-rows .wh-row{align-items:flex-start}
  .wh-rolelist{columns:1}
  .wp-block-query-pagination{gap:8px;margin-top:32px;padding-top:20px}
  .wp-block-query-pagination .page-numbers{min-width:40px;height:40px;padding:0 9px}
  .wp-block-query-pagination-previous,
  .wp-block-query-pagination-next{height:40px;padding:0 14px;font-size:14px}
  .wh-table-wrap th,.wh-table-wrap td{padding:14px 16px;font-size:15px}
  .wh-headrow{align-items:flex-start}
}

/* an "image needed" placeholder the editor can swap for a real image */
.wh-placeholder{
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;
  text-align:center;padding:32px;min-height:260px;border:2px dashed #C1A9A2;
  border-radius:12px;background:rgba(255,255,255,.55);
}
.wh-placeholder .wh-placeholder__kicker{
  font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--wh-red);
}
.wh-placeholder .wh-placeholder__title{font-size:22px;font-weight:600;line-height:1.3;color:var(--wh-maroon);max-width:24ch}
.wh-placeholder p{font-size:15px;line-height:1.5;color:#6B6460;max-width:36ch;margin:0}

/* skip link + a11y */
.skip-link:focus{background:#FFF;color:var(--wh-maroon);padding:12px 20px;z-index:99}
:where(a:focus-visible),:where(button:focus-visible){outline:3px solid var(--wh-amber);outline-offset:2px}

/* ---------- measure utilities (were inline max-width) ---------- */
.wh-measure-13{max-width:13ch}
.wh-measure-16{max-width:16ch}
.wh-measure-20{max-width:20ch}
.wh-measure-22{max-width:22ch}
.wh-measure-24{max-width:24ch}
.wh-measure-60{max-width:60ch}
.wh-measure-66{max-width:66ch}
.wh-measure-80{max-width:80ch}

/* ---------- grid layouts stack down ---------- */
/* core emits grid-template-columns on a single generated class, so the
   two-class selector below wins without needing !important */
@media(max-width:1180px){
  .wp-block-group.is-layout-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media(max-width:781px){
  .wp-block-group.is-layout-grid{grid-template-columns:1fr}
  .wp-block-post-template.is-layout-grid{grid-template-columns:1fr}
}

/* ---------- flow spacing inside prose ---------- */
/* root block gap is 0 so sections butt together; restore rhythm where text flows */
.wh-entry > * + *{margin-block-start:1.1em}
.wp-block-post-content > * + *{margin-block-start:1.1em}
/* ...but full-width bands are not prose: they butt together, as they do when a
   template places them directly. Every pattern's outer element carries a
   wh-band class, except teaching-band which carries only wh-band--white. */
.wp-block-post-content > [class*="wh-band"] + [class*="wh-band"]{margin-block-start:0}
.wh-prose > * + *{margin-block-start:1.1em}
.wh-card > * + *{margin-block-start:12px}
.wh-loop-card > * + *{margin-block-start:10px}

/* ---------- CV: talks and publications ---------- */
.wh-talk-list{margin:0;padding-left:20px}
.wh-talk-list li{margin:6px 0}
.wh-role{display:inline-block;font-size:11px;text-transform:uppercase;letter-spacing:.06em;
  padding:2px 9px;border-radius:99px;margin-left:8px;vertical-align:2px;white-space:nowrap}
.wh-role--live{color:#8A2F00;background:#FFE6D6}
.wh-role--ws{color:#1D5C3A;background:#DFF3E6}
.wh-role--key{color:#6B4B00;background:#FFF2CC}
.wh-role--chair{color:#4A3480;background:#ECE5FF}

.wh-pub{padding:14px 0;border-bottom:1px solid var(--wh-line)}
.wh-pub strong{color:var(--wh-maroon);font-weight:600}
.wh-pub-a{font-size:14px;color:var(--wh-muted)}
.wh-pub-a b{color:var(--wh-body);font-weight:600}
.wh-pub-j{font-size:14px;color:var(--wh-muted)}
.wh-pub-link{display:inline-block;font-size:12px;text-decoration:none;
  padding:2px 10px;border-radius:99px;background:var(--wh-cream);color:var(--wh-maroon)}
.wh-pub-flag{display:inline-block;font-size:11px;text-transform:uppercase;letter-spacing:.06em;
  padding:2px 9px;border-radius:99px;margin-left:8px;vertical-align:2px;
  color:#6B4B00;background:#FFF2CC}
.wh-pub-year{display:flex;align-items:baseline;gap:10px}
.wh-pub-count{font-size:13px;font-weight:400;color:var(--wh-muted)}
@media(max-width:600px){.wh-role,.wh-pub-flag{margin-left:0;margin-top:6px}}

/* On a phone the three parts do not fit on one line. Left to itself the
   numbers overflow the viewport rather than wrapping, which put page 5 off the
   right edge and left "Next Page" stranded on a line of its own. Giving the
   numbers the full width stacks the three parts instead: previous, the numbers,
   next. Source order is untouched, so the tab order still matches what is on
   screen. */
@media(max-width:600px){
  .wp-block-query-pagination{gap:12px}
  .wp-block-query-pagination-numbers{flex-basis:100%;min-width:0}
}

/* 12. Inline body links on dark surfaces.
   The global a{color:var(--wh-maroon)} rule also applied inside the dark and
   red bands, where maroon on maroon measures 1.15:1 and the link is invisible:
   the 404 phone number, and the phone and email in contact-hero, all vanished.
   .wh-topbar and .wh-footer already carried their own dark-context link colour;
   the bands did not. Scoped to main so the header, which sits inside a dark
   band, keeps its own styling, and excluding .wh-filters, whose links are
   already styled as pills and set their own colour. Underlined so the link is
   still marked as one at the light end of the band gradient, where amber drops
   to 3.98:1. */
main .wh-band--dark a:not(.wp-element-button):not(.wh-filters a),
main .wh-band--red a:not(.wp-element-button):not(.wh-filters a),
main .wh-panel--red a:not(.wp-element-button):not(.wh-filters a){
  color:var(--wh-amber-light);text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:1px}
main .wh-band--dark a:not(.wp-element-button):not(.wh-filters a):hover,
main .wh-band--red a:not(.wp-element-button):not(.wh-filters a):hover,
main .wh-panel--red a:not(.wp-element-button):not(.wh-filters a):hover{color:#FFF}

/* 13. Measure-limited text in a constrained band.
   Core's constrained layout gives every direct child
   margin-inline:auto !important, so any child carrying a max-width gets
   centred: .wh-lead has max-width:54ch and the wh-measure-NN classes set their
   own. Wherever either sits directly in a band rather than nested in a column,
   it drifted to the middle while the full-width eyebrow and grid beside it
   stayed at the column edge. page-hero.php uses both, so every page built from
   it is affected.

   The element has to align to the left edge of the centred content column, not
   to the band's padding edge, or it breaks the other way on viewports wider
   than the content size. At 2560 that put the three-steps h2 489px left of its
   own grid. 100% here is the band's content box, so the offset collapses to 0
   once the viewport is narrower than the column. All 48 constrained groups in
   the theme are bands: 1440px everywhere except the single templates, which
   are 820px throughout. */
.wh-band{--wh-content:1440px}
.single .wh-band{--wh-content:820px}
.wh-band.is-layout-constrained > .wh-lead,
.wh-band.is-layout-constrained > [class*="wh-measure-"]{
  margin-left:max(0px,(100% - var(--wh-content))/2) !important;
  margin-right:auto !important}

/* 14. Gap on the post loop grids.
   theme.json sets the root blockGap to 0 (fix 9) so each pattern declares its
   own spacing. The query loops in home.html, index.html, archive.html,
   archive-case_study.html and news-latest.php never did, so their grids
   inherited 0 and the cards — and the featured images inside them — sat edge
   to edge with no gutter. Row gap is larger than the column gap because a card
   is date + title + excerpt under its image and needs the separation. */
.wp-block-post-template.is-layout-grid{gap:44px 28px}
@media(max-width:781px){.wp-block-post-template.is-layout-grid{gap:36px}}

/* 15. Quotes inside band prose.
   .wh-entry blockquote (the single-post rule above) only covers post content.
   A core/quote placed in a band, which is how the CTO pull quote on About is
   built, landed with no styling at all: the theme sets no blockquote element
   style in theme.json and core's own stylesheet only decorates .is-style-large.
   This gives it the same amber rule as the post rule, italic, and overrides
   .wh-prose p so the quote reads a step above the paragraphs around it rather
   than inheriting their 18px/66ch measure.
   The post-content selector was added in 1.2.1 so a quote dropped straight into
   a page, outside any band, is styled too. Without it an editor following
   EDITING-GUIDE.md would get an unstyled quote on Publications or Privacy. */
.wh-band blockquote,.wh-prose blockquote,.wp-block-post-content > blockquote{
  margin:28px 0;padding:2px 0 2px 24px;border-left:3px solid var(--wh-amber);
  font-style:italic;color:var(--wh-maroon);
}
.wh-band blockquote p,.wh-prose blockquote p,.wp-block-post-content > blockquote p{
  font-size:21px;line-height:1.55;max-width:52ch;margin:0;
}
.wh-band blockquote p + p,.wh-prose blockquote p + p,.wp-block-post-content > blockquote p + p{margin-top:.6em}
.wh-band blockquote cite,.wh-prose blockquote cite,.wp-block-post-content > blockquote cite{
  display:block;margin-top:10px;font-size:15px;font-style:normal;color:var(--wh-muted);
}

/* 16. Where a featured image gets cropped.
   The single-post hero forces 16/9 and the loop cards force 3/2, both with
   object-fit:cover, so any source taller than that loses height. Centred, a
   16/9 crop of a 3:2 photo takes 8% off the top, which is exactly where the
   back row of a group photo is: the imaging course photo on post 5218 lost the
   top of four heads. Biasing the crop to 25% keeps them, and it suits the
   other news images too, because a lecture or a stage screen also sits in the
   upper half of the frame. It is a no-op wherever the source already matches
   the target ratio. */
.wp-block-post-featured-image img{object-position:50% 25%}

/* 17. The mobile menu overlay.
   Reported from a phone: the menu opens, the links sit hard against the right
   edge of the screen, and there is no way to close it again. Three separate
   causes, every one of them a core default this theme had not actually beaten.

   Background and text. Core paints the open overlay with
     .wp-block-navigation:not(.has-background) .(container).is-menu-open
   which is four classes and prints after this stylesheet. The theme's own rule
   in the header section was three classes, so it never applied and the overlay
   came up white with black links. It is restated here at five, the extra class
   being the nav's own .wp-block-navigation. Nothing needs !important.

   Padding. Core's overlay padding is
     clamp(1rem, var(--wp--style--root--padding-right), 20rem)
   and this theme.json does not opt into root-padding-aware alignments, so that
   custom property is never emitted, the clamp is invalid and the browser drops
   the whole declaration. Padding computed to 0 and the menu ran into both
   edges of the screen.

   Alignment. The nav carries justifyContent:right for the desktop bar, which
   sets --navigation-layout-justification-setting:flex-end on the nav element.
   The overlay's content and list both read that property, inherit flex-end and
   stack the links to the right. Setting it on the open container overrides the
   inherited value where it is read, so the desktop bar keeps its own value and
   is not touched.

   The close button. It is present and correctly wired, and it was 24px square
   at top:0 right:0 in colour #FFF from the header rule: white on a white
   overlay, in the corner, with nothing around it. Invisible, not missing. It
   gets amber and a 44px tap target here.

   All of it sits inside the overlay's own breakpoint. Core only shows the
   overlay below 600px, so none of these rules can reach the desktop header. */
@media(max-width:599.98px){
  .wh-nav.wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open{
    background:var(--wh-maroon-dark);
    padding:20px var(--wh-pad-x) 40px;
  }
  .wh-nav.wp-block-navigation:not(.has-text-color) .wp-block-navigation__responsive-container.is-menu-open{
    color:#FBEAE7;
  }
  /* The list has to be named as well as the container. Core copies the block's
     own classes onto the inner ul, so .wp-block-navigation.items-justified-right
     matches the ul too and re-sets the property on the very element that reads
     it, overriding whatever it would otherwise inherit. Setting it on the
     container alone paints the overlay correctly and still stacks every link
     hard right, which is what the first attempt at this did. */
  .wh-nav .wp-block-navigation__responsive-container.is-menu-open,
  .wh-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container{
    --navigation-layout-justification-setting:flex-start;
    --navigation-layout-align:flex-start;
  }
  .wh-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container{gap:22px}
  .wh-nav .wp-block-navigation__responsive-container.is-menu-open a{
    font-size:19px;line-height:1.2;color:#FBEAE7;
  }
  .wh-nav .wp-block-navigation__responsive-container.is-menu-open a:hover,
  .wh-nav .wp-block-navigation__responsive-container.is-menu-open a:focus{color:var(--wh-amber)}
  .wh-nav .wp-block-navigation__responsive-container-close{
    top:0;right:0;width:44px;height:44px;padding:10px;color:var(--wh-amber);
  }
  .wh-nav .wp-block-navigation__responsive-container-close svg{width:24px;height:24px;fill:currentColor}
}
