/* tokens.css */
/* Design tokens — see docs/superpowers/specs/2026-09-05-didicollectives-woocommerce-store-design.md §3
   Palette derived from the materials themselves: Adire indigo, coral bead, Aso-oke gold. */
:root {
  --didi-ground: #FFFFFF;  /* white page ground */
  --didi-band:   #F7F3EE;  /* warm band for alternating sections */
  --didi-surface: #F7F3EE; /* product imagery sits on a soft warm tint */
  --didi-border: #E7E1DA;
  --didi-ink:    #1F1A16;  /* warm near-black — body text */
  --didi-indigo: #1F3A5F;  /* Adire indigo — primary accent, links, buttons */
  --didi-coral:  #D2603A;  /* coral bead — secondary accent, badges, sale */
  --didi-gold:   #E8A33D;  /* Aso-oke gold thread — highlights, hover */
  --didi-muted:  #6B615A;
  --didi-coral-deep: #AE4726; /* coral darkened for small text on light grounds (5.1:1) */  /* secondary text, borders */

  --didi-on-dark: rgba(255, 255, 255, 0.88);      /* body copy on a photograph or ink band */
  --didi-on-dark-soft: rgba(255, 255, 255, 0.65); /* the quieter line under it */

  --didi-font-display: 'Inter', system-ui, -apple-system, sans-serif;
  --didi-font-ui: 'Inter', system-ui, -apple-system, sans-serif;
}

/* typography.css */
/* Self-hosted variable font. Latin subset only.
   Sans throughout, following the reference's register — Fraunces was
   removed with the serif direction, saving 36KB off every page. */
