:root {
  --ek-site-width: 1240px;
  --ek-editorial-width: 920px;
  --ek-reading-width: 720px;
  --ek-commerce-width: 1080px;
  --ek-page-gutter: clamp(20px, 4vw, 48px);
  --ek-mobile-gutter: 20px;
}

.skip-link {
  position: fixed;
  z-index: 1000;
  top: 12px;
  left: 12px;
  padding: .75rem 1rem;
  background: var(--wp--preset--color--paper-surface);
  color: var(--wp--preset--color--authority-ink);
  border: 2px solid var(--wp--preset--color--authority-ink);
  box-shadow: 0 8px 22px rgba(23, 32, 42, .16);
  font-size: .9375rem;
  font-weight: 700;
  text-decoration: none;
  transform: translateY(-160%);
  transition: transform .18s ease-out;
}

.skip-link:focus {
  transform: translateY(0);
}

.ek-shell,
.ek-interior.alignwide {
  width: min(calc(100% - (2 * var(--ek-page-gutter))), var(--ek-site-width));
  margin-inline: auto;
}

.ek-interior {
  width: min(calc(100% - (2 * var(--ek-page-gutter))), var(--ek-editorial-width));
  margin-inline: auto;
}

.ek-editorial {
  max-width: var(--ek-editorial-width);
}

.ek-reading,
.ek-legal {
  max-width: var(--ek-reading-width);
}

.ek-commerce,
.woocommerce main.wp-block-group,
.woocommerce-page main.wp-block-group {
  width: min(calc(100% - (2 * var(--ek-page-gutter))), var(--ek-commerce-width));
  max-width: var(--ek-commerce-width);
  margin-inline: auto;
}

.ek-interior > .wp-block-post-title {
  max-width: 18ch;
  margin-top: 0;
  margin-bottom: clamp(2rem, 5vw, 4rem);
  text-wrap: balance;
}

.ek-interior .wp-block-post-content {
  width: 100%;
}

.ek-interior .wp-block-post-content > :where(p, ul, ol, blockquote) {
  max-width: var(--ek-reading-width);
}

.ek-interior .wp-block-post-content > :where(h2, h3, h4) {
  max-width: var(--ek-reading-width);
  margin-top: clamp(2.5rem, 6vw, 4.5rem);
  margin-bottom: 1rem;
  text-wrap: balance;
}

/* ---------- Interior pages that never got .ek-interior ----------
   Root cause, found 2026-08-15 by reading the live DOM rather than the theme.

   Sixteen pages are assigned the `page-with-title` template. That template
   does not exist in this theme — it is inherited from Extendable, and its
   markup is `main > (title band) + wp:post-content`. It never emits the
   `.ek-interior` wrapper. So every interior rule above, all of which are
   scoped to `.ek-interior`, has silently applied to nothing on Download Help,
   About, FAQ, Paperback, Contact, Articles, Shop, Cart, Checkout and My
   account. The reading measure, the heading rhythm and the title treatment
   were all written and none of them were ever in force there.

   What those pages fell back to instead:
     - heading rhythm: none. Extendable's blockGap puts a flat 0.67rem
       margin-block-start on every sibling, so a section heading and the
       paragraph under it were separated by exactly the same 10.72px. There
       was no visual difference between "new section" and "next line".
     - heading scale: Extendable's theme.json gives h2 `x-large` (42px) while
       the template pins the page title to `large` (36px). Every interior page
       therefore rendered its subheadings LARGER than its own title.

   Fixed by matching the real structure instead of the class that isn't there.
   The `>` is load-bearing: it keeps these rules on the page's own prose and
   off WooCommerce's nested block trees on /cart/ and /checkout/.

   Scoped with `body:not(.home)` deliberately. Seven h2s on the front page
   also inherit Extendable's 42px, and there 42px is right — they are landing
   page section heads, not subheadings under a title. Measured before
   changing anything; correcting the scale globally would have shrunk all
   seven. Different context, different size, so the fix is scoped, not global.
   The front page keeps its own scale in funnel.css. */

/* Extendable marks the page title `alignwide`, which resolves to the 1240px
   wide-size, while prose below sits on the reading measure and is centred by
   the constrained layout. The result was a title starting at x=13 above a
   first paragraph starting at x=273 — a 260px stagger between a page's title
   and its own opening line. Matching the measure lands both left edges on the
   same pixel and drops the title off a 1240px line it was never meant to run.

   Commerce pages must be excluded, and this is the correction to a real
   mistake rather than a precaution. Their content runs at the 1080px commerce
   width, not the reading measure, so pinning the title to 720px there did not
   fix a stagger — it introduced a worse one, leaving "Cart" 169px inside its
   own table. Left alone, the title keeps `alignwide`, which resolves against
   the title band's inner width and lands on the same pixel as the cart.

   The general lesson, and the reason this comment is long: a page title
   belongs to the measure of the content under it, and this template serves
   two different measures. Any future rule here has to ask which one. */
body:not(.home):not(.woocommerce-page) main > .wp-block-group > .wp-block-post-title {
  max-width: var(--ek-reading-width);
  margin-inline: auto;
}

body:not(.home) main > .wp-block-post-content {
  margin-top: clamp(2.5rem, 5vw, 4rem);
}

