/* =============================================================================
   56-states.css — SEARCH, EMPTY STATES & 404  ("the pages with no content")
   =============================================================================

   Three moments share one system, because a visitor who hits two of them in a
   session should recognise the second:

     THE LOCKUP     34x1px accent rule + 0.7rem/0.17em micro-kicker, then a
                    Fraunces 300 display line with exactly ONE italic word in
                    --color-accent, then a real sentence. Same three parts, in
                    the same order, on the 404, on no-results, on every result
                    group and on the empty cart.
     THE FIELD      the search box is NOT a boxed control. It is the header's
                    own register: a Fraunces line on a hairline baseline with
                    an accent tick that runs the full width on focus, and a
                    text submit. A rounded input with a magnifier button is
                    what these pages used to wear and it read as a widget.
     THE PANEL      the counterweight, and the useful half of every one of
                    these pages: the deepest shelves with their thumbnails,
                    index numerals and counts. A dead end that only apologises
                    is abandoned; one that hands over the cupboard is designed.

   WHAT EACH PAGE IS
     404          a full-bleed chapter — a photograph of a road through the
                  karst under a five-stop scrim, the lockup and field on the
                  left in the dark, the routes panel floating on the open half
                  of the picture, and a HUD line closing the band on its own
                  bottom rule. It is composed like the hero, not like an error.
     SEARCH       a LEDGER, not a query dump: the tally set as a Fraunces
                  numeral with an italic unit, a scope rail with real per-type
                  counts, and the refine field as the right-hand counterweight
                  — then each result group opening on the standard lockup with
                  its own index numeral and its own counterweight link.
     NO RESULTS   the dead-end spread: lockup, field and three numbered things
                  to try, counterweighted by the routes panel, then what is
                  newest on the shelves. Never a sentence in an empty field.
     EMPTY CART   WooCommerce ships a grey crying face and an exclamation mark.
                  The block markup cannot be edited from a theme, so the glyph
                  goes, the shipped heading is hidden from sight but left in
                  the accessibility tree, and the composition is rebuilt from
                  the block's own pseudo-elements: kicker, display line,
                  sentence, photographic plate, and the "new in store" grid
                  re-set as a real section with a lockup of its own.

   Owns: .st-* (this file's own namespace), .error-404, .search-results-page
   and the empty-cart block. Loads after main.css, woocommerce.css and every
   other part, so it carries all of its own media queries.
   ========================================================================== */


/* =============================================================================
   1. SHARED PRIMITIVES
   ========================================================================== */

.st-404,
.st-search,
.wp-block-woocommerce-empty-cart-block {
  --st-ease: cubic-bezier(0.2, 0.75, 0.2, 1);
  --st-rule: color-mix(in srgb, var(--color-border) 88%, transparent);
  --st-rule-soft: color-mix(in srgb, var(--color-border) 58%, transparent);
  --st-panel-w: clamp(300px, 27vw, 396px);
  --st-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23g)' opacity='0.20'/%3E%3C/svg%3E");
}

/* --- The kicker. The signature; nothing here is ever smaller than 0.7rem. -- */
.st-kicker {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 0 0 clamp(18px, 1.9vw, 28px);
  font-family: var(--font-primary);
  font-size: 0.7rem;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.st-kicker-rule {
  display: block;
  flex: 0 0 auto;
  width: 34px;
  height: 1px;
  background: var(--color-accent);
}

/* --- The display line. Hero settings, one step down in scale. ------------- */
.st-display {
  margin: 0 0 clamp(20px, 2.1vw, 32px);
  font-family: var(--font-heading);
  font-optical-sizing: auto;
  font-weight: 300;
  font-size: clamp(2.9rem, 6vw, 5.8rem);
  line-height: 0.92;
  letter-spacing: -0.045em;
  color: var(--ink);
  text-wrap: balance;
  max-width: 15ch;
}

.st-display--sm {
  font-size: clamp(2.5rem, 4.4vw, 4.1rem);
  line-height: 0.94;
  max-width: 16ch;
}

.st-display em {
  font-style: italic;
  font-weight: 300;
  color: var(--color-accent);
}

/* --- The sentence. --------------------------------------------------------- */
.st-lede {
  margin: 0 0 clamp(28px, 3vw, 44px);
  max-width: 46ch;
  font-size: clamp(0.95rem, 0.4vw + 0.86rem, 1.06rem);
  line-height: 1.68;
  color: var(--color-text-light);
}

/* --- The field. The header's register, not a boxed control. --------------- */
.st-field {
  display: block;
  max-width: 540px;
  margin: 0 0 clamp(30px, 3vw, 44px);
}

.st-field-label {
  display: block;
  margin-bottom: 13px;
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.st-field-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 18px;
  height: 54px;
  padding: 0 2px;
  background: linear-gradient(180deg, transparent 38%, rgba(255, 255, 255, 0.025) 100%);
  transition: background 0.4s var(--st-ease);
}

/* The baseline: always drawn, quiet. */
.st-field-row::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--color-border-strong);
}

/* The accent tick that grows into the baseline on focus. */
.st-field-row::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--color-accent);
  transform: scaleX(0.07);
  transform-origin: left center;
  transition: transform 0.55s var(--st-ease), height 0.3s var(--st-ease);
  z-index: 1;
}

.st-field-row:hover { background: linear-gradient(180deg, transparent 22%, rgba(255, 255, 255, 0.045) 100%); }
.st-field-row:hover::before { transform: scaleX(0.18); }

.st-field-row:focus-within {
  background: linear-gradient(180deg, transparent 14%, rgba(255, 255, 255, 0.055) 100%);
}

.st-field-row:focus-within::before {
  transform: scaleX(1);
  height: 2px;
  box-shadow: 0 -8px 22px -8px color-mix(in srgb, var(--color-accent) 60%, transparent);
}

/* The global control reset gives every input a slab, a radius, a min-height
   and an inset highlight. All four have to go or the field wears a ghost box
   two pixels above its own baseline. */
.st-field-input {
  flex: 1 1 auto;
  min-width: 0;
  width: 100%;
  height: auto;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  -webkit-appearance: none;
  appearance: none;
  outline: none;
  font-family: var(--font-heading);
  font-optical-sizing: auto;
  font-weight: 300;
  font-size: 1.16rem;
  letter-spacing: -0.015em;
  color: var(--ink);
}