@font-face {
  font-family: 'Inter';
  src: url('https://didicollective.co.uk/wp-content/themes/didi/assets/fonts/inter-latin-variable.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-display: swap;
  font-style: normal;
}

body {
  font-family: var(--didi-font-ui);
  color: var(--didi-ink);
  background: var(--didi-ground);
}

/* Weight and tracking carry the hierarchy now that one family does
   everything. Headings run tight and heavy; labels run wide and small. */
h1, h2, h3, h4, h5, h6, .didi-display {
  font-family: var(--didi-font-ui);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.12;
}

.didi-eyebrow {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* chrome.css */
/* Announcement bar + typography bridge. Loaded on every page. */

/* --- Typography bridge -----------------------------------------------
   Blocksy prints its own :root variables inline in <head>, after our
   stylesheet links, so equal-specificity rules lose. The html prefix
   raises specificity enough to win regardless of order.
   Fonts are bridged in CSS rather than set through Blocksy's typography
   options, because those would make Blocksy enqueue Google Fonts and
   undo the self-hosting. */
html body {
  font-family: var(--didi-font-ui);
  background-color: var(--didi-ground);
  color: var(--didi-ink);
}

html h1,
html h2,
html h3,
html h4,
html h5,
html h6,
html .didi-display {
  font-family: var(--didi-font-ui);
  font-weight: 700;
  letter-spacing: -0.02em;
}

/* --- Announcement bar: stepped carousel -------------------------------
   Light ground with accent text and manual arrows, matching the reference. */
.didi-announce {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  background: var(--didi-band);
  /* Coral at 11px on this band is 3.47:1 — under AA. The deepened tone
     clears it at 5.1:1 and reads closer to the reference's brick red. */
  color: var(--didi-coral-deep);
  padding: 0.6rem 1rem;
  text-align: center;
}

.didi-announce__nav {
  border: 0;
  background: none;
  color: var(--didi-muted);
  cursor: pointer;
  padding: 0.35rem;
  line-height: 0;
  flex: none;
}

.didi-announce__nav:hover {
  color: var(--didi-ink);
}

.didi-announce__track {
  position: relative;
  margin: 0;
  padding: 0;
  list-style: none;
  flex: 1;
  min-width: 0;
  height: 1.2rem;
}

.didi-announce__item {
  position: absolute;
  inset: 0;
  margin: 0;
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.2rem;
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.didi-announce__item.is-active {
  opacity: 1;
  pointer-events: auto;
}

/* --- Utility row ------------------------------------------------------ */
.didi-utility {
  background: var(--didi-ground);
  border-bottom: 1px solid var(--didi-border);
}

.didi-utility__inner {
  max-width: 82rem;
  margin-inline: auto;
  padding: 0.5rem 1.25rem;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 1rem;
}

.didi-utility__link {
  font-size: 0.75rem;
  color: var(--didi-muted);
  text-decoration: none;
}

.didi-utility__link:hover {
  color: var(--didi-ink);
}

.didi-utility__divider {
  width: 1px;
  height: 1.1rem;
  background: var(--didi-border);
}

.didi-utility__social {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.didi-utility__social a {
  color: var(--didi-ink);
  display: block;
  line-height: 0;
}

.didi-utility__social a:hover {
  color: var(--didi-coral);
}

@media (max-width: 767.98px) {
  .didi-utility {
    display: none;
  }

  .didi-announce__item {
    font-size: 0.6875rem;
  }
}

/* --- Payment marks --------------------------------------------------- */

/* --- Product cards, site-wide -----------------------------------------
   Cards appear on the homepage, shop, category and material archives, so
   this lives in the always-loaded stylesheet. The card is the link: no
   button, no rating, no category label — image, name, price, nothing else. */
ul.products li.product a img,
ul.products li.product img {
  aspect-ratio: 4 / 5;
  object-fit: cover;
  width: 100%;
  display: block;
  transition: transform 0.5s cubic-bezier(0.2, 0.6, 0.2, 1);
}

ul.products li.product .ct-media-container,
ul.products li.product figure {
  overflow: hidden;
  background: var(--didi-surface);
}

ul.products li.product:hover img {
  transform: scale(1.04);
}

html ul.products li.product .woocommerce-loop-product__title {
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: 0;
  line-height: 1.35;
  margin: 0.75rem 0 0.25rem;
}

html ul.products li.product .price {
  font-size: 0.875rem;
  font-weight: 400;
  color: var(--didi-muted);
}

/* --- Announcement bar: quieter, wider tracking ------------------------ */
.didi-announce {
  padding: 0.55rem 1rem;
  gap: 1.75rem;
}

.didi-announce__item {
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
}

/* --- Secure checkout strip --------------------------------------------
   Plain text, no boxes. It sits between the last section and the footer, so
   a hairline above it and matched padding below stop it reading as a line of
   orphaned words floating in the gap. */
.didi-payments {
  width: min( var(--didi-container, 1440px), var(--theme-container-edge-spacing, 90vw) );
  margin-inline: auto;
  padding: 2rem 0 2.25rem;
  border-top: 1px solid var(--didi-border);
  text-align: center;
}

.didi-payments__label {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  margin: 0 0 0.85rem;
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--didi-ink);
}

/* The lock is the whole point of the label; without it "Secure checkout" is
   four words of grey text that read as a heading for the row below. */
.didi-payments__lock {
  flex: none;
}

.didi-payments__list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem 1.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.didi-payments__mark {
  border: 0;
  padding: 0;
  font-size: 0.75rem;
  letter-spacing: 0.02em;
  color: var(--didi-muted);
  white-space: nowrap;
}

/* A mark with artwork reserves its box before the file loads: these are the
   last images on the page, so an unreserved row would reflow the credit line
   under it. The min-width is the narrowest common acceptance mark. */
.didi-payments__mark--logo {
  display: flex;
  align-items: center;
  min-width: 2.375rem;
  min-height: 1.5rem;
}

.didi-payments__mark--logo img {
  display: block;
  width: auto;
  height: 1.5rem;
}

/* --- Size run on product cards ---------------------------------------- */
.didi-card-sizes {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin: 0.5rem 0 0;
  padding: 0;
  list-style: none;
}

.didi-card-size {
  font-size: 0.625rem;
  letter-spacing: 0.06em;
  color: var(--didi-muted);
  border: 1px solid var(--didi-border, #E5DCD1);
  padding: 0.15rem 0.4rem;
  line-height: 1.4;
}

/* --- Header ----------------------------------------------------------- */
/* Sticky via CSS rather than Blocksy's header-builder sticky option, which
   lives in the same nested config we avoid writing to. */
/* Blocksy sets `#header { position: relative }` — an ID selector, so the
   override has to out-rank it. The wrapper's `overflow: clip` also has to
   be released or sticky is confined to that clipped box. */
html body #site-wrapper,
html body > div:first-of-type {
  overflow: visible;
}

html body header#header.ct-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--didi-ground);
  border-bottom: 1px solid var(--didi-border);
}

/* Nav sits immediately beside the logo, with the icons pushed to the far
   right — Blocksy's default splits the row into two grid cells instead. */
html header.ct-header .ct-container {
  display: flex;
  align-items: center;
  gap: 2.5rem;
}

html header.ct-header .ct-container > *:first-child {
  flex: none;
}

html header.ct-header .ct-container > *:last-child {
  flex: 1;
  min-width: 0;
}

html header.ct-header [data-id="menu"] > ul {
  width: 100%;
  /* Blocksy right-aligns the menu; the reference runs it directly after
     the logo, with only the icons pushed to the far edge. */
  justify-content: flex-start;
}

html header.ct-header [data-id="menu"] {
  width: 100%;
}

/* Account, bag and search cluster at the far right of the nav row.
   :first-of-type would match the first <li> of that element type, not the
   first element carrying the class, so the icons need an explicit marker. */
.didi-util-lead {
  margin-left: auto;
}

html header.ct-header [data-id="menu"] > ul > li > a {
  --theme-text-transform: uppercase;
  --theme-font-weight: 600;
  --theme-font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

html header.ct-header [data-id="menu"] .sub-menu .ct-menu-link {
  --theme-text-transform: none;
  --theme-font-size: 0.8125rem;
  text-transform: none;
}

/* --- Brand logo -------------------------------------------------------
   A real logo now exists, so the typographic wordmark and woven-strip mark
   are retired (kept at assets/css/_wordmark-retired.css.txt and in git at
   9288c38). Blocksy prints the site title alongside the logo image, which
   would duplicate the name, so the text is hidden. */
html header.ct-header .site-title-container {
  display: none;
}

html header.ct-header .site-logo-container img {
  height: 58px;
  width: auto;
  max-width: none;
}

@media (max-width: 767.98px) {
  html header.ct-header .site-logo-container img {
    height: 40px;
  }
}

/* Bag count pill. Retiring the wordmark block removed these rules with it;
   they belong to the cart control, not the logo. */
.didi-cart-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.15rem;
  height: 1.15rem;
  padding: 0 0.25rem;
  border-radius: 999px;
  /* coral-deep, not coral: white on coral is 3.84:1 and this is 10px text,
     which needs 4.5. The deeper tone reads as the same accent at this size. */
  background: var(--didi-coral-deep);
  color: #fff;
  font-size: 0.625rem;
  line-height: 1;
  letter-spacing: 0;
}

/* --- Mobile bag ------------------------------------------------------- */
.didi-mobile-bag {
  display: none;
}

@media (max-width: 999.98px) {
  .didi-mobile-bag {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin-right: 1rem;
    color: var(--didi-ink);
  }

  .didi-mobile-bag svg {
    display: block;
  }
}

/* Blocksy's mobile header sets a 20px base, which inflates the badge
   against a 19px icon. Fixed units keep it proportionate. */
.didi-mobile-bag .didi-cart-count {
  font-size: 10px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
}

/* --- Stacked lockup ---------------------------------------------------
   The supplied full lockup (mark, wordmark, tagline) for the footer. */

/* --- Mega menu --------------------------------------------------------
   Blocksy's stock dropdown is a narrow dark column with dashed dividers.
   This replaces it with a full-width light panel: grouped columns, rules
   between them, and a promo tile. Desktop only — the mobile off-canvas
   keeps the nested list, which is the right pattern on a phone. */
@media (min-width: 1000px) {
  /* The panel spans the header container, so the item cannot be the
     positioning context. */
  html header.ct-header [data-id="menu"] > ul > li.menu-item-has-children {
    position: static;
  }

  html header.ct-header .ct-container {
    position: relative;
  }

  html header.ct-header [data-id="menu"] > ul > li > .sub-menu {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    width: 100%;
    max-width: none;
    min-width: 0;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr)) 22rem;
    align-items: start;
    gap: 0;
    padding: 2.25rem 0 2.5rem;
    background: var(--didi-ground);
    border: 1px solid var(--didi-border);
    border-top: 0;
    box-shadow: 0 18px 40px -24px rgba(31, 26, 22, 0.35);
    border-radius: 0;
  }

  /* Blocksy paints the dropdown dark and dashes the dividers. */
  html header.ct-header [data-id="menu"] .sub-menu {
    --dropdown-divider: none;
    --theme-box-shadow: none;
    --theme-border-radius: 0;
  }

  html header.ct-header [data-id="menu"] .sub-menu .ct-menu-link {
    --theme-link-initial-color: var(--didi-ink);
    color: var(--didi-ink);
  }

  /* Column: heading plus its links. Blocksy lays the item out as a flex
     row so the caret can sit beside the label, which puts the heading
     next to its list instead of above it. */
  html header.ct-header [data-id="menu"] > ul > li > .sub-menu > li {
    display: block;
    padding: 0 2rem;
    border-right: 1px solid var(--didi-border);
  }

  html header.ct-header [data-id="menu"] > ul > li > .sub-menu > li > .ct-menu-link,
  html header.ct-header [data-id="menu"] > ul > li > .sub-menu > li > .sub-menu {
    width: 100%;
  }

  html header.ct-header [data-id="menu"] > ul > li > .sub-menu > li > .sub-menu > li {
    display: block;
    width: 100%;
  }

  html header.ct-header [data-id="menu"] > ul > li > .sub-menu > li:nth-last-child(2) {
    border-right: 0;
  }

  /* The promo is taller than the link columns, so it was setting the panel's
     height and leaving a band of empty white under the links. Filling the
     row from an absolutely positioned child takes it out of the height
     calculation: the panel is now sized by the columns, and the tile matches
     them instead of overhanging. */
  html header.ct-header [data-id="menu"] > ul > li > .sub-menu > li.didi-mega-promo {
    border-right: 0;
    padding-right: 2rem;
    position: relative;
    align-self: stretch;
    min-height: 9rem;
  }

  html header.ct-header [data-id="menu"] .didi-mega-promo > a {
    position: absolute;
    inset: 0 2rem 0 0;
  }

  html header.ct-header [data-id="menu"] .didi-mega-promo img {
    height: 100%;
    aspect-ratio: auto;
  }

  /* Column heading. */
  html header.ct-header .sub-menu > li.didi-mega-heading > .ct-menu-link {
    font-size: 0.9375rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 0 0 0.4rem;
    display: block;
  }

  /* Third-level links. */
  html header.ct-header .sub-menu .sub-menu {
    position: static;
    display: block;
    opacity: 1;
    visibility: visible;
    transform: none;
    background: none;
    border: 0;
    box-shadow: none;
    padding: 0;
    min-width: 0;
    width: auto;
  }

  html header.ct-header .sub-menu .sub-menu .ct-menu-link {
    font-size: 0.875rem;
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    padding: 0.42rem 0;
    display: block;
  }

  html header.ct-header .sub-menu .sub-menu .ct-menu-link:hover {
    color: var(--didi-coral);
  }

  /* Blocksy adds caret icons to anything with children; the columns are
     not expandable, so they should not advertise that they are. */
  html header.ct-header .sub-menu .ct-toggle-dropdown-desktop {
    display: none;
  }



  /* --- Promo tile ----------------------------------------------------- */
  .didi-mega-promo a {
    position: relative;
    display: block;
    overflow: hidden;
    text-decoration: none;
  }

  .didi-mega-promo img {
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    display: block;
  }

  .didi-mega-promo__body {
    position: absolute;
    inset: auto 0 0 0;
    padding: 1.25rem;
    background: linear-gradient(to top, rgba(31, 26, 22, 0.75), transparent);
    color: #fff;
    text-align: center;
  }

  .didi-mega-promo__label {
    display: block;
    font-family: var(--didi-font-display);
    font-weight: 300;
    font-size: 1.0625rem;
    text-transform: uppercase;
    letter-spacing: 0.09em;
  }

  .didi-mega-promo__cta {
    display: inline-block;
    margin-top: 0.6rem;
    font-size: 0.6875rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    border: 1px solid rgba(255, 255, 255, 0.8);
    padding: 0.5rem 1.1rem;
  }

  .didi-mega-promo a:hover .didi-mega-promo__cta {
    background: #fff;
    color: var(--didi-ink);
  }
}

/* --- Animated nav underline -------------------------------------------
   A drawn rule rather than text-decoration, so it can animate. It wipes
   in from the left and out to the right by flipping transform-origin, so
   the line leaves the way the eye is already travelling instead of
   collapsing back on itself. Applies to every top-level item, and stays
   drawn on the current page. */
html header.ct-header [data-id="menu"] > ul > li > .ct-menu-link {
  position: relative;
}

html header.ct-header [data-id="menu"] > ul > li > .ct-menu-link::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  /* The link is a flex item spanning the full header row, so anchoring to
     its bottom edge puts the rule ~50px below the text. It is placed from
     the vertical centre instead, where the label actually sits. */
  top: 50%;
  margin-top: 0.72em;
  height: 1px;
  background: currentColor;
  /* Blocksy already uses .ct-menu-link::after for its own hover effect and
     leaves it at opacity 0, so it has to be re-shown here. */
  opacity: 1;
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 0.32s cubic-bezier(0.65, 0, 0.35, 1);
}

html header.ct-header [data-id="menu"] > ul > li:hover > .ct-menu-link::after,
html header.ct-header [data-id="menu"] > ul > li:focus-within > .ct-menu-link::after,
html header.ct-header [data-id="menu"] > ul > li.current-menu-item > .ct-menu-link::after,
html header.ct-header [data-id="menu"] > ul > li.current-menu-ancestor > .ct-menu-link::after,
html header.ct-header [data-id="menu"] > ul > li.current-menu-parent > .ct-menu-link::after {
  transform: scaleX(1);
  transform-origin: left center;
}

/* Items with a dropdown carry a caret; the rule underlines the label only. */
html header.ct-header [data-id="menu"] > ul > li.menu-item-has-children > .ct-menu-link::after {
  right: 1.5em;
}