/* One measure for the whole column, applied by exclusion rather than by
   listing block types.

   Prose sits on the 720px reading measure while Extendable's constrained
   layout puts everything else on its own 760px content-size. Fixing this per
   block type left survivors: after paragraphs, headings and groups were
   corrected, a button row was still landing at x=253 under content at x=273.
   Enumerating block types means the next block someone adds inherits the bug,
   so the rule is inverted — everything takes the measure except what is
   explicitly meant to be wider.

   The exclusions are all intent-carrying: `alignwide` and `alignfull` are the
   author saying so in the editor, `.ek-commerce` is this theme's own 1080px
   commerce width, and WooCommerce's own top-level blocks own their layout on
   /cart/ and /checkout/. `.woocommerce` is the same category as that last one
   but arrives as a shortcode wrapper rather than a block, which is why it was
   missed: it is the account area, whose signed-in view is a sidebar beside a
   panel and cannot do its job inside a 720px prose measure. account.css puts
   the measure back on the logged-out login view, where it belongs. */
body:not(.home) main > .wp-block-post-content > *:not(.alignwide):not(.alignfull):not(.ek-commerce):not(.woocommerce):not([class*="wp-block-woocommerce"]) {
  max-width: var(--ek-reading-width);
}

body:not(.home) main > .wp-block-post-content > :where(p, ul, ol, blockquote, figure) {
  margin-top: 0;
  margin-bottom: 1.15rem;
}

body:not(.home) main > .wp-block-post-content > :where(h2, h3, h4) {
  text-wrap: balance;
}

body:not(.home) main > .wp-block-post-content > h2 {
  margin-top: clamp(2.75rem, 5vw, 3.75rem);
  margin-bottom: .75rem;
  font-size: clamp(1.5rem, 2vw, 1.75rem);
}

body:not(.home) main > .wp-block-post-content > h3 {
  margin-top: clamp(2rem, 3.5vw, 2.5rem);
  margin-bottom: .6rem;
  font-size: clamp(1.2rem, 1.6vw, 1.4rem);
}

body:not(.home) main > .wp-block-post-content > h4 {
  margin-top: 1.75rem;
  margin-bottom: .5rem;
  font-size: clamp(1.05rem, 1.2vw, 1.15rem);
}

body:not(.home) main > .wp-block-post-content > :first-child {
  margin-top: 0;
}

/* A group of buttons is the end of an argument, not the next line of one.
   At the foot of the FAQ these sat 10.72px under the last question. */
body:not(.home) main > .wp-block-post-content > .wp-block-buttons {
  margin-top: clamp(2rem, 4vw, 3rem);
  margin-bottom: 0;
}

body:not(.home) main > .wp-block-post-content > .wp-block-separator {
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  margin-bottom: clamp(2.5rem, 5vw, 3.5rem);
}

/* The contact form's submit button was 11px from the next section heading,
   so "Send message" read as if it belonged to the paragraph below it. */
body:not(.home) main > .wp-block-post-content > .formlayer-form-wrapper {
  margin-bottom: clamp(1rem, 3vw, 2rem);
}

.ek-interior :where(input, textarea, select, button, .wp-element-button):focus-visible,
.woocommerce :where(input, textarea, select, button, a):focus-visible {
  outline: 3px solid var(--wp--preset--color--institutional-blue);
  outline-offset: 3px;
}

.ek-interior :where(input, textarea, select),
.woocommerce :where(input, textarea, select) {
  min-height: 48px;
  border: 1px solid var(--wp--preset--color--paper-rule);
  border-radius: var(--wp--custom--radius--field, 6px);
  background: var(--wp--preset--color--paper-surface);
  color: var(--wp--preset--color--authority-ink);
}

.ek-interior textarea,
.woocommerce textarea {
  min-height: 160px;
}

.ek-archive,
.ek-single,
.ek-404 {
  padding-top: clamp(4.5rem, 9vw, 8rem);
  padding-bottom: clamp(5rem, 10vw, 9rem);
}

.ek-archive-header {
  max-width: var(--ek-reading-width);
  margin: 0 0 clamp(3.5rem, 8vw, 6rem);
}

.ek-archive-header h1,
.ek-single > .wp-block-post-title,
.ek-404 > h1 {
  margin: 0 0 1.25rem;
  text-wrap: balance;
}

.ek-archive-header > p {
  max-width: 54ch;
  margin: 0;
  line-height: 1.45;
}

.ek-article-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.ek-article-row {
  display: grid;
  grid-template-columns: minmax(110px, .28fr) minmax(0, 1fr);
  column-gap: clamp(1.5rem, 5vw, 4.5rem);
  padding: clamp(2rem, 5vw, 3.5rem) 0;
  border-top: 1px solid var(--wp--preset--color--paper-rule);
}

.ek-article-row > .wp-block-post-date {
  grid-row: 1 / span 3;
  margin: .35rem 0 0;
  text-transform: uppercase;
  letter-spacing: .06em;
}

.ek-article-row > .wp-block-post-title {
  margin: 0 0 .8rem;
}

.ek-article-row > .wp-block-post-title a {
  text-decoration-thickness: 1px;
  text-decoration-color: transparent;
  text-underline-offset: 5px;
}