.st-field-input::placeholder {
  font-family: var(--font-heading);
  font-optical-sizing: auto;
  font-style: italic;
  font-weight: 300;
  font-size: 1.1rem;
  letter-spacing: -0.012em;
  color: var(--color-text-muted);
  opacity: 1;
  transition: color 0.3s var(--st-ease);
}

.st-field-row:hover .st-field-input::placeholder { color: var(--color-text-light); }

/* The site-wide focus ring is a rounded rectangle; on a field that has
   deliberately shed its box that reads as the wireframe coming back. The
   indicator is handed to the component instead — the baseline doubles, runs
   the full width in the accent and throws a soft glow, which is a larger and
   higher-contrast change of state than the ring it replaces. */
.st-field-input:focus,
.st-field-input:focus-visible {
  outline: none;
  box-shadow: none;
}

.st-field-btn {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 6px 2px;
  border: 0;
  background: none;
  cursor: pointer;
  font-family: var(--font-primary);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--color-text-light);
  transition: color 0.3s var(--st-ease);
}

.st-field-btn svg {
  width: 15px;
  height: 15px;
  transition: transform 0.4s var(--st-ease);
}

.st-field-btn:hover { color: var(--color-accent); }
.st-field-btn:hover svg { transform: translateX(4px); }
.st-field-row:focus-within .st-field-btn { color: var(--color-accent); }

/* --- Actions. Two routes, one weighted. ----------------------------------- */
.st-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 18px;
}

.st-btn {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  height: 52px;
  padding: 0 27px;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  font-family: var(--font-primary);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background-color 0.35s var(--st-ease), border-color 0.35s var(--st-ease),
              color 0.35s var(--st-ease), transform 0.35s var(--st-ease);
}

.st-btn svg { width: 15px; height: 15px; transition: transform 0.4s var(--st-ease); }
.st-btn:hover svg { transform: translateX(4px); }

.st-btn--solid {
  background: var(--paper);
  border-color: var(--paper);
  color: var(--night-2);
}

.st-btn--solid:hover {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--night-2);
  transform: translateY(-2px);
}

.st-btn--ghost {
  border-color: var(--color-border-strong);
  background: color-mix(in srgb, var(--night-2) 42%, transparent);
  color: var(--color-text);
}

.st-btn--ghost:hover {
  border-color: color-mix(in srgb, var(--color-accent) 62%, transparent);
  background: color-mix(in srgb, var(--color-primary) 16%, transparent);
  color: var(--ink);
  transform: translateY(-2px);
}

/* --- The counterweight link. ---------------------------------------------- */
.st-link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 4px;
  font-size: 0.86rem;
  font-weight: 500;
  color: var(--color-accent);
  white-space: nowrap;
}

.st-link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: color-mix(in srgb, var(--color-accent) 46%, transparent);
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 0.45s var(--st-ease);
}

.st-link:hover { color: var(--color-accent); }
.st-link:hover::after { transform: scaleX(1); transform-origin: left center; }
.st-link svg { width: 16px; height: 16px; transition: transform 0.4s var(--st-ease); }
.st-link:hover svg { transform: translateX(5px); }

/* --- HUD text: the hard facts, on a rule. --------------------------------- */
.st-hud {
  font-family: var(--font-primary);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  font-variant-numeric: lining-nums tabular-nums;
}

.st-hud--lead {
  display: inline-flex;
  align-items: center;
  gap: 16px;
  color: var(--color-text-light);
}

.st-hud--lead::before {
  content: "";
  flex: 0 0 auto;
  width: 34px;
  height: 1px;
  background: var(--color-accent);
}


/* =============================================================================
   2. THE ROUTES PANEL — shared by the 404 and no-results
   -----------------------------------------------------------------------------
   The deepest shelves, thumbnailed. This is the object that gives both pages a
   right-hand half worth looking at, and the only thing on either page that a
   visitor can actually act on beyond typing again.
   ========================================================================== */

.st-routes {
  position: relative;
  align-self: center;
  padding: clamp(18px, 1.6vw, 24px) clamp(15px, 1.4vw, 21px) clamp(9px, 0.9vw, 13px);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--night-2) 72%, transparent) 0%,
      color-mix(in srgb, var(--night-2) 92%, transparent) 100%);
  -webkit-backdrop-filter: blur(18px) saturate(1.08);
  backdrop-filter: blur(18px) saturate(1.08);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

/* The accent tick on the panel's own top edge — the same 34px signature the
   kicker opens with, so the panel reads as part of the lockup family. */
.st-routes::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 72px;
  height: 1px;
  background: linear-gradient(90deg, var(--color-accent), transparent);
}

.st-routes-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  margin: 0;
  padding: 0 6px 15px;
  border-bottom: 1px solid var(--st-rule);
}

.st-routes-kicker {
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-text-light);
}

.st-routes-count {
  font-size: 0.7rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  font-variant-numeric: lining-nums tabular-nums;
  white-space: nowrap;
}

.st-routes-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.st-route + .st-route { border-top: 1px solid var(--st-rule-soft); }

.st-route > a {
  display: grid;
  grid-template-columns: 20px 46px minmax(0, 1fr) 18px;
  align-items: center;
  gap: 15px;
  padding: 13px 6px;
  border-radius: var(--radius-sm);
  transition: background-color 0.35s var(--st-ease);
}

.st-route > a:hover { background: color-mix(in srgb, var(--color-primary) 13%, transparent); }

.st-route-num {
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
  font-variant-numeric: lining-nums tabular-nums;
}

.st-route-chip {
  position: relative;
  width: 46px;
  height: 46px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  overflow: hidden;
}

.st-route-chip img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The catalogue photography arrives at wildly different exposures; the
     panel grades all of it to one key or it reads as a contact sheet. */
  filter: saturate(0.82) contrast(1.05) brightness(0.94);
  transition: filter 0.5s var(--st-ease), transform 0.6s var(--st-ease);
}

.st-route > a:hover .st-route-chip img {
  filter: saturate(1) contrast(1.03) brightness(1.06);
  transform: scale(1.07);
}

.st-route-glyph {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  font-family: var(--font-heading);
  font-weight: 300;
  font-size: 1.3rem;
  color: var(--color-text-muted);
}