/* The utility icons are not navigation labels and should not draw a rule. */
html header.ct-header [data-id="menu"] > ul > li.didi-util-item > .ct-menu-link::after {
  content: none;
}

@media (prefers-reduced-motion: reduce) {
  html header.ct-header [data-id="menu"] > ul > li > .ct-menu-link::after {
    transition: none;
  }
}

/* --- Mobile drawer ----------------------------------------------------
   The stock panel is a translucent dark sheet on an otherwise light, warm
   site: page content shows through it and the utility icons render as
   unlabelled glyphs. This makes it an opaque light panel that matches the
   rest of the site. */
@media (max-width: 999.98px) {
  html #offcanvas {
    --side-panel-width: min(92vw, 25rem);
  }

  /* Blocksy paints the panel at 0.98 alpha over the page, via
     [data-header*="type-1"] #offcanvas .ct-panel-inner. The attribute sits
     on <body> itself, so the override has to be body[data-header] rather
     than a descendant selector. */
  html body[data-header] #offcanvas .ct-panel-inner {
    background-color: var(--didi-ground);
    display: flex;
    flex-direction: column;
    height: 100%;
  }

  html #offcanvas .ct-panel-content {
    padding: 0;
  }

  /* The foot is pushed down with margin-top:auto, which only works if the
     wrappers above it fill the height. Blocksy renders two .ct-panel-content
     elements and hides one, so this is scoped to the panel that actually
     holds the drawer — setting display on both un-hid the spare and the
     whole menu rendered twice, stacked. */
  html #offcanvas .ct-panel-content:has(.didi-drawer__foot) {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    /* Blocksy scrolls .ct-panel-content-inner. This wrapper has to clip so
       the inner is constrained to the panel height and can actually scroll;
       left visible, the inner just grows and the overflow is unreachable. */
    overflow: hidden;
  }

  /* The close glyph is an inline SVG that takes its colour from a Blocksy
     variable, so setting colour on the button alone leaves it invisible
     against the now-light panel. */
  html #offcanvas .ct-toggle-close {
    color: var(--didi-ink);
    --theme-icon-color: var(--didi-ink);
    --theme-icon-hover-color: var(--didi-coral);
  }

  html #offcanvas .ct-toggle-close svg {
    fill: var(--didi-ink);
    color: var(--didi-ink);
  }

  /* Pin the account/bag block to the foot of the drawer rather than
     letting it float above dead space. */
  html #offcanvas .ct-panel-content-inner {
    display: flex;
    flex-direction: column;
    /* stretch, not centre: Blocksy centres panel children, which left the
       foot band narrower than the menu above it. */
    align-items: stretch;
    /* Fill the panel when the menu is short, so the foot sits at the
       bottom; grow past it when a section is expanded, so it scrolls. */
    flex: 1 0 auto;
    min-height: 100%;
    width: 100%;
  }

  /* --- Top: brand + search ------------------------------------------- */
  .didi-drawer__top {
    padding: 0.5rem 1.25rem 1.25rem;
  }

  .didi-drawer__logo img {
    height: 34px;
    width: auto;
    display: block;
    margin-bottom: 1.1rem;
  }

  .didi-drawer__search {
    display: flex;
    align-items: center;
    border: 1px solid var(--didi-border);
    background: #fff;
  }

  .didi-drawer__search input {
    flex: 1;
    min-width: 0;
    border: 0;
    background: transparent;
    font: inherit;
    /* iOS zooms the page when a focused input is under 16px. */
    font-size: 1rem;
    padding: 0.85rem 0.9rem;
    min-height: 48px;
  }

  .didi-drawer__search input:focus {
    outline: none;
  }

  .didi-drawer__search button {
    border: 0;
    background: transparent;
    color: var(--didi-ink);
    padding: 0 0.9rem;
    min-height: 48px;
    cursor: pointer;
    line-height: 0;
  }

  /* --- Menu ----------------------------------------------------------- */
  /* Blocksy draws its own divider between mobile menu items; combined with
     a border on the list item that yields doubled rules, and the sub-menus
     add more. Its divider is switched off so there is exactly one source. */
  html #offcanvas [data-id="mobile-menu"] {
    --theme-font-weight: 500;
    --theme-font-size: 1rem;
    --theme-link-initial-color: var(--didi-ink);
    --mobile-menu-divider: none;
  }

  html #offcanvas .ct-menu-link {
    color: var(--didi-ink);
    /* Comfortable thumb target. */
    min-height: 52px;
    display: flex;
    align-items: center;
    padding: 0 1.25rem;
    text-transform: none;
    letter-spacing: 0;
  }

  /* Exactly one rule per top-level item, and none after the last. */
  html #offcanvas [data-id="mobile-menu"] > ul > li {
    border-bottom: 1px solid var(--didi-border);
  }

  html #offcanvas [data-id="mobile-menu"] > ul > li:last-child {
    border-bottom: 0;
  }

  html #offcanvas [data-id="mobile-menu"] .sub-menu,
  html #offcanvas [data-id="mobile-menu"] .sub-menu li,
  html #offcanvas [data-id="mobile-menu"] .ct-sub-menu-parent {
    border: 0;
  }

  /* Expanded sub-menus were showing default list bullets. */
  html #offcanvas [data-id="mobile-menu"] .sub-menu {
    list-style: none;
    padding-left: 0;
    margin-left: 0;
  }

  html #offcanvas [data-id="mobile-menu"] .sub-menu li {
    list-style: none;
  }

  html #offcanvas [data-id="mobile-menu"] .sub-menu li::marker,
  html #offcanvas [data-id="mobile-menu"] .sub-menu li::before {
    content: none;
  }

  /* The second level holds the desktop mega panel's column headings —
     Garments, Sets & Layers — which are a layout device, not destinations.
     Leaving them as a second accordion meant two taps to reach a category
     on a phone, so they render as group labels and their children are
     revealed with the parent. */
  html #offcanvas [data-id="mobile-menu"] .sub-menu .sub-menu {
    display: block;
  }

  html #offcanvas [data-id="mobile-menu"] .sub-menu .ct-toggle-dropdown-mobile {
    display: none;
  }

  /* Group label. */
  html #offcanvas .sub-menu > li > .ct-sub-menu-parent > .ct-menu-link,
  html #offcanvas .sub-menu > li > .ct-menu-link {
    min-height: 0;
    padding: 1.1rem 1.25rem 0.35rem;
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--didi-muted);
  }

  /* Destinations. */
  html #offcanvas .sub-menu .sub-menu .ct-menu-link {
    min-height: 46px;
    padding: 0 1.25rem;
    font-size: 0.9375rem;
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    color: var(--didi-ink);
  }

  html #offcanvas .sub-menu .sub-menu .ct-menu-link:active {
    color: var(--didi-coral);
  }

  /* Breathing room before the next top-level item. */
  html #offcanvas [data-id="mobile-menu"] > ul > li > .sub-menu {
    padding-bottom: 0.75rem;
  }

  html #offcanvas .sub-menu li {
    border: 0;
  }

  /* The bare account/bag icons are reissued as labelled rows below. */
  html #offcanvas .didi-util-item {
    display: none;
  }

  html #offcanvas .ct-toggle-dropdown-mobile {
    color: var(--didi-muted);
    min-width: 52px;
    min-height: 52px;
  }

  /* --- Foot: account, bag, reassurance -------------------------------- */
  /* Blocksy sets a margin on every direct child of the panel inner via
     "#offcanvas .ct-panel-content-inner > *", which outranks a bare class
     selector and cancelled the auto margin that pins this to the bottom. */
  html #offcanvas .ct-panel-content-inner > .didi-drawer__foot {
    margin-top: auto;
  }

  .didi-drawer__foot {
    padding: 1.1rem 1.25rem 1.5rem;
    background: var(--didi-band);
  }

  .didi-drawer__tiles {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.625rem;
  }

  .didi-drawer__tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    min-height: 76px;
    padding: 0.75rem 0.5rem;
    border: 1px solid var(--didi-border);
    background: #fff;
    color: var(--didi-ink);
    text-decoration: none;
  }

  .didi-drawer__tile:active {
    background: var(--didi-band);
  }

  .didi-drawer__tile-label {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.8125rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    font-weight: 600;
  }

  .didi-drawer__social {
    display: flex;
    justify-content: center;
    gap: 1.5rem;
    margin: 1.1rem 0 0;
    padding: 0;
    list-style: none;
  }

  .didi-drawer__social a {
    color: var(--didi-ink);
    display: block;
    line-height: 0;
    padding: 0.4rem;
  }

  .didi-drawer__note {
    margin: 0.9rem 0 0;
    padding: 0;
    text-align: center;
    font-size: 0.6875rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--didi-muted);
  }
}

@media (max-width: 999.98px) {
  /* Group labels are headings, not destinations — every one pointed at the
     same parent category, which the explicit "View all" link now covers.
     Scoped to .ct-sub-menu-parent only: a heading has children so it is
     wrapped in one, whereas ".sub-menu > li > .ct-menu-link" also matched
     every category one level deeper and made them all untappable. */
  html #offcanvas .sub-menu > li > .ct-sub-menu-parent > .ct-menu-link {
    pointer-events: none;
  }

  html #offcanvas .sub-menu > li.didi-viewall > a {
    pointer-events: auto;
  }

  .didi-viewall a {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    min-height: 46px;
    padding: 0 1.25rem;
    margin-top: 0.5rem;
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--didi-ink);
    text-decoration: none;
  }
}