.ek-article-row > .wp-block-post-title a:hover {
  text-decoration-color: var(--wp--preset--color--decision-amber);
}

.ek-article-row .wp-block-post-excerpt {
  margin: 0;
  color: var(--wp--preset--color--working-ink);
}

.ek-article-row .wp-block-post-excerpt__more-link {
  display: inline-block;
  margin-top: .7rem;
  font-size: var(--wp--preset--font-size--label);
  font-weight: 700;
}

/* Missed in the square-to-rounded migration: this panel kept hard 0 corners
   while every other surface moved to the panel radius. It is the whole visual
   content of /paperback/, so the one square box on the site was also the only
   thing on that page. */
.ek-empty-state {
  margin-top: 1px;
  padding: clamp(2rem, 6vw, 4rem);
  border: 1px solid var(--wp--preset--color--paper-rule);
  border-radius: var(--wp--custom--radius--panel, 10px);
  background: var(--wp--preset--color--paper-surface);
  box-shadow: 0 18px 44px rgba(23, 32, 42, .09);
}

.ek-empty-state h2 {
  margin-top: 0;
}

.ek-article-query .wp-block-query-pagination {
  margin-top: 3rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--wp--preset--color--paper-rule);
}

.ek-search-form {
  margin-top: 2rem;
}

.ek-search-form .wp-block-search__inside-wrapper {
  gap: .75rem;
}

.ek-search-form .wp-block-search__input {
  padding-inline: 1rem;
}

.ek-single .ek-post-meta {
  gap: .65rem 1.5rem;
  margin-bottom: 2rem;
}

.ek-single > .wp-block-separator {
  margin-bottom: clamp(2.5rem, 6vw, 4rem);
}

.ek-single .wp-block-post-content {
  font-size: clamp(1.03rem, 1.2vw, 1.12rem);
}

.ek-post-navigation {
  gap: 2rem;
  margin-top: clamp(3.5rem, 8vw, 6rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--wp--preset--color--paper-rule);
}

.ek-404 .ek-search-form {
  margin: 2.5rem 0 3rem;
}

.ek-route-list {
  padding-left: 1.2rem;
}

.ek-route-list li {
  margin-bottom: .8rem;
}

.ek-principles {
  gap: 0;
  margin: 2rem 0 clamp(3.5rem, 8vw, 6rem);
  border-top: 1px solid var(--wp--preset--color--authority-ink);
  border-bottom: 1px solid var(--wp--preset--color--paper-rule);
}

.ek-principles > .wp-block-column {
  padding: clamp(1.5rem, 4vw, 2.5rem);
  border-right: 1px solid var(--wp--preset--color--paper-rule);
}

.ek-principles > .wp-block-column:first-child {
  padding-left: 0;
}

.ek-principles > .wp-block-column:last-child {
  padding-right: 0;
  border-right: 0;
}

.ek-principles h3 {
  margin-top: 0 !important;
}

.ek-scope-note {
  margin: clamp(3rem, 7vw, 5rem) 0;
  padding: clamp(2rem, 5vw, 3.5rem);
  box-shadow: 0 18px 44px rgba(23, 32, 42, .09);
}

.ek-scope-note h2 {
  margin-top: 0 !important;
}

.ek-faq-category {
  margin-top: clamp(3rem, 7vw, 5rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--wp--preset--color--authority-ink);
}

/* These are section labels inside a long question list, so they sit below the
   page title in the hierarchy. Nested one level down, they were out of reach
   of the direct-child ramp above and kept Extendable's 42px — larger than the
   36px "FAQ" title they belong under.
   Deliberately not fixed with a blanket descendant rule: `.ek-empty-state h2`
   on /paperback/ is a hero statement and is meant to stay large. */
.ek-faq-category > h2 {
  margin-top: 0 !important;
  font-size: clamp(1.5rem, 2vw, 1.75rem);
}

.ek-faq-list details {
  border-bottom: 1px solid var(--wp--preset--color--paper-rule);
}

.ek-faq-list summary {
  position: relative;
  padding: 1.3rem 3rem 1.3rem 0;
  cursor: pointer;
  color: var(--wp--preset--color--authority-ink);
  font-family: var(--wp--preset--font-family--display-serif);
  font-size: var(--wp--preset--font-size--title);
  line-height: 1.25;
  list-style: none;
}

.ek-faq-list summary::-webkit-details-marker {
  display: none;
}

.ek-faq-list summary::after {
  content: '+';
  position: absolute;
  top: 1rem;
  right: .2rem;
  color: var(--wp--preset--color--completion-green);
  font-family: var(--wp--preset--font-family--working-sans);
  font-size: var(--wp--preset--font-size--title);
}

.ek-faq-list details[open] summary::after {
  transform: rotate(45deg);
}

.ek-faq-list p {
  max-width: 68ch;
  margin: 0;
  padding: 0 3rem 1.5rem 0;
}

.ek-paperback-state {
  margin-bottom: clamp(3.5rem, 8vw, 6rem);
}

/* WooCommerce keeps its native markup and behavior; this layer only gives
   the store the same working-paper hierarchy as the rest of the site. */
.woocommerce div.product,
.woocommerce .woocommerce-cart-form,
.woocommerce .cart-collaterals,
.woocommerce .woocommerce-checkout,
.woocommerce .woocommerce-order,
.woocommerce .woocommerce-MyAccount-content {
  max-width: 100%;
}