.st-route-body {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.st-route-name {
  font-family: var(--font-heading);
  font-optical-sizing: auto;
  font-weight: 300;
  font-size: 1.08rem;
  line-height: 1.15;
  letter-spacing: -0.022em;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.st-route-count {
  font-size: 0.7rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  font-variant-numeric: lining-nums tabular-nums;
}

.st-route-go {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  color: var(--color-text-muted);
  opacity: 0.4;
  transition: opacity 0.35s var(--st-ease), transform 0.4s var(--st-ease), color 0.35s var(--st-ease);
}

.st-route-go svg { width: 16px; height: 16px; }

.st-route > a:hover .st-route-go {
  opacity: 1;
  color: var(--color-accent);
  transform: translateX(3px);
}

.st-routes-all {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 4px;
  padding: 16px 6px 6px;
  border-top: 1px solid var(--st-rule);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-accent);
}

.st-routes-all svg { width: 16px; height: 16px; transition: transform 0.4s var(--st-ease); }
.st-routes-all:hover { color: var(--color-accent); }
.st-routes-all:hover svg { transform: translateX(5px); }


/* =============================================================================
   3. THE 404 — a chapter, not an error
   ========================================================================== */

.error-404.st-404 {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  /* Beats the rhythm padding 05-motion.css sets on every .error-404. */
  padding: 0;
  text-align: left;
  min-height: clamp(560px, 76vh, 900px);
  background-color: var(--night-2);
}

/* Layer 1 — the photograph. Mirrored, so the road and the river run into the
   OPEN half of the scrim instead of dying under the display type. Darkened,
   never desaturated to grey: a photograph with its colour taken away and its
   blacks lifted has nothing left to read by. */
.error-404.st-404::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: url("../../media/journey/05-mountain-road.webp");
  background-repeat: no-repeat;
  background-position: 58% 46%;
  background-size: cover;
  filter: saturate(0.62) contrast(1.14) brightness(0.86) hue-rotate(-8deg);
  transform: scaleX(-1);
}

/* Layer 2 — the scrim stack: grain, a low green wash pooling under the title,
   a vertical recess, and the horizontal scrim that opens a WINDOW over the
   middle third where the picture is meant to be read. */
.error-404.st-404::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background-image:
    var(--st-grain),
    radial-gradient(62% 116% at 1% 112%,
      color-mix(in srgb, var(--color-primary) 26%, transparent) 0%,
      color-mix(in srgb, var(--color-primary) 6%, transparent) 46%,
      transparent 74%),
    linear-gradient(180deg,
      color-mix(in srgb, var(--night-2) 72%, transparent) 0%,
      color-mix(in srgb, var(--night-2) 2%, transparent) 38%,
      color-mix(in srgb, var(--night-2) 10%, transparent) 62%,
      color-mix(in srgb, var(--night-2) 62%, transparent) 100%),
    linear-gradient(97deg,
      var(--night-2) 0%,
      color-mix(in srgb, var(--night-2) 92%, transparent) 26%,
      color-mix(in srgb, var(--night-2) 46%, transparent) 44%,
      color-mix(in srgb, var(--night-2) 10%, transparent) 64%,
      color-mix(in srgb, var(--night-2) 52%, transparent) 100%);
  background-size: 180px 180px, auto, auto, auto;
}

.st-404-inner {
  position: relative;
  z-index: 2;
  flex: 1 1 auto;
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) var(--st-panel-w);
  gap: clamp(40px, 5vw, 96px);
  align-items: center;
  align-content: center;
  padding-top: clamp(76px, 8.4vw, 132px);
  padding-bottom: clamp(66px, 7.2vw, 112px);
}

.st-404-lead { min-width: 0; }

.st-404-lead .st-display { max-width: 13ch; }

/* The band closes on its own rule, with the hard facts either side of it —
   the same HUD line the hero runs along its horizon. */
.st-404-foot {
  position: relative;
  z-index: 2;
  border-top: 1px solid var(--color-border);
  background: linear-gradient(180deg,
    transparent 0%,
    color-mix(in srgb, var(--night-2) 62%, transparent) 100%);
}

.st-404-foot-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  /* Longhands only: `padding` shorthand here would wipe the gutter .container
     puts on this same element and run the HUD off both page edges. */
  padding-top: 17px;
  padding-bottom: 19px;
}


/* =============================================================================
   4. SEARCH RESULTS — the ledger and the groups
   ========================================================================== */

.search-results-page.st-search { text-align: left; }

/* --- The ledger ----------------------------------------------------------- */
.st-ledger {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(280px, 400px);
  gap: clamp(28px, 3.4vw, 72px);
  align-items: end;
  /* No rule above: every chapter on this site opens on its kicker and closes
     on a hairline, and a lone rule floating in the silence under the plate
     read as a stray mark rather than the top of a band. */
  padding: 0 0 clamp(24px, 2.4vw, 34px);
  border-bottom: 1px solid var(--color-border);
  margin-bottom: var(--rhythm-tight, clamp(64px, 7vw, 112px));
}

/* No accent tick on the band's own top rule: the kicker two lines below
   already carries the 34x1px mark, and two of them stacked at the same x
   read as a mistake rather than a signature. */

.st-ledger-tally { min-width: 0; }
.st-ledger .st-kicker { margin-bottom: clamp(14px, 1.4vw, 20px); }

.st-tally {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin: 0 0 clamp(20px, 2.2vw, 30px);
}

.st-tally-num {
  font-family: var(--font-heading);
  font-optical-sizing: auto;
  font-weight: 300;
  font-size: clamp(2.4rem, 4.2vw, 3.7rem);
  line-height: 0.9;
  letter-spacing: -0.045em;
  color: var(--ink);
  font-variant-numeric: lining-nums tabular-nums;
}

.st-tally-unit {
  font-family: var(--font-heading);
  font-optical-sizing: auto;
  font-style: italic;
  font-weight: 300;
  font-size: clamp(1.15rem, 1.7vw, 1.55rem);
  letter-spacing: -0.02em;
  color: var(--color-accent);
}

/* --- The scope rail: real filters, real counts. --------------------------- */
.st-scope {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 4px 30px;
}

.st-scope-item {
  position: relative;
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  padding: 7px 0 9px;
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  transition: color 0.3s var(--st-ease);
}

.st-scope-item + .st-scope-item::before {
  content: "";
  position: absolute;
  left: -15px;
  top: 50%;
  width: 1px;
  height: 13px;
  transform: translateY(-50%);
  background: var(--color-border-strong);
}

.st-scope-item:hover { color: var(--color-text); }