/* --- Layout container -------------------------------------------------
   The page was running three different widths: Blocksy's header at 1290,
   the utility row at 1312, and content sections at 1200 with 2rem padding,
   so section content began 45px inside the nav above it.

   One measurement now drives all of them. Blocksy's container width is a
   variable, so widening it moves the header too, and the sections add
   their own gutter on top of the same number. */
html body {
  --didi-container: 1440px;
  --didi-gutter: 2rem;
  --theme-normal-container-max-width: var(--didi-container);
}

/* Blocksy already varies its own edge spacing by breakpoint, so reusing
   that variable keeps every element on the same responsive gutter rather
   than inventing a second, competing one. */
html body .didi-utility__inner {
  width: min( var(--didi-container), var(--theme-container-edge-spacing, 90vw) );
  max-width: none;
  margin-inline: auto;
  padding-inline: 0;
}

/* === Newsletter ========================================================
   Site-wide since the signup moved into the footer: it used to live only in
   the homepage stylesheet, so every other page loaded the markup unstyled. */
/* --- Newsletter ------------------------------------------------------- */
.didi-newsletter__signup {
  margin-top: 1.75rem;
}

.didi-newsletter__note {
  margin: 0.85rem 0 0;
  font-size: 0.75rem;
  line-height: 1.5;
}

.didi-newsletter__done {
  font-weight: 600;
  color: var(--didi-ink);
}


/* Newsletter: an underline, not a boxed form. */
.didi-newsletter__form {
  display: flex;
  gap: 0;
  max-width: 30rem;
  margin: 0;
  border-bottom: 1px solid var(--didi-ink);
}

.didi-newsletter__form input {
  flex: 1;
  min-width: 0;
  min-height: 48px;
  border: 0;
  background: transparent;
  padding: 0 0 0.5rem;
  font: inherit;
  font-size: 1rem;
}

/* Removing the outline is only safe because the underline below thickens and
   takes the accent colour, so the field still shows focus. */
.didi-newsletter__form:focus-within {
  border-bottom-width: 2px;
  border-bottom-color: var(--didi-coral-deep);
}

.didi-newsletter__form input:focus {
  outline: none;
}

.didi-newsletter__form button {
  flex: none;
  min-height: 48px;
  border: 0;
  background: transparent;
  color: var(--didi-ink);
  padding: 0 0 0.5rem;
  font: inherit;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-size: 0.75rem;
  cursor: pointer;
}

.didi-newsletter__form button:hover,
.didi-newsletter__form button:focus {
  background: transparent;
  color: var(--didi-coral-deep);
}


/* The newsletter reads as one column on phones and as copy beside the form on
   desktop. Left-aligning the heading stack while the form kept the old
   centred auto margins left it stranded mid-section with the heading at the
   page spine — the form now shares that spine's column instead. */
@media (min-width: 768px) {
  .didi-fnews__inner {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 26rem);
    /* Rows are declared explicitly because the signup spans them with
       `1 / -1`, and -1 resolves against the last *explicit* line. With
       implicit rows it silently collapsed to row 1 and the form sat above
       the heading it belongs beside. */
    column-gap: 4rem;
    align-items: center;
  }

  .didi-fnews__copy {
    grid-column: 1;
  }

  .didi-newsletter__signup {
    grid-column: 2;
    margin-top: 0;
  }
}

/* === Footer ============================================================
   One tinted band carrying the whole footer: signup and socials on the left,
   the brand mark, then three link columns, with the credit line beneath.

   Blocksy's own footer is hidden rather than emptied through its footer
   builder, whose stored layout is deeply nested and fragile to edit. */
.ct-footer {
  display: none;
}

.didi-footer {
  background: var(--didi-band);
}

.didi-footer__inner {
  width: min( var(--didi-container, 1440px), var(--theme-container-edge-spacing, 90vw) );
  margin-inline: auto;
  padding-block: clamp(2.5rem, 6vw, 4rem);
  display: grid;
  gap: 2.5rem;
}

/* The signup heading is small and bold rather than the large light setting
   the page sections use: at the foot of the page it is a label for the field
   under it, not a section opening. */
.didi-footer__heading {
  margin: 0 0 1rem;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.4;
  color: var(--didi-ink);
}

.didi-footer__lede {
  margin: 0;
  max-width: 34ch;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--didi-muted);
}

.didi-footer__signup .didi-newsletter__signup {
  margin-top: 1.5rem;
}

.didi-footer__signup .didi-newsletter__form {
  max-width: 29rem;
}

.didi-footer__signup .didi-fsocial {
  margin-top: 1.75rem;
}

.didi-footer__mark img {
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 7.5rem;
}

.didi-fnav__heading {
  margin: 0 0 1.1rem;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--didi-ink);
}

.didi-fnav__col ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Excludes the social row, which is a horizontal list and was picking up the
   stacked links' top margin on all but its first item. */
.didi-fnav__col ul:not(.didi-fsocial) li + li {
  margin-top: 1.05rem;
}

.didi-fnav__col a {
  font-size: 1rem;
  color: var(--didi-muted);
  text-decoration: none;
}

.didi-fnav__col a:hover,
.didi-fnav__col a:focus-visible {
  color: var(--didi-ink);
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

/* The three icons are drawn at different heights inside a 24-unit box, and
   inline SVGs sit on the text baseline, so the row centres them explicitly. */
.didi-fsocial {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
  line-height: 0;
}

.didi-fsocial li {
  display: flex;
}

.didi-fsocial a {
  display: flex;
  color: var(--didi-ink);
}

.didi-fsocial svg {
  display: block;
}

.didi-fsocial a:hover,
.didi-fsocial a:focus-visible {
  color: var(--didi-coral-deep);
}

.didi-footer__base {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem 2rem;
  margin-top: 0.5rem;
}

.didi-footer__copy {
  margin: 0;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--didi-muted);
}

.didi-footer__tagline {
  display: block;
}

/* In the footer the marks are one line in the credit row, not a strip of
   their own, so the container width, rule and centring all come off. */
.didi-footer__base .didi-payments {
  width: auto;
  margin: 0;
  padding: 0;
  border: 0;
  text-align: left;
}

.didi-footer__base .didi-payments__label {
  justify-content: flex-start;
  margin-bottom: 0.5rem;
}

.didi-footer__base .didi-payments__list {
  justify-content: flex-start;
  gap: 0.4rem 0.9rem;
}

@media (min-width: 700px) {
  .didi-footer__inner {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    column-gap: 2.5rem;
  }

  .didi-footer__signup {
    grid-column: 1 / -1;
  }

  .didi-footer__mark {
    display: none;
  }

  .didi-footer__base {
    grid-column: 1 / -1;
  }
}

@media (min-width: 1000px) {
  .didi-footer__inner {
    /* Signup, brand mark, then the three link columns — the mark sits
       between them rather than beside the credit line, which is where the
       reference puts it and what keeps the left block from running wide. */
    grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr) repeat(3, minmax(0, 1fr));
    column-gap: 3rem;
  }

  .didi-footer__signup {
    grid-column: 1;
  }

  .didi-footer__mark {
    display: block;
    grid-column: 2;
    align-self: start;
  }
}

/* The welcome code, shown the moment someone signs up. Set apart from the
   thank-you line so it reads as something to copy rather than as prose. */
.didi-newsletter__code {
  margin: 0.6rem 0 0;
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--didi-muted);
}

.didi-newsletter__code span {
  display: inline-block;
  margin-right: 0.5rem;
  padding: 0.35rem 0.7rem;
  border: 1px dashed var(--didi-ink);
  color: var(--didi-ink);
  font-weight: 600;
  letter-spacing: 0.12em;
  /* Selectable in one gesture, so the code can be copied rather than typed. */
  user-select: all;
}

/* Legal row. Sits in the footer base beside the copyright, wrapping under it
   on narrow screens rather than squeezing the copyright line. */
.didi-footer__legal {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.25rem;
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.8125rem;
}

.didi-footer__legal a {
  color: inherit;
  opacity: 0.75;
}

.didi-footer__legal a:hover,
.didi-footer__legal a:focus-visible {
  opacity: 1;
}

/* system.css */
/* Design-system normalisation.
 *
 * Findings from a computed-style audit across the homepage, shop, a category,
 * a product, a material, the cart and a page. Each block below fixes one
 * measured inconsistency rather than a matter of taste; the numbers are the
 * counts of affected elements at the time of the audit.
 *
 * Loaded after chrome.css. Blocksy prints its own styles inline in the head,
 * so these rules carry the specificity to outrank them rather than relying on
 * source order.
 */

/* --- One typeface ------------------------------------------------------
   The audit found three in use: Inter on 502 elements, the system stack on
   264 — every .ct-menu-link, which is the header nav and the whole mega menu
   — and Georgia on the hero title, the lifestyle banner headings and the
   mega promo labels.

   The nav rendering in San Francisco next to Inter body copy is most of why
   the site read as "too many fonts": the two are similar enough that it
   looks like sloppy rendering rather than a deliberate pairing. Form
   controls do not inherit font by default, which is the other half. */