/* Scoped with :has() to WooCommerce's CLASSIC product markup only.
   Unscoped, `.woocommerce div.product` also matched the block template's
   page-level wrapper (single-product.html), which has a single child: the
   grid then created two columns, the one child took the first, and the inner
   wp:column collapsed to width 0 — the product title rendered one letter per
   line. It was invisible for as long as the store sat behind Coming Soon, and
   appeared the moment the store went live.

   The block template lays itself out with wp:columns and needs no grid here. */
.woocommerce div.product:has(> div.summary),
.woocommerce div.product:has(> div.images) {
  display: grid;
  grid-template-columns: minmax(0, .92fr) minmax(0, 1.08fr);
  gap: clamp(2.5rem, 7vw, 6rem);
  align-items: start;
}

.woocommerce div.product div.images,
.woocommerce div.product div.summary {
  width: auto;
  float: none;
  margin: 0;
}

.woocommerce div.product div.summary > h1 {
  margin-top: 0;
}

.woocommerce form .form-row {
  margin: 0 0 1.25rem;
  padding: 0;
}

.woocommerce form .form-row label {
  display: block;
  margin-bottom: .45rem;
  color: var(--wp--preset--color--authority-ink);
  font-size: var(--wp--preset--font-size--label);
  font-weight: 700;
}

.woocommerce form .form-row :where(input.input-text, textarea, select),
.wc-block-components-text-input input,
.wc-block-components-combobox .wc-block-components-combobox-control input.components-combobox-control__input {
  min-height: 48px;
  padding: .75rem 1rem;
  border: 1px solid var(--wp--preset--color--paper-rule);
  border-radius: var(--wp--custom--radius--field, 6px);
  background: var(--wp--preset--color--paper-surface);
  color: var(--wp--preset--color--authority-ink);
}

.woocommerce form .form-row.woocommerce-invalid :where(input.input-text, textarea, select) {
  border-color: var(--wp--preset--color--warning-brick);
}

.woocommerce-error,
.woocommerce-message,
.woocommerce-info {
  margin: 0 0 2rem;
  padding: 1rem 1.25rem;
  border: 1px solid var(--wp--preset--color--paper-rule);
  border-top-width: 1px;
  border-radius: var(--wp--custom--radius--panel, 10px);
  background: var(--wp--preset--color--paper-surface);
  color: var(--wp--preset--color--authority-ink);
  box-shadow: 0 12px 28px rgba(23, 32, 42, .08);
  list-style-position: inside;
}

.woocommerce-error {
  border-color: var(--wp--preset--color--warning-brick);
}

.woocommerce-message {
  border-color: var(--wp--preset--color--completion-green);
}

.woocommerce-error::before,
.woocommerce-message::before,
.woocommerce-info::before {
  display: none;
}

.woocommerce :where(button.button, a.button, input.button),
.wc-block-components-button {
  min-height: 48px;
  border-radius: var(--wp--custom--radius--control, 6px);
  background: var(--wp--preset--color--authority-ink);
  color: var(--wp--preset--color--paper-surface);
  font-weight: 700;
}

.woocommerce :where(button.button, a.button, input.button):hover,
.wc-block-components-button:hover {
  background: var(--wp--preset--color--completion-green);
  color: var(--wp--preset--color--paper-surface);
}

.woocommerce table.shop_table,
.woocommerce-table,
.wc-block-components-totals-wrapper {
  border-color: var(--wp--preset--color--paper-rule);
  border-radius: var(--wp--custom--radius--panel, 10px);
  overflow: hidden;
  background: var(--wp--preset--color--paper-surface);
}

/* ---------- Cart: the line-items panel ----------
   The panel treatment used to be applied to `.wc-block-cart-items` itself.
   That element is a <table>, and the surface never actually landed on it —
   the computed background stayed transparent and padding stayed 0, so the
   left half of the cart was a bare table sitting next to a fully realised
   card on the right. Two halves of one page, finished to different standards.

   Moved onto the block wrapper, which is a div and can hold padding
   honestly. The table keeps its own layout and the row rules below keep
   drawing the separators, so nothing here fights WooCommerce's own grid. */
.wc-block-cart .wp-block-woocommerce-cart-items-block {
  padding: clamp(1.25rem, 2.5vw, 2rem);
  border: 1px solid var(--wp--preset--color--paper-rule);
  border-radius: var(--wp--custom--radius--panel, 10px);
  background: var(--wp--preset--color--paper-surface);
}

/* The sidebar layout is a flex row with the default `align-items: normal`,
   which stretches both columns to the taller one. That was invisible while
   the items side had no surface; with a real panel on it, a one-line cart
   drew a 352px card holding 147px of table and 142px of nothing. The panel
   now hugs its contents and the columns simply start at the same line.

   Note the compound selector. WooCommerce puts `wc-block-cart` and
   `wc-block-components-sidebar-layout` on the SAME element, so a descendant
   selector between the two matches nothing — which is exactly how the first
   attempt at this rule failed silently. */
.wc-block-cart.wc-block-components-sidebar-layout {
  align-items: flex-start;
}