.st-scope-item.is-on { color: var(--ink); }
.st-scope-item.is-on::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--color-accent);
}

.st-scope-n {
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  font-variant-numeric: lining-nums tabular-nums;
}

.st-scope-item.is-on .st-scope-n { color: var(--color-accent); }

.st-field--aside {
  max-width: none;
  margin: 0;
}

/* --- Group heads ---------------------------------------------------------- */
.st-group-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(220px, 344px);
  gap: clamp(24px, 3vw, 64px);
  align-items: end;
  padding-bottom: clamp(18px, 1.9vw, 28px);
  margin-bottom: clamp(30px, 3.4vw, 50px);
  border-bottom: 1px solid var(--color-border);
}

.st-group-lead { min-width: 0; }
.st-group-lead .st-kicker { margin-bottom: clamp(12px, 1.3vw, 18px); }

.st-group-title {
  margin: 0;
  font-family: var(--font-heading);
  font-optical-sizing: auto;
  font-weight: 300;
  font-size: clamp(1.9rem, 3.1vw, 3rem);
  line-height: 0.98;
  letter-spacing: -0.04em;
  color: var(--ink);
  text-wrap: balance;
}

.st-group-title em {
  font-style: italic;
  font-weight: 300;
  color: var(--color-accent);
}

.st-group-aside {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 14px;
  text-align: right;
}

.st-group-note {
  margin: 0;
  max-width: 36ch;
  font-size: 0.86rem;
  line-height: 1.62;
  color: var(--color-text-light);
}

.search-results-page.st-search .st-group + .st-group { margin-top: var(--rhythm-tight, clamp(64px, 7vw, 112px)); }
.search-results-page.st-search .search-results-group { margin-bottom: 0; }

/* --- Pagination -----------------------------------------------------------
   `the_posts_pagination()` emits `.page-numbers`; the theme only ever styled
   `.page-btn`, so the rail arrived as five bare numerals in 12px type. Scoped
   to this page so nothing else in the store shifts under it. */
.st-search .shop-pagination.st-pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}

.st-search .shop-pagination .nav-links {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}

.st-search .shop-pagination .page-numbers {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  height: 44px;
  padding: 0 14px;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  font-family: var(--font-primary);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  font-variant-numeric: lining-nums tabular-nums;
  color: var(--color-text-light);
  transition: background-color 0.3s var(--st-ease), border-color 0.3s var(--st-ease),
              color 0.3s var(--st-ease);
}

.st-search .shop-pagination a.page-numbers:hover {
  border-color: color-mix(in srgb, var(--color-accent) 46%, transparent);
  background: color-mix(in srgb, var(--color-primary) 14%, transparent);
  color: var(--ink);
}

.st-search .shop-pagination .page-numbers.current {
  background: var(--paper);
  border-color: var(--paper);
  color: var(--night-2);
  font-weight: 600;
}

.st-search .shop-pagination .page-numbers.dots {
  min-width: 22px;
  padding: 0;
  color: var(--color-text-muted);
}

.st-search .shop-pagination .page-numbers.next,
.st-search .shop-pagination .page-numbers.prev {
  border-color: var(--color-border);
  font-size: 1.15rem;
  line-height: 1;
}

.st-pager-count { white-space: nowrap; }

/* --- The last-row fill ----------------------------------------------------
   A product grid whose last row is short leaves a rectangle of dead field
   beside it — one match in a four-up grid leaves three empty cells. The gap
   is filled deliberately instead, with the one thing a searcher who found
   almost nothing still needs: the way into the whole cupboard. The span
   travels as a data attribute, not an inline style, so the breakpoints below
   can re-plan it. */
.st-fill {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: clamp(11px, 1.1vw, 16px);
  padding: clamp(22px, 2.2vw, 36px);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

/* Never a flat panel where a photograph can carry the meaning: at three
   columns wide the bordered box was its own empty room. */
.st-fill::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  background-image: url("../../media/journey/03-drying-house.webp");
  background-repeat: no-repeat;
  background-position: 50% 46%;
  background-size: cover;
  filter: saturate(0.62) contrast(1.08) brightness(0.82);
  transform: scale(1.02);
  transition: transform 0.9s var(--st-ease), filter 0.6s var(--st-ease);
}

.st-fill::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    var(--st-grain),
    linear-gradient(178deg,
      color-mix(in srgb, var(--night-2) 26%, transparent) 0%,
      color-mix(in srgb, var(--night-2) 54%, transparent) 44%,
      color-mix(in srgb, var(--night-2) 92%, transparent) 100%);
  background-size: 180px 180px, auto;
}

.st-fill:hover { border-color: color-mix(in srgb, var(--color-accent) 46%, transparent); }
.st-fill:hover::before { transform: scale(1.06); filter: saturate(0.8) contrast(1.06) brightness(0.9); }

.st-fill[data-span="1"] { grid-column: span 1; }
.st-fill[data-span="2"] { grid-column: span 2; }
.st-fill[data-span="3"] { grid-column: span 3; }
.st-fill[data-span="4"] { grid-column: span 4; }

.st-fill-kicker {
  display: flex;
  align-items: center;
  padding-left: 50px;
  background-image: linear-gradient(var(--color-accent), var(--color-accent));
  background-repeat: no-repeat;
  background-position: left 6px;
  background-size: 34px 1px;
  font-size: 0.7rem;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--color-text-light);
}

.st-fill-line {
  max-width: 20ch;
  font-family: var(--font-heading);
  font-optical-sizing: auto;
  font-weight: 300;
  font-size: clamp(1.3rem, 2vw, 2.15rem);
  line-height: 1.02;
  letter-spacing: -0.038em;
  color: var(--ink);
  text-wrap: balance;
}

.st-fill-line em { font-style: italic; color: var(--color-accent); }

.st-fill-go {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding-top: clamp(4px, 0.6vw, 8px);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-accent);
}

.st-fill-go svg { width: 16px; height: 16px; transition: transform 0.4s var(--st-ease); }
.st-fill:hover .st-fill-go svg { transform: translateX(5px); }

/* An odd number of articles leaves the last card alone in a two-column grid,
   with a whole empty cell beside it. That card takes the full width instead
   and turns horizontal — the group closes on a straight edge, and the last
   thing on the page reads as a deliberate wide entry rather than a leftover.
   Guarded on :has() so a card with no thumbnail simply widens. */