/* Blocksy drives its own components from custom properties rather than from
   font-family directly, and sets them on :root — so overriding the property
   on each consumer only reaches the ones we can name. Overriding the variable
   reaches all of them, including markup this theme never touches. */
:root {
  --theme-font-family: var(--didi-font-ui) !important;

  /* Blocksy rounds controls through `var(--x, 3px)` fallbacks, so the
     variables read as empty at root and only the fallback shows. Setting
     them is what actually squares the corners; the property overrides
     below cannot outrank every one of its scoped selectors. */
  --theme-border-radius: 0;
  --theme-button-border-radius: 0;
  --theme-form-border-radius: 0;
  --toggle-button-radius: 0;
  --badge-radius: 0;
}

html body,
html .ct-menu-link,
html .ct-header,
html .ct-footer,
html button,
html input,
html select,
html textarea,
html .wp-block-button__link {
  font-family: var(--didi-font-ui);
}

/* --- One weight scale --------------------------------------------------
   Five weights were in play (300/400/500/600/700). 700 sat on the nav, page
   and product titles and prices, against 300 on every section heading — the
   two extremes of the family on one screen. 600 carries the same emphasis
   without the clash. */
html .ct-menu-link,
html .ct-module-title,
html .woocommerce-Reviews-title,
html .comment-reply-title,
html .wc-block-grid__product-title,
html .posted_in,
html .tagged_as,
html .product_title,
html .page-title,
html .entry-summary .price,
html .entry-summary .price bdi,
html .didi-cart-count,
html .woocommerce-Price-currencySymbol {
  font-weight: 600;
}

/* Blocksy scopes the menu's weight by data attribute, which outranks a
   two-part selector, and it applies to the drawer copy of the menu as well
   as the header one. */
html .ct-menu-link {
  font-weight: 600 !important;
}

/* --- Square corners ----------------------------------------------------
   Blocksy rounds inputs, selects, buttons and media containers to 3px — 63
   elements. Every control this theme draws itself is square, so the two read
   as different design systems side by side. Pills and circles are opted back
   in individually below. */
html input:not([type="checkbox"]):not([type="radio"]),
html select,
html textarea,
html button,
html a.button,
html .wp-block-button__link,
html .ct-media-container,
html .ct-media-container img,
html ul.products li.product img,
html [class^="ct-"],
html [class*=" ct-"],
html .woocommerce-input-wrapper input {
  border-radius: 0;
}

/* The quantity stepper and the mega menu panel round themselves through
   rules the variables above do not reach. */
html .ct-increase,
html .ct-decrease,
html .quantity input.input-text,
html .ct-header .sub-menu {
  border-radius: 0 !important;
}

/* Genuinely round things stay round. */
html .didi-cart-count,
html .didi-swatch,
html .pswp .pswp__counter {
  border-radius: 999px;
}

html .didi-swatch__dot,
html .pswp .pswp__button,
html .pswp .pswp__button--arrow--left,
html .pswp .pswp__button--arrow--right {
  border-radius: 50%;
}

/* --- One accent, not three --------------------------------------------
   Indigo was still Blocksy's link colour and the add-to-cart background (18
   text uses, 13 backgrounds) while every section rebuilt since uses ink with
   coral for hover, and the cross-sell button is gold. Three competing action
   colours on one page is one too many for a shop this size.

   Ink is the primary action, which is also what the reference storefronts do;
   coral is reserved for hover and small emphasis; gold stays on the single
   secondary cross-sell button. Indigo remains a palette token for editorial
   use, but no longer dresses controls. */
:root {
  --theme-link-initial-color: var(--didi-ink) !important;
  --theme-link-hover-color: var(--didi-coral-deep) !important;
  --theme-button-background-initial-color: var(--didi-ink) !important;
  --theme-button-background-hover-color: var(--didi-coral-deep) !important;
}

html .single_add_to_cart_button,
html .wc-block-components-button,
html .wp-block-button__link {
  background-color: var(--didi-ink);
  color: #fff;
}

html .single_add_to_cart_button:hover,
html .single_add_to_cart_button:focus,
html .wc-block-components-button:hover,
html .wp-block-button__link:hover {
  background-color: var(--didi-coral-deep);
  color: #fff;
}

/* WooCommerce's required marker is pure #C00, which is in no palette here
   and is the only saturated red on the site. */
html .required,
html .wc-block-components-validation-error {
  color: var(--didi-coral-deep) !important;
}

/* Blocksy's star rating is #FDA256, a sixth accent nobody chose. Gold is the
   palette's highlight and is what the rest of the site uses for it. */
/* Gold on white is 2.16:1 — under the 3:1 a non-text control needs. This is
   the same hue carried far enough to be seen: 4.94:1. */
html .star-rating,
html .stars a,
html .comment-form-rating .stars a {
  color: #96671A;
}

/* WooCommerce greys the add-to-cart button until a variation is chosen, at
   3.31:1 — the label on the primary action is unreadable at exactly the
   moment a shopper is trying to work out why they cannot buy. Disabled
   controls are exempt from the contrast rule; that is not a reason to leave
   the most important button on the page illegible. */
html .single_add_to_cart_button.disabled,
html .single_add_to_cart_button:disabled,
html .wc-block-components-button:disabled {
  background-color: var(--didi-muted);
  color: #fff;
  /* Forced: WooCommerce also halves the opacity, which puts the label back
     under the threshold however dark the background is. */
  opacity: 1 !important;
}

/* --- Motion ------------------------------------------------------------
   A short rise and fade as a section first comes into view, and the link
   underlines that go with it.

   The hidden state is only ever applied when the script has run and has
   already checked prefers-reduced-motion — hence .didi-reveal-on on the
   root. Without JavaScript, or with reduced motion asked for, nothing is
   hidden and nothing moves. */
.didi-reveal-on .didi-reveal {
  opacity: 0;
  transform: translateY(10px);
}

/* Short and shallow. The point is that the block feels placed rather than
   already there; anything longer starts reading as a page that is still
   loading. */
.didi-reveal-on .didi-reveal.is-revealed {
  opacity: 1;
  transform: none;
  transition:
    opacity 0.45s cubic-bezier(0.2, 0.6, 0.2, 1),
    transform 0.45s cubic-bezier(0.2, 0.6, 0.2, 1);
}

/* --- Link underlines ---------------------------------------------------
   One behaviour for every text link that is not already a button: a rule
   that grows from the left on hover and on keyboard focus. */
html .didi-fnav__col a,
html .didi-assurance a,
html .didi-story__origins a .didi-story__material,
html .didi-material-link {
  position: relative;
  text-decoration: none;
}

html .didi-fnav__col a::after,
html .didi-assurance a::after,
html .didi-material-link::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: -0.15em;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.28s cubic-bezier(0.2, 0.6, 0.2, 1);
}

html .didi-fnav__col a:hover::after,
html .didi-fnav__col a:focus-visible::after,
html .didi-assurance a:hover::after,
html .didi-assurance a:focus-visible::after,
html .didi-material-link:hover::after,
html .didi-material-link:focus-visible::after {
  transform: scaleX(1);
}

/* The footer links already carried a plain underline on hover; the animated
   rule replaces it rather than sitting under a second line. */
html .didi-fnav__col a:hover,
html .didi-fnav__col a:focus-visible {
  text-decoration: none;
}

@media (prefers-reduced-motion: reduce) {
  html .didi-fnav__col a::after,
  html .didi-assurance a::after,
  html .didi-material-link::after {
    transition: none;
  }
}

/* --- Unfinished copy ---------------------------------------------------
   Scaffolding, not design. Every note marked .didi-todo is a fact only the
   owner can supply — a courier rate, a measurement, a return window — and
   each one is loud on purpose so it cannot reach launch unnoticed. The site
   is closed to search engines while any of these remain; see
   docs/launch-checklist.md. Delete this rule once the notes are gone. */
.didi-todo {
  border-left: 3px solid var(--didi-coral-deep);
  background: rgba(232, 163, 61, 0.12);
  padding: 0.9rem 1.1rem;
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--didi-ink);
}

.didi-todo strong {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.75rem;
  display: block;
  margin-bottom: 0.3rem;
  color: var(--didi-coral-deep);
}

/* --- Text pages --------------------------------------------------------
   About, Size Guide, Shipping & Returns, Contact. Two things were wrong: the
   content headings were rendering larger than the page title above them, so
   the hierarchy read backwards, and body text ran the full container — about
   150 characters a line, roughly twice a comfortable measure. */
/* The measure is set on the prose itself, not on the content wrapper.
   Capping the wrapper squeezed the materials index grid to half width — any
   page with a grid or a shortcode in it would have had the same problem. And
   the lists are matched by their editor class, because the material tiles are
   a <ul> too and a bare `> ul` caught those as well. */
body.page:not(.home) .entry-content > p,
body.page:not(.home) .entry-content > h2,
body.page:not(.home) .entry-content > h3,
body.page:not(.home) .entry-content > ul.wp-block-list,
body.page:not(.home) .entry-content > ol.wp-block-list {
  max-width: 68ch;
}