/* The table's own top border would double the panel edge it now sits inside. */
.wc-block-cart .wc-block-cart-items {
  margin: 0;
  border: 0;
  background: none;
}

.wc-block-cart .wc-block-cart-items__header {
  border-bottom: 1px solid var(--wp--preset--color--paper-rule);
}

.wc-block-cart .wc-block-cart-items__row:last-child :where(td, .wc-block-cart-item__image, .wc-block-cart-item__product, .wc-block-cart-item__total) {
  border-bottom: 0;
  padding-bottom: 0;
}

.woocommerce :where(.order-number, .order-date, .order-status, .woocommerce-order-overview__order, code),
.wc-block-components-order-summary-item__description,
.wc-block-components-product-name,
.woocommerce-table a {
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: break-word;
}

.woocommerce .select2-container--default .select2-selection--single {
  min-height: 48px;
  border-color: var(--wp--preset--color--paper-rule);
  border-radius: var(--wp--custom--radius--field, 6px);
}

.woocommerce .select2-container--default .select2-selection--single .select2-selection__rendered,
.woocommerce .select2-container--default .select2-selection--single .select2-selection__arrow {
  min-height: 46px;
  line-height: 46px;
}

.woocommerce :where(input, textarea, select, button, a.button):focus-visible,
.wc-block-components-button:focus-visible {
  outline: 3px solid var(--wp--preset--color--institutional-blue);
  outline-offset: 3px;
}

/* ---------- Shop archive ----------
   /shop/ was rendering from Extendable's archive-product.html, which this
   theme had never overridden. Four things were wrong with it, and only one
   was cosmetic:

   1. NO FOOTER. The parent template pins its footer part with
      `{"slug":"footer","theme":"extendable"}`, so it resolved to the parent's
      part rather than this theme's, and nothing rendered — `.ek-footer` was
      absent from the page entirely. Every legal link, the contact route and
      the trust disclaimer live in that footer, on a product whose positioning
      is that it tells you the truth. That is the reason a child template now
      exists at all; CSS could not have fixed it.
   2. No `<main>` landmark and no skip link — the page was a bare div.
   3. The archive title had no font-size anywhere in the cascade, so an h1
      inherited 16px and rendered identical to body copy.
   4. Full-bleed 1240px content while /cart/ and /checkout/ sit at 1080px.

   The child template fixes 1-4 structurally. What is left here is the
   typography of blocks the template does not control. */

.ek-shop-toolbar {
  align-items: center;
  gap: 1rem;
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--wp--preset--color--paper-rule);
}

.woocommerce .wc-block-product-results-count,
.woocommerce .wc-block-catalog-sorting {
  margin: 0;
  color: var(--wp--preset--color--working-ink);
  font-size: .9375rem;
}

.wp-block-woocommerce-product-collection {
  margin-top: clamp(2rem, 4vw, 3rem);
}

/* Both were rendering at 13px — a product name and its price set smaller than
   the body text of the page they sit on. */
.wc-block-product-template .wp-block-post-title,
.wc-block-product-template .wp-block-post-title a {
  color: var(--wp--preset--color--authority-ink);
  font-family: var(--wp--preset--font-family--display-serif);
  font-size: 1.15rem;
  font-weight: 500;
  letter-spacing: -.015em;
  text-decoration: none;
}

.wc-block-product-template .wc-block-components-product-price {
  color: var(--wp--preset--color--working-ink);
  font-size: 1rem;
}

.wc-block-product-template .wc-block-components-product-image img {
  border-radius: var(--wp--custom--radius--field, 6px);
}

/* The no-results block was rendering underneath a product that was visibly
   on the page: "No products were found matching your selection." directly
   below the kit, its price, and a working Add to cart button. The template
   keeps the block so a genuinely empty catalogue still explains itself; this
   guard only suppresses it when the sibling template actually produced rows,
   which is the one case where the sentence is a lie. */
.wp-block-woocommerce-product-collection:has(.wc-block-product-template li) .wp-block-query-no-results {
  display: none;
}

/* ---------- Cart and checkout: line-item description ----------
   WooCommerce trims the product short description for the summary and this
   product's copy is 154 characters, so the cut landed mid-sentence: it read
   "…34 printable worksheet pages. One…" at the exact moment the buyer is
   deciding whether to hand over money. A sentence that stops dead reads as a
   broken page, and the trim is server-side, so no amount of CSS recovers the
   rest of it.

   The full copy still runs on the product page, where it is doing sales work.
   In the summary the line item already carries the name, the quantity and the
   price, which is what a confirmation panel is for. Hiding the fragment is
   the fix; shortening the product copy to fit a truncation limit would be the
   tail wagging the dog. */
.wc-block-components-product-metadata__description {
  display: none;
}

.wp-block-woocommerce-checkout-order-summary-block,
.wc-block-components-order-summary {
  border-radius: var(--wp--custom--radius--panel, 10px);
}