.st-search .blog-grid-full > .blog-card:last-child:nth-child(odd) {
  grid-column: 1 / -1;
}

.st-search .blog-grid-full > .blog-card:last-child:nth-child(odd):has(.blog-card-image) {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  column-gap: clamp(24px, 3vw, 48px);
  align-items: center;
}

.st-search .blog-grid-full > .blog-card:last-child:nth-child(odd):has(.blog-card-image) .blog-card-image {
  grid-row: 1 / span 2;
  aspect-ratio: 16 / 10;
  height: 100%;
}

.st-search .blog-grid-full > .blog-card:last-child:nth-child(odd):has(.blog-card-image) .blog-card-body { align-self: end; }
.st-search .blog-grid-full > .blog-card:last-child:nth-child(odd):has(.blog-card-image) .blog-card-footer { align-self: start; }


/* =============================================================================
   5. NO RESULTS — the dead-end plate
   -----------------------------------------------------------------------------
   The empty search is the page most likely to be the LAST thing a visitor
   sees, so it gets the same treatment as the 404 rather than a sentence on a
   flat field: a full-bleed photograph under the same multi-stop scrim, the
   lockup and the field in the dark on the left, the routes panel floating on
   the open half of the picture, the three things to try running the full width
   where the scrim has closed to solid ground, and a HUD rail closing the band.

   The plate carries 03-drying-house — a macro of dried leaf, not a landscape.
   Deliberately a different key from the 404's karst road: the two states are
   the same composition wearing two different photographs, which is what makes
   them read as one authored system instead of one designed page and one
   forgotten one. It is also the literal picture of the sentence above it —
   every leaf on the shelves, searched, and the word in none of them.
   ========================================================================== */

/* The banner above already opened the chapter; the page's own rhythm padding
   would leave a strip of flat ground between it and the plate. */
/* `body :is(.page-banner) + :is(.search-results-page)` in 05-motion.css is
   0-2-1, so this needs the same weight to hand the banner straight over. */
body .search-results-page.st-search--empty { padding-top: 0; }

.st-plate {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background-color: var(--night-2);
  border-top: 1px solid var(--color-border);
  margin-bottom: var(--rhythm, clamp(76px, 8vw, 132px));
}

/* Layer 1 — the photograph. Held back hard: a leaf macro at full exposure has
   more mid-tone than any display line can survive, and the scrim above it is
   doing composition, not rescue work. */
.st-plate::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: url("../../media/journey/03-drying-house.webp");
  background-repeat: no-repeat;
  background-position: 44% 62%;
  /* `cover`, never a percentage width: this band is three times taller on a
     phone than it is on a desktop, and a percentage width leaves the bottom
     two thirds of a tall band as bare background colour. The zoom is done on
     the element instead, which cannot uncover an edge. */
  background-size: cover;
  filter: saturate(0.76) contrast(1.05) brightness(0.92) hue-rotate(4deg);
  /* Flipped, the way the 404 mirrors its road: it lands the one sharp,
     fibrous leaf in the OPEN band of the scrim and drops the soft
     out-of-focus back of the frame into the half the scrim closes. */
  transform: scale(1.16, -1.16);
}

/* Layer 2 — the scrim stack, the same four-part recipe the 404 runs: grain, a
   low green wash, a vertical gradient that seams into the banner at the top
   and closes to SOLID ground by ~78% (so the advice band below is a calm
   reading field, not type over a picture), and a horizontal gradient that
   holds the left column dark and opens the right half — where the routes
   panel's backdrop-filter then picks the leaf up as frosted glass. */
.st-plate::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background-image:
    var(--st-grain),
    radial-gradient(60% 104% at 3% 6%,
      color-mix(in srgb, var(--color-primary) 24%, transparent) 0%,
      color-mix(in srgb, var(--color-primary) 6%, transparent) 44%,
      transparent 72%),
    linear-gradient(180deg,
      color-mix(in srgb, var(--night-2) 72%, transparent) 0%,
      color-mix(in srgb, var(--night-2) 22%, transparent) 13%,
      color-mix(in srgb, var(--night-2) 4%, transparent) 38%,
      color-mix(in srgb, var(--night-2) 22%, transparent) 56%,
      color-mix(in srgb, var(--night-2) 80%, transparent) 70%,
      var(--night-2) 79%,
      var(--night-2) 100%),
    linear-gradient(97deg,
      var(--night-2) 0%,
      color-mix(in srgb, var(--night-2) 88%, transparent) 25%,
      color-mix(in srgb, var(--night-2) 42%, transparent) 45%,
      color-mix(in srgb, var(--night-2) 6%, transparent) 70%,
      color-mix(in srgb, var(--night-2) 40%, transparent) 100%);
  background-size: 180px 180px, auto, auto, auto;
}

/* The .container gutter is a shorthand; longhands only, or the plate runs its
   type off both page edges. */
.st-plate-inner {
  position: relative;
  z-index: 2;
  flex: 1 1 auto;
  padding-top: clamp(74px, 8.2vw, 128px);
  padding-bottom: clamp(52px, 5.6vw, 86px);
}

/* The band closes on its own rule with the hard facts either side — the same
   HUD line the 404 runs along its bottom edge, and the hero along its horizon.
   A dead end that ends on a fact instead of on nothing is still authored. */
.st-plate-foot {
  position: relative;
  z-index: 2;
  border-top: 1px solid var(--color-border);
  background: linear-gradient(180deg,
    transparent 0%,
    color-mix(in srgb, var(--night-2) 62%, transparent) 100%);
}

.st-plate-foot-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding-top: 17px;
  padding-bottom: 19px;
}

/* Inside the plate the spread no longer closes on a hairline of its own —
   the foot rail is the close. */
.st-plate .st-dead {
  padding-bottom: 0;
  margin-bottom: 0;
  border-bottom: 0;
}

/* Over a photograph the panel wants a touch more separation from the picture
   than it needs on flat ground. */
.st-plate .st-routes { box-shadow: var(--shadow-lg), 0 1px 0 0 color-mix(in srgb, var(--ink) 7%, transparent) inset; }

.st-dead {
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) var(--st-panel-w);
  gap: clamp(36px, 4.6vw, 88px);
  align-items: start;
  padding-bottom: var(--rhythm-tight, clamp(64px, 7vw, 112px));
  margin-bottom: var(--rhythm-tight, clamp(64px, 7vw, 112px));
  border-bottom: 1px solid var(--color-border);
}