body.page:not(.home) .page-title {
  font-weight: 300;
  font-size: clamp(1.5rem, 5vw, 2.25rem);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  line-height: 1.2;
}

body.page:not(.home) .entry-content h2 {
  margin-top: 2.5rem;
  font-weight: 600;
  font-size: 1.125rem;
  letter-spacing: 0;
  line-height: 1.35;
}

body.page:not(.home) .entry-content h3 {
  font-weight: 600;
  font-size: 1rem;
}

body.page:not(.home) .entry-content p,
body.page:not(.home) .entry-content li {
  line-height: 1.7;
}

body.page:not(.home) .entry-content li + li {
  margin-top: 0.4rem;
}

/* Legal and text pages.
   The page title sits inside Blocksy's constrained hero, which is 90vw
   centred, giving a 5vw gutter. The content wrapper below it is full-bleed,
   so its children were centred against a different edge and the heading never
   lined up with the text it introduced. Match the hero's width here, then pin
   the children to its left edge below. */
body.page:not(.home) .entry-content {
  width: min(var(--theme-container-edge-spacing, 90vw), 100%);
  margin-inline: auto;
}

body.page:not(.home) .entry-content > p,
body.page:not(.home) .entry-content > h2,
body.page:not(.home) .entry-content > h3,
body.page:not(.home) .entry-content > ul.wp-block-list,
body.page:not(.home) .entry-content > ol.wp-block-list,
body.page:not(.home) .entry-content > .didi-todo {
  /* WordPress's own block layout centres every child with
     "margin-left: auto !important", so specificity alone cannot move them:
     the override has to be !important too. Without it the heading sits on the
     container's left edge while the paragraph it introduces floats to the
     middle, and the two never share an edge. */
  margin-left: 0 !important;
  margin-right: 0 !important;
}

/* The sentence that opens a policy is doing more work than the ones after it. */
body.page:not(.home) .entry-content .didi-lead {
  font-size: 1.0625rem;
  line-height: 1.65;
  color: var(--didi-ink);
  max-width: 62ch;
}

/* When the page last changed. Quiet, but a legal page has to carry it. */
body.page:not(.home) .entry-content .didi-legal-meta {
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--didi-muted);
  margin: 0 0 2rem;
}

/* A rule above each section gives the eye somewhere to rest in a long
   document, and makes the sections scannable without a contents list. */
body.page:not(.home) .entry-content > h2 {
  margin-top: 3rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--didi-border);
  max-width: 68ch;
}

body.page:not(.home) .entry-content > h2:first-of-type {
  margin-top: 2.5rem;
}

body.page:not(.home) .entry-content > p + p {
  margin-top: 1.1rem;
}

/* Lists of processors and exemptions read better with room around them. */
body.page:not(.home) .entry-content > ul.wp-block-list {
  margin-top: 1.1rem;
  padding-left: 1.1rem;
}

body.page:not(.home) .entry-content > ul.wp-block-list li::marker {
  color: var(--didi-coral-deep);
}

body.page:not(.home) .entry-content a {
  overflow-wrap: anywhere;
}

/* The scaffolding notes are questions for the owner, not part of the policy.
   They should read as an annotation rather than as a clause. */
body.page:not(.home) .entry-content .didi-todo {
  max-width: 68ch;
  margin-top: 1.25rem;
}

/* cart-drawer.css */
/* The bag drawer.
   Slides from the right over a scrim, because a shopper's attention is on the
   button they just pressed and the confirmation should arrive next to it
   rather than at the top of the page. */
.didi-bag {
  position: fixed;
  /* inset alone, deliberately. An explicit height here fights the admin-bar
     offset below: the box would keep its full height and simply start lower,
     pushing the checkout button off the bottom by exactly the height of the
     bar. Letting top and bottom define the box keeps both cases right. */
  inset: 0;
  z-index: 9999;
}

.didi-bag[hidden] {
  display: none !important;
}

.didi-bag__scrim {
  position: absolute;
  inset: 0;
  background: rgba(20, 16, 13, 0.42);
  opacity: 0;
  transition: opacity 0.24s ease;
}

.didi-bag.is-open .didi-bag__scrim {
  opacity: 1;
}