/* ---------- Cart: the empty state ----------
   Read from the live markup and the shipped plugin CSS on 2026-08-15, not from
   memory. Four separate defects, all real:

   1. WooCommerce masks a cartoon crying face into
      `.wc-block-cart__empty-cart__title.with-empty-cart-icon:before` at 5em
      (cart.css). A weeping emoji is the wrong register on a product bought by
      people who have just had a death in the family — it is the single most
      off-tone element on the store. The mechanism is `mask-image` over
      `background-color: currentColor`, so replacing the mask swaps the drawing
      and leaves the block's own geometry alone. The replacement is a plain
      unfaced bag outline: it still says "cart", and says nothing else.

   2. `.wc-block-cart__empty-cart__title { font-size: inherit }` (cart.css,
      (0,1,0)) beats theme.json's `:root :where(h2)`, so the one sentence that
      explains the page rendered at body size. (0,2,0) here restores it.

   3. `.wc-block-grid.has-4-columns .wc-block-grid__product` pins every card to
      `flex: 1 0 25%; max-width: 25%` (all-products.css, (0,3,0)). This store
      has exactly one product, so the only route back to it rendered at a
      quarter width, hard against the left edge, under centered headings.
      Scoping to the empty-cart block takes this to (0,4,0) and leaves the real
      /shop/ grid untouched.

   4. The recovery card had no surface, so the offer read as loose debris.

   NOT fixed here, because it is page content and not CSS: the second heading
   still says "New in store" on a one-product store, and the first still ends
   in an exclamation mark. Demoting that heading to a quiet section label below
   is a mitigation, not the fix. */

.wp-block-woocommerce-empty-cart-block {
  max-width: 44rem;
  margin-inline: auto;
  padding: clamp(2.5rem, 6vw, 4rem) clamp(1.5rem, 5vw, 3rem);
  border: 1px solid var(--wp--preset--color--paper-rule);
  border-radius: var(--wp--custom--radius--panel, 10px);
  background: var(--wp--preset--color--paper-surface);
  box-shadow: 0 18px 44px rgba(23, 32, 42, .09);
  text-align: center;
}

.wp-block-woocommerce-empty-cart-block .wc-block-cart__empty-cart__title {
  margin: 0;
  color: var(--wp--preset--color--authority-ink);
  font-family: var(--wp--preset--font-family--display-serif);
  font-size: clamp(1.5rem, 3.5vw, 2rem);
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -.022em;
}