.st-dead-lead { min-width: 0; }
.st-dead .st-routes { align-self: start; }

/* Three numbered things to try. They run the FULL width under the spread
   rather than stacking in the left column: with the panel ending 240px above
   a column of advice, the lower right of this page was a dead pocket, which
   is the one composition fault this project keeps being rejected for. As a
   band they close both columns on the same line instead.
   The index is quiet — the accent on this page is already spent on the one
   italic word above. */
.st-tries {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0 clamp(28px, 3.4vw, 64px);
  margin: clamp(44px, 5vw, 76px) 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--color-border);
}

.st-try {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  align-content: start;
  gap: 18px;
  padding: 20px 0 4px;
}

.st-try-num {
  padding-top: 3px;
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  color: var(--color-text-muted);
  font-variant-numeric: lining-nums tabular-nums;
}

.st-try-body {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}

.st-try-title {
  font-family: var(--font-heading);
  font-optical-sizing: auto;
  font-weight: 300;
  font-size: 1.16rem;
  line-height: 1.25;
  letter-spacing: -0.024em;
  color: var(--ink);
}

.st-try-note {
  font-size: 0.85rem;
  line-height: 1.6;
  color: var(--color-text-light);
}

.st-suggest { margin-top: 0; }


/* =============================================================================
   6. THE EMPTY CART
   -----------------------------------------------------------------------------
   WooCommerce's empty-cart block is page content, not a template a theme can
   edit, so the whole composition is rebuilt from what the block already ships:

     ::before                    the kicker
     h2.wc-block-cart__…__title  the display line — its own string is hidden
                                 from sight but LEFT IN THE ACCESSIBILITY TREE
                                 with the standard clip pattern, and the line
                                 is drawn from the heading's two pseudos so
                                 that one word can be italic in the accent
     hr.wp-block-separator       the sentence (the shipped "···" is dropped)
     ::after                     the photographic plate
     h2 "New in store"           re-set as a section head, kicker and all
     .wc-block-grid              the shelves, graded to one key
   ========================================================================== */

.wp-block-woocommerce-empty-cart-block {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(260px, 380px);
  grid-template-areas:
    "kick  plate"
    "lead  plate"
    "lede  plate"
    "head  head"
    "shelf shelf";
  column-gap: clamp(32px, 4.4vw, 80px);
  align-items: start;
  text-align: left;
}

/* The kicker. Its 34x1px rule cannot be a second pseudo-element on the same
   box, so the rule is drawn as the kicker's own left border — same length,
   same hairline, same colour, one element fewer. */
.wp-block-woocommerce-empty-cart-block::before {
  content: "Your basket · nothing in it yet";
  grid-area: kick;
  align-self: end;
  display: flex;
  align-items: center;
  margin-bottom: clamp(16px, 1.7vw, 24px);
  padding-left: 50px;
  /* The 34x1px rule. A second pseudo-element is not available on this box, and
     a border-left would be as tall as the line, so the rule is painted as a
     one-pixel gradient held at the leading edge — same mark, same measure. */
  background-image: linear-gradient(var(--color-accent), var(--color-accent));
  background-repeat: no-repeat;
  /* Held on the first line rather than the box centre, so a kicker that wraps
     on a phone does not float its rule into the gap between two lines. */
  background-position: left 6px;
  background-size: 34px 1px;
  font-family: var(--font-primary);
  font-size: 0.7rem;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* The display line. The heading's own string ("Your cart is currently
   empty!") is taken to zero and made transparent rather than removed, so it
   is still the accessible name of this region; the line that is SEEN is drawn
   from the heading's two pseudo-elements, which is what buys the one italic
   accent word every display line on this site carries. Block markup that
   ships inside page content cannot be edited from a theme, so this is the
   only way to set it properly. */
.wp-block-woocommerce-empty-cart-block > .wc-block-cart__empty-cart__title {
  grid-area: lead;
  margin: 0 0 clamp(18px, 2vw, 28px);
  padding: 0;
  font-size: 0;
  line-height: 0.94;
  color: transparent;
  text-align: left;
  text-wrap: balance;
}

.wp-block-woocommerce-empty-cart-block > .wc-block-cart__empty-cart__title::before,
.wp-block-woocommerce-empty-cart-block > .wc-block-cart__empty-cart__title::after {
  display: inline;
  font-family: var(--font-heading);
  font-optical-sizing: auto;
  font-weight: 300;
  font-size: clamp(2.4rem, 4.4vw, 4rem);
  line-height: 0.94;
  letter-spacing: -0.045em;
}

/* This pseudo-element is also where WooCommerce paints its crying-face glyph
   (a 5em masked shape filled with `background-color: currentColor`, drawn for
   a white page). Every one of those properties is unwound in the same rule
   that takes the pseudo over, so the glyph cannot survive as a grey slab
   sitting behind the line. */
.wp-block-woocommerce-empty-cart-block > .wc-block-cart__empty-cart__title::before {
  content: "Nothing set aside\00a0";
  display: inline;
  width: auto;
  height: auto;
  margin: 0;
  background: none;
  background-color: transparent;
  -webkit-mask-image: none;
  mask-image: none;
  /* woocommerce.css already took the glyph down to 0.28 and greyscale; on
     type those two turn the line into fog. */
  opacity: 1;
  filter: none;
  color: var(--ink);
}

.wp-block-woocommerce-empty-cart-block > .wc-block-cart__empty-cart__title::after {
  content: "yet.";
  font-style: italic;
  color: var(--color-accent);
}

/* The sentence, carried by the separator the block already ships. */
.wp-block-woocommerce-empty-cart-block > .wp-block-separator {
  grid-area: lede;
  width: 100%;
  max-width: 46ch;
  height: auto;
  margin: 0 0 clamp(28px, 3vw, 40px);
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  opacity: 1;
}

.wp-block-woocommerce-empty-cart-block > .wp-block-separator::before,
.wp-block-woocommerce-empty-cart-block > .wp-block-separator.is-style-dots::before {
  content: "Quantities, delivery and payment all come later — nothing is reserved until you check out. Below is what has most recently landed on the shelves.";
  display: block;
  padding: 0;
  font-family: var(--font-primary);
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.68;
  letter-spacing: 0;
  color: var(--color-text-light);
}

.wp-block-woocommerce-empty-cart-block > .wp-block-separator::after { content: none; }

/* The plate: the one photograph on the page, framed and scrimmed in the same
   register as the chapter plate above it. */
.wp-block-woocommerce-empty-cart-block::after {
  content: "";
  grid-area: plate;
  align-self: stretch;
  min-height: clamp(240px, 24vw, 340px);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-image:
    linear-gradient(180deg,
      color-mix(in srgb, var(--night-2) 34%, transparent) 0%,
      color-mix(in srgb, var(--night-2) 10%, transparent) 42%,
      color-mix(in srgb, var(--night-2) 78%, transparent) 100%),
    url("../../media/journey/06-tea-ceremony.webp");
  background-repeat: no-repeat;
  background-position: 50% 50%;
  background-size: cover, cover;
  box-shadow: var(--shadow-lg);
}

/* "New in store" — re-set as a section head with a kicker of its own. */
.wp-block-woocommerce-empty-cart-block > .wp-block-heading:not(.wc-block-cart__empty-cart__title) {
  grid-area: head;
  position: relative;
  margin: clamp(56px, 6.4vw, 100px) 0 clamp(26px, 3vw, 42px);
  padding: clamp(26px, 2.8vw, 40px) 0 0;
  border-top: 1px solid var(--color-border);
  font-family: var(--font-heading);
  font-optical-sizing: auto;
  font-weight: 300;
  font-size: clamp(1.8rem, 2.8vw, 2.6rem);
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--ink);
  text-align: left;
}