.didi-bag__panel {
  position: absolute;
  top: 0;
  right: 0;
  /* Height comes from the container rather than the viewport: the container
     is already inset for mobile browser chrome and for the admin bar, so
     measuring the viewport directly would push the checkout button below the
     fold at the exact moment it is needed. */
  height: 100%;
  max-height: 100%;
  width: min(26rem, 100%);
  background: var(--didi-ground, #fff);
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  transition: transform 0.26s cubic-bezier(0.32, 0.72, 0, 1);
  box-shadow: -12px 0 40px rgba(20, 16, 13, 0.14);
}

.didi-bag.is-open .didi-bag__panel {
  transform: translateX(0);
}

.didi-bag__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.25rem 1.25rem 1rem;
  border-bottom: 1px solid var(--didi-border, #E7E1DA);
  flex: 0 0 auto;
}

.didi-bag__title {
  margin: 0;
  font-size: 0.8125rem;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.didi-bag__close {
  background: none;
  border: 0;
  padding: 0.25rem;
  cursor: pointer;
  color: var(--didi-ink, #1F1A16);
  line-height: 0;
}

.didi-bag__close:hover,
.didi-bag__close:focus-visible {
  color: var(--didi-coral-deep, #AE4726);
}

/* The body scrolls, the footer does not: the subtotal and checkout stay in
   view however many pieces are in the bag. */
.didi-bag__body {
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

.didi-bag__inner {
  display: flex;
  flex-direction: column;
  min-height: 100%;
}

.didi-bag__items {
  list-style: none;
  margin: 0;
  padding: 0;
  flex: 1 1 auto;
}

.didi-bag__item {
  display: grid;
  grid-template-columns: 4.5rem 1fr auto;
  gap: 0.875rem;
  padding: 1.125rem 1.25rem;
  border-bottom: 1px solid var(--didi-border, #E7E1DA);
  align-items: start;
}

.didi-bag__thumb img {
  width: 100%;
  height: auto;
  display: block;
  background: var(--didi-surface, #F7F3EE);
}

.didi-bag__detail {
  min-width: 0;
}

.didi-bag__name {
  margin: 0 0 0.25rem;
  font-size: 0.9375rem;
  line-height: 1.35;
}

.didi-bag__name a {
  color: inherit;
  text-decoration: none;
}

.didi-bag__name a:hover,
.didi-bag__name a:focus-visible {
  text-decoration: underline;
}

.didi-bag__meta {
  margin: 0 0 0.35rem;
  font-size: 0.8125rem;
  color: var(--didi-muted, #6B615A);
  line-height: 1.4;
}

.didi-bag__line {
  margin: 0;
  font-size: 0.875rem;
  display: flex;
  gap: 0.4rem;
  align-items: baseline;
}

.didi-bag__qty {
  color: var(--didi-muted, #6B615A);
}

.didi-bag__price {
  font-weight: 500;
}

.didi-bag__price del {
  color: var(--didi-muted, #6B615A);
  font-weight: 400;
  margin-right: 0.3rem;
}

.didi-bag__remove {
  color: var(--didi-muted, #6B615A);
  text-decoration: none;
  font-size: 1.25rem;
  line-height: 1;
  padding: 0.15rem 0.35rem;
}

.didi-bag__remove:hover,
.didi-bag__remove:focus-visible {
  color: var(--didi-coral-deep, #AE4726);
}

.didi-bag__foot {
  flex: 0 0 auto;
  padding: 1.125rem 1.25rem calc(1.25rem + env(safe-area-inset-bottom));
  border-top: 1px solid var(--didi-border, #E7E1DA);
  background: var(--didi-ground, #fff);
}

.didi-bag__subtotal {
  display: flex;
  justify-content: space-between;
  margin: 0 0 0.3rem;
  font-size: 0.9375rem;
}

.didi-bag__subtotal span:first-child {
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: 0.75rem;
  align-self: center;
  color: var(--didi-muted, #6B615A);
}

.didi-bag__note {
  margin: 0 0 0.875rem;
  font-size: 0.75rem;
  color: var(--didi-muted, #6B615A);
}

.didi-bag__checkout {
  display: block;
  text-align: center;
  padding: 0.9375rem 1rem;
  background: var(--didi-ink, #1F1A16);
  color: #fff;
  text-decoration: none;
  font-size: 0.8125rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transition: background 0.18s ease;
}

.didi-bag__checkout:hover,
.didi-bag__checkout:focus-visible {
  background: var(--didi-coral-deep, #AE4726);
  color: #fff;
}

.didi-bag__empty {
  padding: 3rem 1.25rem;
  text-align: center;
  color: var(--didi-muted, #6B615A);
}

.didi-bag__continue {
  display: inline-block;
  margin-top: 0.75rem;
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--didi-ink, #1F1A16);
}

@media (prefers-reduced-motion: reduce) {
  .didi-bag__panel,
  .didi-bag__scrim {
    transition: none;
  }
}

/* WooCommerce renders item variations as a definition list. Lay it out on one
   line so "Size: S, Colourway: Yellow" reads as a caption rather than a table. */
.didi-bag__meta dl,
.didi-bag__meta dt,
.didi-bag__meta dd,
.didi-bag__meta p {
  display: inline;
  margin: 0;
  font-size: 0.8125rem;
  color: var(--didi-muted, #6B615A);
  line-height: 1.4;
}

.didi-bag__meta dt {
  font-weight: 400;
}

.didi-bag__meta dt::after {
  content: " ";
}

.didi-bag__meta dd + dt::before {
  content: " · ";
}

/* WordPress's admin bar is fixed at the top of the viewport with a z-index
   above this drawer, so a panel pinned to inset:0 has its header hidden
   underneath it. Only logged-in staff see the bar, but they are the people
   opening this all day. The bar is 32px, and 46px below WordPress's own 782px
   breakpoint. */
body.admin-bar .didi-bag {
  top: 32px;
}

@media screen and (max-width: 782px) {
  body.admin-bar .didi-bag {
    top: 46px;
  }
}

/* WooCommerce's own "View cart" link, which its JavaScript inserts next to a
   loop button after an AJAX add. The drawer opens on the same event and says
   the same thing better, so this is a second, quieter route to the bag sitting
   directly under the first. Hidden here and removed from the DOM in
   cart-drawer.js, because hiding alone leaves it in the tab order and
   announced to a screen reader. */
.added_to_cart,
.added_to_cart.wc-forward {
  display: none !important;
}

/* Quantity stepper. */
.didi-bag__line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin: 0.4rem 0 0;
}

.didi-bag__stepper {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--didi-border, #E7E1DA);
}

.didi-bag__step {
  width: 1.75rem;
  height: 1.75rem;
  border: 0;
  background: none;
  cursor: pointer;
  font-size: 0.9375rem;
  line-height: 1;
  color: var(--didi-ink, #1F1A16);
  padding: 0;
}

.didi-bag__step:hover:not(:disabled),
.didi-bag__step:focus-visible:not(:disabled) {
  background: var(--didi-surface, #F7F3EE);
}

.didi-bag__step:disabled {
  opacity: 0.35;
  cursor: default;
}

.didi-bag__count {
  min-width: 1.75rem;
  text-align: center;
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
}

/* While a change is in flight the numbers on screen are briefly wrong, so
   dim them rather than invite a second click on a stale figure. */
.didi-bag.is-busy .didi-bag__items,
.didi-bag.is-busy .didi-bag__foot {
  opacity: 0.55;
  pointer-events: none;
  transition: opacity 0.12s ease;
}

/* The add confirmation.
   A card rather than a drawer: it names the piece, offers both ways onward and
   says how far off free delivery the bag is, without covering the page the
   shopper was reading. Anchored under the bag it refers to on a desktop, and
   across the bottom of a phone where a thumb reaches. */
.didi-added {
  position: fixed;
  z-index: 9998;
  left: 0.75rem;
  right: 0.75rem;
  bottom: calc(0.75rem + env(safe-area-inset-bottom));
  opacity: 0;
  transform: translateY(0.5rem);
  transition: opacity 0.2s ease, transform 0.2s ease;
  pointer-events: none;
}

.didi-added[hidden] {
  display: none !important;
}

.didi-added.is-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.didi-added__panel {
  background: var(--didi-ground, #fff);
  border: 1px solid var(--didi-border, #E7E1DA);
  box-shadow: 0 16px 44px rgba(20, 16, 13, 0.18);
  max-width: 22rem;
  margin: 0 auto;
}

.didi-added__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.875rem 1rem;
  border-bottom: 1px solid var(--didi-border, #E7E1DA);
}

.didi-added__title {
  margin: 0;
  font-size: 0.9375rem;
  font-weight: 600;
}

.didi-added__close {
  background: none;
  border: 0;
  padding: 0.2rem;
  cursor: pointer;
  line-height: 0;
  color: var(--didi-muted, #6B615A);
}

.didi-added__close:hover,
.didi-added__close:focus-visible {
  color: var(--didi-ink, #1F1A16);
}

.didi-added__body {
  padding: 1rem;
}

.didi-added__item {
  display: grid;
  grid-template-columns: 4rem 1fr;
  gap: 0.875rem;
  margin-bottom: 1rem;
}

.didi-added__thumb img {
  width: 100%;
  height: auto;
  display: block;
  background: var(--didi-surface, #F7F3EE);
}

.didi-added__name {
  margin: 0 0 0.25rem;
  font-size: 0.875rem;
  line-height: 1.35;
}

.didi-added__price {
  margin: 0;
  font-size: 0.875rem;
  font-weight: 500;
}

.didi-added__view,
.didi-added__checkout {
  display: block;
  text-align: center;
  padding: 0.75rem 1rem;
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  transition: background 0.18s ease, color 0.18s ease;
}

.didi-added__view {
  border: 1px solid var(--didi-ink, #1F1A16);
  color: var(--didi-ink, #1F1A16);
  margin-bottom: 0.5rem;
}

.didi-added__view:hover,
.didi-added__view:focus-visible {
  background: var(--didi-surface, #F7F3EE);
}

.didi-added__checkout {
  background: var(--didi-ink, #1F1A16);
  color: #fff;
  border: 1px solid var(--didi-ink, #1F1A16);
}

.didi-added__checkout:hover,
.didi-added__checkout:focus-visible {
  background: var(--didi-coral-deep, #AE4726);
  border-color: var(--didi-coral-deep, #AE4726);
  color: #fff;
}

/* The nudge. Amber while there is something to do about it, green once the
   threshold is met, because those are different messages. */
.didi-added__shipping {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0.75rem 0 0;
  padding: 0.625rem 0.75rem;
  font-size: 0.8125rem;
  line-height: 1.35;
  background: rgba(232, 163, 61, 0.14);
  color: var(--didi-ink, #1F1A16);
}

.didi-added__shipping.is-met {
  background: rgba(31, 94, 58, 0.1);
  color: #1F5E3A;
}

.didi-added__shipping svg {
  flex: 0 0 auto;
}

.didi-added__shipping .amount {
  font-weight: 600;
}

@media (min-width: 782px) {
  .didi-added {
    left: auto;
    right: 1.25rem;
    top: 6.5rem;
    bottom: auto;
    transform: translateY(-0.5rem);
    width: 22rem;
  }

  body.admin-bar .didi-added {
    top: calc(6.5rem + 32px);
  }
}

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

/* consent.css */
/* Cookie consent.
   Reject and Accept are the same size, weight and prominence. A banner where
   accepting is a button and refusing is a grey link is not consent freely
   given, and the ICO has said so plainly. */
.didi-consent {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 9997;
  background: var(--didi-ink, #1F1A16);
  color: rgba(255, 255, 255, 0.92);
  transform: translateY(100%);
  transition: transform 0.26s cubic-bezier(0.32, 0.72, 0, 1);
}

.didi-consent[hidden] {
  display: none !important;
}

.didi-consent.is-visible {
  transform: translateY(0);
}

.didi-consent__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 2rem;
  justify-content: space-between;
  max-width: 76rem;
  margin: 0 auto;
  padding: 1.125rem clamp(1rem, 5vw, 2rem) calc(1.125rem + env(safe-area-inset-bottom));
}

.didi-consent__text {
  flex: 1 1 22rem;
  min-width: 0;
}

.didi-consent__title {
  margin: 0 0 0.25rem;
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--didi-gold, #E8A33D);
}

.didi-consent__text p {
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.55;
}

.didi-consent__text a {
  color: #fff;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.didi-consent__actions {
  display: flex;
  gap: 0.625rem;
  flex: 0 0 auto;
}

.didi-consent__btn {
  flex: 1 1 auto;
  min-width: 7rem;
  padding: 0.75rem 1.5rem;
  font: inherit;
  font-size: 0.8125rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.55);
  background: none;
  color: #fff;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}

.didi-consent__btn:hover,
.didi-consent__btn:focus-visible {
  background: rgba(255, 255, 255, 0.12);
}

.didi-consent__btn--accept {
  background: #fff;
  color: var(--didi-ink, #1F1A16);
  border-color: #fff;
}

.didi-consent__btn--accept:hover,
.didi-consent__btn--accept:focus-visible {
  background: var(--didi-gold, #E8A33D);
  border-color: var(--didi-gold, #E8A33D);
  color: var(--didi-ink, #1F1A16);
}

body.admin-bar .didi-consent {
  /* nothing: the admin bar is at the top and this sits at the bottom. */
}

@media (max-width: 600px) {
  .didi-consent__actions {
    width: 100%;
  }
}

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

/* product.css */
/* Product page. Loaded only on single products — see functions.php. */
.didi-material-link {
  display: inline-block;
  margin: 1rem 0;
  color: var(--didi-ink);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  font-size: 0.9375rem;
}

.didi-material-link:hover,
.didi-material-link:focus {
  color: var(--didi-coral);
}

.didi-sticky-cart {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  padding-bottom: calc(0.75rem + env(safe-area-inset-bottom));
  background: var(--didi-ground);
  border-top: 1px solid rgba(31, 26, 22, 0.12);
}

.didi-sticky-cart__name {
  flex: 1;
  font-size: 0.875rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.didi-sticky-cart__price {
  font-weight: 600;
  white-space: nowrap;
}

/* Matches the main add-to-cart button: one primary action colour. */
.didi-sticky-cart__button {
  background: var(--didi-ink);
  color: var(--didi-ground);
  border: 0;
  border-radius: 999px;
  /* 44px minimum touch target. */
  padding: 0.75rem 1.5rem;
  min-height: 44px;
  font: inherit;
  cursor: pointer;
}

.didi-sticky-cart__button:hover,
.didi-sticky-cart__button:focus {
  background: var(--didi-coral);
}

/* Desktop keeps the real add-to-cart in view, so the bar is redundant. */
@media (min-width: 768px) {
  .didi-sticky-cart { display: none; }
}

/* Shown on cart and checkout for non-UK destinations. */
.didi-duty-notice {
  background: rgba(232, 163, 61, 0.12);
  border-left: 3px solid var(--didi-gold);
  padding: 0.875rem 1rem;
  margin: 1rem 0;
  font-size: 0.875rem;
  line-height: 1.55;
}

/* --- Gallery lightbox --------------------------------------------------
   The magnifier opens the photograph full screen with the rest of the
   gallery alongside. WooCommerce's in-place magnifier is turned off in
   PHP: it enlarges inside the frame, which loses sight of the garment.
   The photograph itself is a control too: tapping it selects the colour
   it shows, so it gets a plain pointer rather than a zoom cursor. */
.didi-gallery .flexy-view img {
  cursor: pointer;
}

/* Blocksy prints the magnifier as a bare emoji anchor. It is the affordance
   that tells people the image opens, so it gets a real button. */
.woocommerce-product-gallery__trigger {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  font-size: 0.9rem;
  line-height: 1;
  text-decoration: none;
  background: rgba(255, 255, 255, 0.92);
  color: var(--didi-ink);
  box-shadow: 0 2px 10px rgba(31, 26, 22, 0.18);
  transition: background 0.2s ease;
}

.woocommerce-product-gallery__trigger:hover,
.woocommerce-product-gallery__trigger:focus-visible {
  background: #fff;
}

.woocommerce-product-gallery {
  position: relative;
}

/* --- Lightbox chrome ---------------------------------------------------
   PhotoSwipe's default skin is a dark overlay with a sprite-sheet toolbar.
   This makes it a full-screen white viewer with round controls: the garment
   is the only thing on screen, and the photography is shot on pale studio
   grounds that a dark backdrop fights. */
/* PhotoSwipe animates .pswp__bg's opacity and holds it at 0.7, which left
   the page readable behind the viewer. Painting the container itself makes
   the backdrop solid regardless of what the skin does to that layer. */
.pswp {
  background: #fff;
}

.pswp__bg {
  background: #fff;
}

.pswp__caption,
.pswp__button--share,
.pswp__button--fs,
.pswp__preloader {
  display: none !important;
}

/* The sprite sheet goes; every control is drawn from an inline SVG so it
   scales and needs no extra request. */
.pswp .pswp__button,
.pswp .pswp__button--arrow--left,
.pswp .pswp__button--arrow--right,
.pswp .pswp__counter {
  box-sizing: border-box;
}

.pswp .pswp__button,
.pswp .pswp__button--arrow--left,
.pswp .pswp__button--arrow--right {
  width: 44px;
  height: 44px;
  flex: none;
  background-color: #fff !important;
  border: 1px solid var(--didi-border);
  border-radius: 50%;
  box-shadow: 0 2px 12px rgba(31, 26, 22, 0.12);
  opacity: 1;
  background-repeat: no-repeat !important;
  background-position: center !important;
  background-size: 22px 22px !important;
}

.pswp .pswp__button:hover,
.pswp .pswp__button--arrow--left:hover,
.pswp .pswp__button--arrow--right:hover {
  background-color: var(--didi-band) !important;
}

.pswp .pswp__button--close { background-image: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2222%22%20height%3D%2222%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%231F1A16%22%20stroke-width%3D%221.6%22%20stroke-linecap%3D%22round%22%3E%3Cpath%20d%3D%22M6%206l12%2012M18%206L6%2018%22%2F%3E%3C%2Fsvg%3E') !important; }
.pswp .pswp__button--zoom { background-image: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2222%22%20height%3D%2222%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%231F1A16%22%20stroke-width%3D%221.6%22%20stroke-linecap%3D%22round%22%3E%3Ccircle%20cx%3D%2211%22%20cy%3D%2211%22%20r%3D%226.5%22%2F%3E%3Cpath%20d%3D%22M15.8%2015.8L21%2021M11%208.4v5.2M8.4%2011h5.2%22%2F%3E%3C%2Fsvg%3E') !important; }

.pswp .pswp__button--arrow--left::before,
.pswp .pswp__button--arrow--right::before {
  display: none;
}

.pswp .pswp__button--arrow--left {
  background-image: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2222%22%20height%3D%2222%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%231F1A16%22%20stroke-width%3D%221.6%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M14.5%205.5L8%2012l6.5%206.5%22%2F%3E%3C%2Fsvg%3E') !important;
  left: 1.25rem;
}

.pswp .pswp__button--arrow--right {
  background-image: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2222%22%20height%3D%2222%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%231F1A16%22%20stroke-width%3D%221.6%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M9.5%205.5L16%2012l-6.5%206.5%22%2F%3E%3C%2Fsvg%3E') !important;
  right: 1.25rem;
}

/* Counter and buttons are children of the same flex row rather than one
   being fixed-positioned on its own, so they cannot drift apart. */
.pswp .pswp__top-bar {
  background: transparent !important;
  padding: 1rem 1.25rem 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.625rem;
  height: auto;
}

/* Counter as a pill on the left, matching the round controls opposite. */
.pswp .pswp__counter {
  position: static;
  margin-right: auto;
  height: 44px;
  min-width: 62px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fff;
  border: 1px solid var(--didi-border);
  border-radius: 999px;
  box-shadow: 0 2px 12px rgba(31, 26, 22, 0.12);
  color: var(--didi-ink);
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  opacity: 1;
}

@media (max-width: 767px) {
  .pswp__button--arrow--left { left: 0.5rem; }
  .pswp__button--arrow--right { right: 0.5rem; }
}

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

/* --- Assurances, related material, accordions -------------------------- */
.didi-assurance {
  margin: 1.75rem 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.85rem;
}

.didi-assurance li {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.9375rem;
  line-height: 1.4;
}

.didi-assurance svg {
  flex: none;
  color: var(--didi-ink);
}

.didi-assurance a {
  color: var(--didi-ink);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.didi-assurance a:hover,
.didi-assurance a:focus-visible {
  color: var(--didi-coral-deep);
}

/* Bordered panel, matching the reference's boxed cross-sell. */
.didi-same-material {
  margin-top: 2rem;
  border: 1px solid var(--didi-border);
  padding: 1.5rem 1.25rem 1.25rem;
  text-align: center;
}

.didi-same-material__title {
  margin: 0 0 1.1rem;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* Flex rather than a fixed three-column grid: a material with only one other
   piece would otherwise leave two empty columns beside it. */
.didi-same-material__list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.625rem;
  margin: 0 0 1.1rem;
  padding: 0;
  list-style: none;
}

.didi-same-material__list li {
  flex: 0 1 calc(33.333% - 0.42rem);
  min-width: 0;
}

.didi-same-material__list img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  object-position: center top;
  display: block;
  background: var(--didi-surface);
}

.didi-same-material__cta {
  display: block;
  padding: 0.9rem 1rem;
  background: var(--didi-gold);
  color: var(--didi-ink);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  transition: background 0.2s ease;
}

.didi-same-material__cta:hover,
.didi-same-material__cta:focus-visible {
  background: var(--didi-coral);
  color: #fff;
}

.didi-accordions {
  margin-top: 2rem;
  border-top: 1px solid var(--didi-border);
}

.didi-accordion {
  border-bottom: 1px solid var(--didi-border);
}

/* The title carries the weight and the body the colour, so a closed row
   reads as a heading and an open one as heading then text. At the same
   weight and size they ran together. */
.didi-accordion > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  /* 44px touch target. */
  min-height: 56px;
  padding: 0.5rem 0;
  font-size: 1rem;
  font-weight: 600;
  color: var(--didi-ink);
  cursor: pointer;
  list-style: none;
}

/* Safari draws its own disclosure triangle beside the chevron. */
.didi-accordion > summary::-webkit-details-marker {
  display: none;
}

.didi-accordion > summary svg {
  flex: none;
  transition: transform 0.2s ease;
}

.didi-accordion[open] > summary svg {
  transform: rotate(180deg);
}

.didi-accordion__body {
  padding: 0 0 1.25rem;
  font-size: 0.9375rem;
  color: var(--didi-muted);
  line-height: 1.7;
}

.didi-accordion__body p:first-child {
  margin-top: 0;
}

.didi-accordion > summary:focus-visible {
  outline: 2px solid var(--didi-coral);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .didi-accordion > summary svg,
  .didi-same-material__cta {
    transition: none;
  }
}

/* Variable products have no SKU of their own, so this prints "SKU: N/A" —
   noise in the middle of the buying column. Blocksy's own meta rule is
   scoped by a data attribute and outranks a two-class selector. */
.product_meta .sku_wrapper {
  display: none !important;
}