.wp-block-woocommerce-empty-cart-block .wc-block-cart__empty-cart__title.with-empty-cart-icon::before {
  height: 2.5em;
  margin: 0 auto 1.1em;
  background-color: var(--wp--preset--color--quiet-ink);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.7 7.7h14.6l-1.13 11.86a1.6 1.6 0 0 1-1.6 1.44H7.43a1.6 1.6 0 0 1-1.6-1.44Z'/%3E%3Cpath d='M8.85 10.3V6.2a3.15 3.15 0 0 1 6.3 0v4.1'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.7 7.7h14.6l-1.13 11.86a1.6 1.6 0 0 1-1.6 1.44H7.43a1.6 1.6 0 0 1-1.6-1.44Z'/%3E%3Cpath d='M8.85 10.3V6.2a3.15 3.15 0 0 1 6.3 0v4.1'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

/* The dotted rule is decorative punctuation from the block library. A hairline
   in the system's own rule colour does the same job without the dots. */
.wp-block-woocommerce-empty-cart-block > .wp-block-separator {
  width: 100%;
  max-width: 3.5rem;
  height: 0;
  margin: clamp(1.75rem, 4vw, 2.5rem) auto;
  border: 0;
  border-top: 1px solid var(--wp--preset--color--paper-rule);
  opacity: 1;
}

.wp-block-woocommerce-empty-cart-block > .wp-block-separator.is-style-dots::before {
  content: none;
}

/* "New in store" on a store with one product. Demoted from a competing h2 to a
   section label so the wrong word carries as little weight as possible until
   the copy itself is corrected in the page. */
.wp-block-woocommerce-empty-cart-block > h2:not(.wc-block-cart__empty-cart__title) {
  margin: 0 0 1.5rem;
  color: var(--wp--preset--color--working-ink);
  font-family: var(--wp--preset--font-family--working-sans);
  font-size: var(--wp--preset--font-size--label);
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.wp-block-woocommerce-empty-cart-block .wc-block-grid__products {
  justify-content: center;
  gap: 1rem;
  margin: 0;
}

.wp-block-woocommerce-empty-cart-block .wc-block-grid.has-4-columns .wc-block-grid__product,
.wp-block-woocommerce-empty-cart-block .wc-block-grid__product {
  flex: 0 1 21rem;
  max-width: 21rem;
  margin: 0;
  padding: 1.5rem;
  border: 1px solid var(--wp--preset--color--paper-rule);
  border-radius: var(--wp--custom--radius--panel, 10px);
  background: var(--wp--preset--color--paper-ground);
}

.wp-block-woocommerce-empty-cart-block .wc-block-grid__product-image img {
  border-radius: var(--wp--custom--radius--field, 6px);
}

.wp-block-woocommerce-empty-cart-block .wc-block-grid__product-title {
  margin-top: 1rem;
  color: var(--wp--preset--color--authority-ink);
  font-family: var(--wp--preset--font-family--display-serif);
  font-size: 1.15rem;
  font-weight: 500;
  letter-spacing: -.015em;
}

.wp-block-woocommerce-empty-cart-block .wc-block-grid__product-price {
  margin: .3rem 0 1.1rem;
  color: var(--wp--preset--color--working-ink);
  font-size: 1rem;
}

.wp-block-woocommerce-empty-cart-block .wc-block-grid__product-add-to-cart .wp-element-button {
  width: 100%;
  min-height: 48px;
}

.wp-block-woocommerce-empty-cart-block .wc-block-grid__product-link {
  text-decoration: none;
}

/* ---------- FormLayer (contact form) ----------
   The plugin ships Arial and a #5525D6 submit button. Styled here rather than
   in the plugin so an update cannot revert it, and scoped to .formlayer-*
   so it applies wherever the shortcode is placed.

   The help text matters more than usual on this form: the people filling it in
   are stressed, often mid-problem, and the commonest support failure is a
   mistyped reply-to address. So help text is Working Body, not a whisper. */

.formlayer-form,
.formlayer-form input,
.formlayer-form textarea,
.formlayer-form button {
  font-family: var(--wp--preset--font-family--working-sans);
}

.formlayer-form {
  max-width: var(--ek-reading-width);
  margin-top: 1.5rem;
}

.formlayer-form .formlayer-field-wrap {
  margin-bottom: 1.6rem;
}

.formlayer-form .formlayer-label {
  display: block;
  margin-bottom: .45rem;
  color: var(--wp--preset--color--authority-ink);
  font-size: var(--wp--preset--font-size--label);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.formlayer-form .required-indicator {
  margin-left: .25rem;
  color: var(--wp--preset--color--warning-brick);
}

/* The plugin styles fields as `.formlayer-form input[type="text"]` — (0,2,1),
   and its stylesheet loads after this one, so an equal-specificity rule loses.
   The wrapper prefix takes this to (0,3,1). Same reason the 16px floor is
   restated here: the plugin ships 15px, which trips iOS focus auto-zoom. */
.formlayer-form-wrapper .formlayer-form input.formlayer-input,
.formlayer-form-wrapper .formlayer-form textarea.formlayer-input {
  width: 100%;
  min-height: 48px;
  padding: .75rem 1rem;
  box-sizing: border-box;
  border: 1px solid var(--wp--preset--color--paper-rule);
  border-radius: var(--wp--custom--radius--field, 6px);
  background: var(--wp--preset--color--paper-surface);
  color: var(--wp--preset--color--authority-ink);
  font-size: 1rem;
  line-height: 1.5;
}

.formlayer-form-wrapper .formlayer-form textarea.formlayer-input {
  min-height: 170px;
  resize: vertical;
}

.formlayer-form .formlayer-input:focus-visible {
  outline: 3px solid var(--wp--preset--color--institutional-blue);
  outline-offset: 2px;
}

.formlayer-form .formlayer-help-text {
  display: block;
  margin-top: .5rem;
  max-width: 62ch;
  color: var(--wp--preset--color--quiet-ink);
  font-size: .9375rem;
  line-height: 1.55;
}

.formlayer-form .formlayer-submit-btn {
  min-height: 54px;
  padding: .85rem 1.55rem;
  border: 1px solid var(--wp--preset--color--authority-ink);
  border-radius: var(--wp--custom--radius--control, 6px);
  background: var(--wp--preset--color--authority-ink);
  color: var(--wp--preset--color--paper-surface);
  font-size: var(--wp--preset--font-size--label);
  font-weight: 800;
  letter-spacing: .01em;
  cursor: pointer;
  transition: background-color .2s ease, box-shadow .2s ease;
}

.formlayer-form .formlayer-submit-btn:hover {
  background: var(--wp--preset--color--completion-green);
  border-color: var(--wp--preset--color--completion-green);
  box-shadow: 0 12px 28px rgba(23, 32, 42, .14);
}

.formlayer-form .formlayer-submit-btn:disabled {
  opacity: .5;
  cursor: not-allowed;
}

.formlayer-form .formlayer-form-status:not(:empty) {
  margin-bottom: 1.5rem;
  padding: 1rem 1.25rem;
  border: 1px solid var(--wp--preset--color--completion-green);
  border-radius: var(--wp--custom--radius--panel, 10px);
  background: var(--wp--preset--color--paper-surface);
  color: var(--wp--preset--color--authority-ink);
}

.formlayer-form .formlayer-form-status.error,
.formlayer-form .formlayer-form-status.formlayer-error {
  border-color: var(--wp--preset--color--warning-brick);
}

@media (prefers-reduced-motion: reduce) {
  .formlayer-form .formlayer-submit-btn { transition-duration: .01ms; }
}

/* The totals cards had `padding: 16px 0` — vertical only. Measured on the
   live page: the label started at the card's left border and the amount ended
   at its right border, both at exactly 0px inset. The money in a cart was
   touching the edge of the box it sits in. */
.wc-block-cart__sidebar .wc-block-components-totals-wrapper,
.wc-block-checkout__sidebar .wc-block-components-totals-wrapper,
.wp-block-woocommerce-checkout-order-summary-block .wc-block-components-totals-wrapper {
  padding-inline: clamp(1rem, 2.5vw, 1.5rem);
}

@media (max-width: 720px) {
  :root {
    --ek-page-gutter: var(--ek-mobile-gutter);
  }

  /* Adding 40px of panel padding left the line-items table 287px against a
     302px min-content width, so WooCommerce's auto table layout squeezed the
     last column and the price rendered as "$30." — a truncated amount in a
     cart, which is the one number on the site that must never look wrong.

     The room is reclaimed from the panel inset alone. Shrinking the thumbnail
     was tried first and was dead CSS: WooCommerce sizes that cell through its
     own container classes at `.is-medium table.wc-block-cart-items
     .wc-block-cart-items__row .wc-block-cart-item__image` — (0,4,1), and it
     switches those classes by observed width, not by viewport. Out-specifying
     a responsive system with a viewport media query wins the declaration and
     loses the behaviour. Left to WooCommerce; the padding is ours. */
  .wc-block-cart .wp-block-woocommerce-cart-items-block {
    padding: 1rem .75rem;
  }

  .ek-interior {
    padding-top: clamp(3.5rem, 12vw, 5rem) !important;
    padding-bottom: clamp(4rem, 14vw, 6rem) !important;
  }

  .ek-article-row {
    display: block;
  }

  .ek-article-row > .wp-block-post-date {
    margin-bottom: .75rem;
  }

  .ek-post-navigation,
  .ek-search-form .wp-block-search__inside-wrapper {
    align-items: stretch;
    flex-direction: column;
  }

  .ek-principles > .wp-block-column {
    padding: 1.5rem 0;
    border-right: 0;
    border-bottom: 1px solid var(--wp--preset--color--paper-rule);
  }

  .ek-principles > .wp-block-column:last-child {
    border-bottom: 0;
  }

  .woocommerce div.product {
    grid-template-columns: 1fr;
  }

  .woocommerce table.shop_table,
  .woocommerce-table,
  .wc-block-cart-items {
    display: block;
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
}

@media (prefers-reduced-motion: reduce) {
  .skip-link {
    transition-duration: .01ms;
  }
}

/* ---------- Cart: the remove control's hit area ----------
   WooCommerce ships this button at 24x24. That is exactly the WCAG 2.5.8
   minimum with no margin, and half the 44px target this theme gives every
   other standalone control: the three header icons in style.css and the
   stacked footer links in funnel.css both carry explicit 44px rules and
   comments saying why. The button was never broken — it was unhittable,
   which on a phone is the same thing.

   This is also the worst control to make someone fight. A buyer reaching for
   it has changed their mind, and an interface that will not let go of a
   $30 charge is the kind of thing people remember.

   Same construction as the header icons: a 44px box with the glyph centred
   inside it. The icon keeps its own size; only the hit area grows. */
.wc-block-cart-item__remove-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
}

/* ---------- The interior container ----------
   Root cause, verified 2026-08-16 by reading the live DOM rather than the theme.

   These pages resolve to Extendable's page-with-title.html, whose <main>
   carries margin:0, blockGap:0 and no padding on any side. The only vertical
   contribution on the whole page is the title band's
   var(--wp--preset--spacing--30) — 0.67rem, 10.72px. That single fact is the
   3px footer collision at 1440, the 0px collision at 360, and the identical
   11px clearance under the floating pill on all five pages.

   Padding rather than margin: Extendable sets margin inline on that element,
   so a margin rule would need !important to win the tie. Padding sidesteps
   the contest entirely.

   The top is deliberately smaller than the bottom. The header pill floats
   over the page and the first heading only has to clear it; the footer is a
   hard dark edge, and content arriving at it needs more room than content
   leaving the header.

   Commerce is included deliberately. Cart and checkout carry the identical
   collision, and padding touches no measure — none of the commerce measure
   reasoning above is disturbed by it. body:not(.home) keeps the front page on
   funnel.css, which owns its own rhythm. */
body:not(.home) main.wp-block-group {
  padding-top: clamp(2.5rem, 5vw, 4rem);
  padding-bottom: var(--wp--preset--spacing--section);
}

/* ---------- Multi-column blocks take the editorial measure ----------
   With hyphenation off, About's three principle headings still sat at 36px in
   186px columns — about five characters a line. The cause is that a
   three-column grid was being held to the 720px prose measure by the blanket
   rule above.

   The system rule: prose keeps the reading measure, multi-column blocks take
   the editorial one. Each column becomes roughly 290px instead of 186px.

   The three trailing :not() clauses are specificity ballast, and this rule
   must stay below the blanket rule it corrects. That rule scores (0,7,2) —
   two elements, then :not(.home) and .wp-block-post-content, then five more
   classes across its own exclusions. Written without the ballast this rule
   scores (0,4,2), loses silently, and every column stays at 720px while the
   stylesheet appears to say otherwise. With it, both score (0,7,2) and source
   order decides — which is why this block's position in the file is a
   requirement rather than a preference.

   The exclusions carry intent as well as weight: alignwide and alignfull are
   the author saying so in the editor, and .ek-commerce is this theme's own
   1080px width. :not(.woocommerce-page) follows the precedent set above for
   the page title — commerce runs at its own measure.

   No mobile branch is specified, and that is deliberate. Below 720px the
   columns already stack to full width and the headings already step down to
   about 23px, so this rule changes nothing there. */
body:not(.home):not(.woocommerce-page) main > .wp-block-post-content > .wp-block-columns:not(.alignwide):not(.alignfull):not(.ek-commerce) {
  max-width: var(--ek-editorial-width);
  margin-inline: auto;
}