.wp-block-woocommerce-empty-cart-block > .wp-block-heading:not(.wc-block-cart__empty-cart__title)::before {
  content: "Meanwhile · newest on the shelves";
  display: flex;
  align-items: center;
  margin-bottom: clamp(14px, 1.5vw, 20px);
  padding-left: 50px;
  /* The 34x1px rule. A second pseudo-element is not available on this box, and
     a border-left would be as tall as the line, so the rule is painted as a
     one-pixel gradient held at the leading edge — same mark, same measure. */
  background-image: linear-gradient(var(--color-accent), var(--color-accent));
  background-repeat: no-repeat;
  /* Held on the first line rather than the box centre, so a kicker that wraps
     on a phone does not float its rule into the gap between two lines. */
  background-position: left 6px;
  background-size: 34px 1px;
  font-family: var(--font-primary);
  font-size: 0.7rem;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* The right-hand counterweight. Every section head on this site balances its
   display line with something on the right; this band had nothing there, and
   an empty right half of a header band is a standing rejection. */
.wp-block-woocommerce-empty-cart-block > .wp-block-heading:not(.wc-block-cart__empty-cart__title)::after {
  content: "Newest first";
  position: absolute;
  right: 0;
  bottom: 5px;
  font-family: var(--font-primary);
  font-size: 0.7rem;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.wp-block-woocommerce-empty-cart-block > .wc-block-grid { grid-area: shelf; }

/* The grid itself: a card that matches the shop's, and one photographic key
   across four images that arrive at four different exposures. */
.wp-block-woocommerce-empty-cart-block .wc-block-grid__products {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 28px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* WooCommerce lays this list out with flexbox and caps every item at
   `flex: 1 0 25%; max-width: 25%`. Under a grid parent that 25% is measured
   against the COLUMN, which collapsed each card to a 66px sliver with its
   button set vertically. */
.wp-block-woocommerce-empty-cart-block .wc-block-grid__products > .wc-block-grid__product {
  flex: none;
  width: auto;
  max-width: none;
  min-width: 0;
  margin: 0;
  padding: 18px 0 0;
  font-size: 1rem;
  text-align: left;
  /* Woo also uses transparent 8px side / 16px bottom borders as gutters,
     which inset every child of the card by eight pixels from its own rule. */
  border: 0;
  border-top: 1px solid var(--color-border);
}

/* WooCommerce makes this box an inline-block, so it carries a line box and
   the photograph sat letterboxed inside its own frame with a 22px band of
   surface colour above and below it. */
.wp-block-woocommerce-empty-cart-block .wc-block-grid__products .wc-block-grid__product-image {
  display: block;
  margin: 0 0 18px;
  padding: 0;
  font-size: 0;
  line-height: 0;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-surface);
}

/* `.post-content img` gives every image in page content a 24px vertical
   margin; inside a card frame that reads as letterboxing. */
.wp-block-woocommerce-empty-cart-block .wc-block-grid__products .wc-block-grid__product-image img {
  display: block;
  margin: 0;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  filter: saturate(0.78) contrast(1.05) brightness(0.9);
  transition: filter 0.5s var(--st-ease), transform 0.7s var(--st-ease);
}

.wp-block-woocommerce-empty-cart-block .wc-block-grid__products .wc-block-grid__product-link:hover img {
  filter: saturate(1) contrast(1.03) brightness(1);
  transform: scale(1.04);
}

.wp-block-woocommerce-empty-cart-block .wc-block-grid__products .wc-block-grid__product-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  /* Two-line clamp measured in em, so it survives a breakpoint. */
  min-height: calc(2 * 1.35em);
  margin: 0 0 10px;
  font-family: var(--font-heading);
  font-optical-sizing: auto;
  font-weight: 300;
  font-size: 1.02rem;
  line-height: 1.35;
  letter-spacing: -0.022em;
  color: var(--ink);
}

.wp-block-woocommerce-empty-cart-block .wc-block-grid__products .wc-block-grid__product-price {
  margin: 0 0 16px;
  font-family: var(--font-primary);
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-dark);
}

.wp-block-woocommerce-empty-cart-block .wc-block-grid__products .wc-block-grid__product-add-to-cart { margin: 0; }
.wp-block-woocommerce-empty-cart-block .wc-block-grid__products .wc-block-grid__product-link {
  display: block;
  width: 100%;
  margin: 0;
}


/* =============================================================================
   7. BREAKPOINTS
   -----------------------------------------------------------------------------
   This file loads after every media query in main.css, so it carries its own.
   ========================================================================== */

@media (max-width: 1200px) {
  .st-404-inner { gap: clamp(32px, 3.6vw, 60px); }
  .st-ledger { grid-template-columns: minmax(0, 1fr) minmax(260px, 340px); }
  .st-group-head { grid-template-columns: minmax(0, 1fr) minmax(200px, 300px); }
}

@media (max-width: 1000px) {
  /* One column everywhere. The panel stops being a counterweight and becomes
     the next thing you read, which is the right order on a phone anyway. */
  .st-404-inner,
  .st-dead,
  .st-ledger,
  .st-group-head {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(34px, 5vw, 52px);
  }

  .error-404.st-404 { min-height: 0; }
  .st-404-inner { padding-top: clamp(60px, 8vw, 92px); padding-bottom: clamp(52px, 7vw, 80px); }
  .st-404-lead .st-display,
  .st-display { max-width: 18ch; }

  .st-routes { align-self: stretch; }

  .st-group-aside {
    align-items: flex-start;
    text-align: left;
  }

  .st-search .blog-grid-full > .blog-card:last-child:nth-child(odd):has(.blog-card-image) {
    display: block;
  }

  .st-fill[data-span] { grid-column: 1 / -1; }
  .st-group-note { max-width: 52ch; }

  .st-field--aside { max-width: 540px; }

  /* The advice band collapses to a list, and each item gets its own closing
     rule back — three stacked blocks with no rules between them read as one
     run-on paragraph. */
  .st-tries { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .st-try { padding: 17px 0; border-bottom: 1px solid var(--st-rule-soft); }

  /* Stacked, the plate is two to three times as tall, so the picture is read
     in the top third and the scrim closes correspondingly earlier. */
  .st-plate-inner { padding-top: clamp(58px, 8vw, 90px); padding-bottom: clamp(44px, 6vw, 70px); }
  .st-plate::before { background-position: 56% 58%; transform: scale(1.3, -1.3); }
  .st-plate::after {
    background-image:
      var(--st-grain),
      radial-gradient(70% 46% at 4% 2%,
        color-mix(in srgb, var(--color-primary) 22%, transparent) 0%,
        color-mix(in srgb, var(--color-primary) 5%, transparent) 46%,
        transparent 74%),
      linear-gradient(180deg,
        color-mix(in srgb, var(--night-2) 80%, transparent) 0%,
        color-mix(in srgb, var(--night-2) 42%, transparent) 8%,
        color-mix(in srgb, var(--night-2) 17%, transparent) 24%,
        color-mix(in srgb, var(--night-2) 35%, transparent) 46%,
        color-mix(in srgb, var(--night-2) 80%, transparent) 62%,
        var(--night-2) 71%,
        var(--night-2) 100%),
      linear-gradient(97deg,
        color-mix(in srgb, var(--night-2) 66%, transparent) 0%,
        color-mix(in srgb, var(--night-2) 30%, transparent) 42%,
        color-mix(in srgb, var(--night-2) 20%, transparent) 100%);
    background-size: 180px 180px, auto, auto, auto;
  }

  .wp-block-woocommerce-empty-cart-block {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "kick"
      "lead"
      "lede"
      "plate"
      "head"
      "shelf";
  }
  .wp-block-woocommerce-empty-cart-block::after {
    min-height: clamp(220px, 34vw, 300px);
    margin-bottom: 8px;
  }
  .wp-block-woocommerce-empty-cart-block .wc-block-grid__products {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 760px) {
  .st-display { font-size: clamp(2.6rem, 10vw, 3.6rem); max-width: 16ch; }
  .st-display--sm { font-size: clamp(2.2rem, 8.6vw, 3rem); }
  .st-tally-num { font-size: clamp(2.2rem, 9vw, 3rem); }
  .st-group-title { font-size: clamp(1.7rem, 6.4vw, 2.3rem); }

  /* The rail wraps below this width, and a hairline separator drawn by the
     item that follows another lands at the START of the wrapped row, which
     reads as a stray tick against the page edge. Two columns with real
     borders instead. */
  .st-scope {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0;
  }
  .st-scope-item { padding: 10px 0 10px 15px; }
  .st-scope-item + .st-scope-item::before { content: none; }
  .st-scope-item:nth-child(odd) { padding-left: 0; }
  .st-scope-item:nth-child(even) { border-left: 1px solid var(--color-border-strong); }
  .st-scope-item:nth-child(n + 3) { border-top: 1px solid var(--st-rule-soft); }

  /* Stacked AND stretched: a column flex item sized to max-content will not
     wrap, and the facts line is wider than a phone. */
  .st-404-foot-inner,
  .st-plate-foot-inner {
    flex-direction: column;
    align-items: stretch;
    gap: 9px;
    padding-top: 16px;
    padding-bottom: 18px;
  }
  .st-hud { letter-spacing: 0.15em; line-height: 1.5; }

  .st-route > a { grid-template-columns: 20px 42px minmax(0, 1fr) 16px; gap: 12px; }
  .st-route-chip { width: 42px; height: 42px; }
}

@media (max-width: 560px) {
  .st-field-row { gap: 12px; height: 50px; }
  .st-field-input,
  .st-field-input::placeholder { font-size: 1.02rem; }
  .st-field-btn { font-size: 0.7rem; letter-spacing: 0.12em; gap: 8px; }

  .st-actions { gap: 12px; }
  .st-btn { height: 48px; padding: 0 20px; letter-spacing: 0.12em; }
  .st-btn--solid,
  .st-btn--ghost { flex: 1 1 100%; justify-content: center; }

  .st-try { grid-template-columns: 24px minmax(0, 1fr); gap: 14px; }

  /* One column: the head has no right half left to counterweight, and the HUD
     would sit on top of the display line. */
  .wp-block-woocommerce-empty-cart-block > .wp-block-heading:not(.wc-block-cart__empty-cart__title)::after { content: none; }

  .st-lede { font-size: 0.95rem; }

  .wp-block-woocommerce-empty-cart-block .wc-block-grid__products {
    grid-template-columns: minmax(0, 1fr);
    gap: 22px;
  }
}

/* =============================================================================
   8. REDUCED MOTION
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .st-field-row::before,
  .st-field-btn svg,
  .st-btn,
  .st-btn svg,
  .st-link,
  .st-link::after,
  .st-link svg,
  .st-route-chip img,
  .st-route-go,
  .st-routes-all svg,
  .wp-block-woocommerce-empty-cart-block .wc-block-grid__products .wc-block-grid__product-image img {
    transition-duration: 0.01ms;
  }
  .st-btn:hover,
  .st-route > a:hover .st-route-chip img,
  .wp-block-woocommerce-empty-cart-block .wc-block-grid__products .wc-block-grid__product-link:hover img {
    transform: none;
  }
}
