/** Shopify CDN: Minification failed

Line 237:2 Unexpected "/"
Line 237:26 Expected identifier but found whitespace

**/
/* Badges live in calmy-cardsurface.css now - one pill, one position, for every
   card on the site. The rules that were here set background:none and loaded
   later, so they quietly turned the pill back into bare text. */
/* ============================================================================
   CALMY DESIGN TOKENS + SHARED PRIMITIVES + CARD SYSTEM

   OWNS: palette and spacing tokens, section grounds, the line-icon primitive, the
   information band, link/button variants and the product card.
   MUST NOT TOUCH: header, navigation, drawers, overlay, cart, PDP purchase column.

   GROUNDS - three neutrals, small steps. They should read as a change of air, not colour.
     --c-bg var(--t-page) ivory | --c-white var(--t-white) soft white | --c-surface var(--t-page) soft cream
   ============================================================================ */

:root{
  --c-serif:var(--font-heading--family,Georgia,'Times New Roman',serif);
  --c-sans:var(--font-body--family,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif);
  --c-eyebrow:.22em;--c-label:.16em;
  --c-white:var(--t-white);--c-clay:var(--t-accent);--c-clay-soft:var(--t-accent-mut);
  --c-espresso:var(--t-ink);--c-olive:var(--t-neutral);--c-cream:var(--t-page);
  --c-sp:64px;--c-sp-tight:48px;
}
@media(min-width:700px){:root{--c-sp:80px;--c-sp-tight:60px}}
@media(min-width:1000px){:root{--c-sp:104px;--c-sp-tight:76px}}

.csec--white{background:var(--c-white)}
.ccar--white{background:var(--c-white)}

/* ---------- Line icon primitive ----------
   One weight, one size, currentColor. Never coloured, never filled, never large. */
.cico{width:20px;height:20px;display:block;fill:none;stroke:currentColor;stroke-width:1.15;
  stroke-linecap:round;stroke-linejoin:round;vector-effect:non-scaling-stroke}

/* ---------- Information band ---------- */
.cinfb{width:100%}
.cinfb--white{background:var(--c-white)}
.cinfb--surface{background:var(--c-surface)}
.cinfb__row{display:grid;gap:2px}
.cinfb__i{display:flex;align-items:flex-start;gap:12px;text-decoration:none;color:inherit;min-width:0}
.cinfb__ic{flex:none;color:var(--c-clay);margin-top:1px}
.cinfb__b{display:flex;flex-direction:column;gap:5px;min-width:0}
.cinfb__h{font-size:10.5px;letter-spacing:var(--c-label);text-transform:uppercase;color:var(--c-fg);line-height:1.4}
.cinfb__t{font-size:12.5px;line-height:1.6;color:var(--c-muted);max-width:30ch}
a.cinfb__i:hover .cinfb__h{color:var(--c-clay)}

/* Compact: one quiet rule of labels. */
.cinfb--compact{border-top:1px solid var(--c-hair);border-bottom:1px solid var(--c-hair)}
.cinfb--compact .cinfb__row{grid-template-columns:1fr 1fr;gap:14px 20px;padding:18px 0}
@media(min-width:700px){.cinfb--compact .cinfb__row{grid-template-columns:repeat(4,1fr);gap:20px;padding:20px 0}}
.cinfb--compact .cinfb__i{align-items:center;gap:9px}
.cinfb--compact .cico{width:17px;height:17px}
.cinfb--compact .cinfb__h{font-size:9.5px}

/* Full: icon, heading, explanation. */
.cinfb--full{padding:var(--c-sp-tight) 0}
.cinfb--full .cinfb__row{grid-template-columns:1fr;gap:26px}
@media(min-width:700px){.cinfb--full .cinfb__row{grid-template-columns:repeat(3,1fr);gap:40px}}
.csec__head--c{justify-content:center;text-align:center}

/* ---------- Button and link variants ---------- */
.cbtn.cbtn--secondary{background:transparent;color:var(--c-fg);border:1px solid var(--c-line)}
.cbtn.cbtn--secondary:hover{border-color:var(--c-fg);opacity:1}
.csec--dark .cbtn.cbtn--secondary{color:var(--c-cream);border-color:rgb(var(--t-page-rgb) / .4)}
.clink{display:inline-flex;align-items:center;gap:9px;font-size:10px;letter-spacing:var(--c-eyebrow);text-transform:uppercase;color:inherit;text-decoration:none;min-height:44px;background:none;border:0;padding:0;cursor:pointer;font-family:inherit}
.clink:after{content:"\2192";transition:transform .22s var(--c-ease)}
.clink:hover:after{transform:translateX(4px)}

/* ---------- Product card -----------------------------------------------------
   One rounded card, no border, ground one step off the page. The product image
   floats directly on that ground with a soft shadow — there is no inner tinted
   frame any more.

   On a pointer device the card swaps to a full-bleed lifestyle image on hover,
   keeps the category word, fades the text block out and slides a pill up from
   the bottom edge. Nothing scales, nothing lifts, and the card's own shadow
   never changes.

   These rules override calmy-cardsurface.css, which frames the image as a
   cover-cropped panel with its own ground. Selectors are doubled so the result
   does not depend on which file loads last.
   --------------------------------------------------------------------------- */

/* min-width: 0 on the grid item itself for the same reason as the track: a
   grid item's automatic minimum is its min-content size, so without this the
   card can refuse to shrink into a column that is narrower than its longest
   unbreakable word. */
.ccard {
  min-width: 0;
  --card-pad: 18px;
  --pill-h: 46px;
  --pill-inset: 12px;
  --swap: 400ms;
  height: 100%;
}
@media (min-width: 1000px) { .ccard { --card-pad: 22px; } }

.ccard__inner {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
  /* Clips the hover image to the card, corners included. */
  overflow: hidden;
  /* ONE CONTINUOUS CREAM SURFACE. The hairline and the 22px radius are gone:
     the card is now a single soft field with the media sitting on the same
     ground as the text under it, rather than a bordered tile with a framed
     photograph inside it. --t-card is the cream one step off the page, so the
     card still reads as a distinct surface on --t-page without an outline. */
  border: 0;
  border-radius: 16px;
  background: var(--t-card);
  padding: var(--card-pad);
  /* No pill reservation any more — the button is the last item in the foot,
     in normal flow, so it takes its own height and the card's bottom padding
     is simply the card's padding. */
  text-decoration: none;
  color: inherit;
  isolation: isolate;
}

/* ---- The hover image ------------------------------------------------------
   Absent from the DOM entirely when there is nothing to swap to, so hover can
   never reveal an empty frame. */
.ccard__hover {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  transition: opacity var(--swap) var(--c-ease, ease);
  pointer-events: none;
}

/* ---- Category word --------------------------------------------------------
   The card's headline: large, heavy, lowercase, muted. Sits above the hover
   image so it survives the swap. */
/* A small uppercase eyebrow at the top of the card.

   It used to be 26-30px display type laid over the photograph, which put a
   word across the product at exactly the size that competes with it. As an
   eyebrow it labels the card instead of decorating it, and the media area
   below gets the whole card width back. */
.ccard__mood {
  position: relative;
  z-index: 2;
  margin: 0 0 10px;
  font-family: var(--c-sans);
  font-size: 9.5px;
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-indent: 0.18em;
  color: var(--c-soft);
  min-height: 1.4em;
  transition: color var(--swap) var(--c-ease, ease);
}
.ccard__mood.ccard__mood:empty { display: block; }


/* Pinned to the CARD, not the image, at a fixed inset — its offset parent is
   .ccard__inner, so it cannot slide with the photograph or sit under it. z-2
   puts it above the hover image at z-1. The fill transition runs on the same
   clock as the image fade, so the pill grows in as the photograph darkens and
   there is no moment where dark text sits on a dark shot. */
.ccard__badge.ccard__badge {
  position: absolute;
  top: var(--card-pad);
  right: var(--card-pad);
  left: auto;
  z-index: 3;
  padding: 5px 10px;
  border-radius: 999px;
  transition: background-color var(--swap) var(--c-ease, ease),
              color var(--swap) var(--c-ease, ease);
}

/* ---- Product image --------------------------------------------------------
   Floats on the card ground. No inner box, no frame, no ground of its own. */
.ccard__media.ccard__media {
  position: relative;
  z-index: 0;
  display: grid;
  place-items: center;
  /* 4:5 portrait. Square cropped the taller products tight against the sides;
     a portrait box gives every one of them room above and below. The card
     grows to suit. */
  aspect-ratio: 4 / 5;
  /* min-height: 0 is load-bearing. As a flex item this defaults to `auto`,
     which floors the box at its content size — the image sized itself from
     max-width (86% of 251 = 216px), went square, and dragged the frame to
     216px tall regardless of the ratio. With the floor removed the ratio
     decides the height, and the image's max-height percentage finally has a
     definite height to resolve against. */
  min-height: 0;
  overflow: visible;
  /* No ground of its own — the card's shows through, so the frame is the card
     rather than a tile laid on it. */
  background: transparent;
  border-radius: 14px;
  box-shadow: none;
  padding: 0;
  transition: opacity var(--swap) var(--c-ease, ease);
}

/* Absolutely positioned and centred with `margin: auto`, not laid out in
   flow. In flow the image sized itself from max-width alone — max-height's
   percentage had no definite height to resolve against once min-height was
   zeroed, so a square photograph came out taller than its frame and, with
   overflow visible, printed straight over the product name beneath it.
   Against the frame's padding box both percentages resolve, and the image can
   never exceed the space reserved for it. */
/* Scoped to the PRODUCT image by class, not to any img in the box.

   As `.ccard__media img` it also caught the hover image the moment that moved
   inside the media box — at (0,3,1) it outranked the rule holding the swap
   hidden, so the second photograph sat permanently on top of the first and
   there was no hover left to see. It is the leftover of the contain-with-12%-
   inset treatment that cover replaced, so most of it is dead; what remains is
   the positioning. */
.ccard__media.ccard__media .ccard__img {
  position: absolute;
  inset: 0;
  margin: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 1;
} / .is-on { opacity: 1 }. This card renders one
     image and never sets is-on, so without this every photograph is invisible. */
  opacity: 1;
  /* The catalogue is shot on a neutral grey sweep — sampled at
     rgb(var(--t-page-rgb)) — against a warm cream card at rgb(var(--t-page-rgb)). Two
     different hues, which is why the photograph read as a white box pasted
     onto the card rather than an object sitting on it.

     multiply pulls that sweep into the card's own colour: the result is the
     card's hue about 5% darker rather than a foreign grey. It cannot vanish
     completely, because the backdrop is 242 and not pure white — that needs
     cut-out images with real transparency, which is photography rather than
     CSS. This is as close as the source files allow.

     NO drop-shadow. A CSS shadow here is cast by the SWEEP's rectangle, not
     by the ring, so it outlined the very edge this is trying to play down —
     it was what made the photograph read as a tile with a border. The rings
     already cast their own shadow inside the frame, which is the shadow that
     belongs to the object. */
  mix-blend-mode: multiply;
}

/* RULE 0 — no image yet. One flat tone at the frame's exact size: no icon, no
   wireframe, no gradient, and the card keeps its height so nothing moves when
   a photograph arrives. */
.ccard__empty {
  position: absolute;
  inset: 0;
  margin: auto;
  display: block;
  width: 76%;
  height: 76%;
  border-radius: 2px;
  background: var(--c-sink, var(--t-card));
}

/* ---- Bottom block ---------------------------------------------------------
   Pinned to the bottom of the card so every card in a row ends level however
   long the name above it runs. */
/* ── The foot: one column, one spacing scale ───────────────────────────────
   Five items, top to bottom, every one a full-width block on the same left
   edge: rating, title, price, descriptor, swatches. Any of the three optional
   ones can be absent and the rest keep their rhythm, because each item owns
   the space ABOVE itself and the first one in the column zeroes it. That is
   what makes the arrangement independent of which items a given product has —
   there is no rule anywhere that says "if there is a descriptor, then".

   THREE STEPS, and only three. --gap-tight binds the rating to the title it
   belongs to, --gap-base is the ordinary step between lines of information,
   --gap-wide separates the swatches, which are a different kind of thing from
   the text above them:

     rating  -> title       6px   tight
     title   -> price       8px   base
     price   -> descriptor  8px   base
     desc    -> swatches   10px   wide

   ALIGNED TO THE PILL, not to the card's text padding. .ccard__inner pads by
   --card-pad (18px, 22px from 1000px) but the buy pill is positioned at
   --pill-inset (12px), so the foot's left edge sat 6-10px inside the pill's
   and nothing in the card lined up with the one control on it. The negative
   margin is the difference between the two tokens, so it stays correct at
   both card sizes and cannot drift if either token moves. */
.ccard__foot {
  /* Tightened. The information block is compact by design — title, subtitle
     and swatches are one unit under the photograph, not four separate rows —
     so the only step that stays generous is the one before the button, which
     needs air to read as a control rather than as another line of text. */
  --gap-tight: 4px;
  --gap-base: 8px;
  --gap-wide: 14px;

  position: relative;
  z-index: 0;
  /* BLOCK, not flex, and the reason is the title's clamp.

     .ccard__t declares BOTH clamping mechanisms: the legacy pair
     (display: -webkit-box + -webkit-line-clamp) and the modern `line-clamp`.
     Chrome takes the modern one, which makes the element a block container —
     its computed display reads flow-root, not -webkit-box, and that is the
     modern path working, not a failure. Safari has no `line-clamp` yet and
     falls back to the legacy pair, which only functions on a real -webkit-box.

     A flex parent blockifies its items' display, which would destroy that
     -webkit-box and leave Safari with no clamp at all while Chrome carried on
     looking correct. Block children are full width and left-aligned anyway,
     so the column loses nothing by not being a flex container.

     Sibling margins cannot collapse into each other here because every item
     below sets margin-top only and leaves margin-bottom at zero, and the foot
     is itself a flex item, which establishes a BFC, so nothing escapes it. */
  display: block;
  margin-top: auto;
  margin-inline: calc(var(--pill-inset) - var(--card-pad));
  transition: opacity var(--swap) var(--c-ease, ease);
}

/* Each item declares its own leading space; whichever lands first has none. */
.ccard__foot > .ccard__row { margin-top: var(--gap-tight); }
.ccard__foot > .ccard__desc { margin-top: var(--gap-tight); }
.ccard__foot > .ccard__sw { margin-top: var(--gap-base); }
.ccard__foot > .ccard__buy { margin-top: var(--gap-wide); }
.ccard__foot > :first-child { margin-top: 0; }

/* The star row. Rendered only when a product carries BOTH calmy.rating and
   calmy.rating_count — see the gate in snippets/calmy-product-card.liquid. It
   used to stand in with outline stars and a (0) so the row never appeared from
   nowhere later, but on a store with no review data that placeholder is what
   every card shows, and it reads as a product nobody has reviewed.

   Nothing here reserves its height. .ccard__foot is display: block and the row
   owns its own margin-bottom, so on a card without a rating the margin leaves
   with the element and the title closes up against the top of the foot. */
.ccard__rate {
  display: flex;
  align-items: center;
  gap: 6px;
  /* Zero. This carried `margin-bottom: 6px`, which stacked under the title's
     own 6px margin-top and set the two 12px apart. The foot's scale is the
     only thing allowed to space these. */
  margin: 0;
  line-height: 1;
}
.ccard__stars { display: inline-flex; gap: 1px; }
.ccard__star {
  /* 11px, and muted below. The rating is supporting information: it sits above
     the title and must not compete with it. */
  font-size: 11px;
  line-height: 1;
  /* Unfilled stars sit a step back from filled ones so a 3-of-5 reads at a
     glance rather than as five marks of equal weight — but at the light
     neutral they measured 1.41:1 against the card, which is not "a step
     back", it is invisible. The SAME neutral at 0.95 clears the 3:1 a
     non-text indicator needs while staying plainly lighter than a filled
     star. No new hue: one token at one alpha. */
  color: rgb(var(--t-neutral-rgb) / 0.95);
}
/* A lit star is --c-muted, not --c-fg: 6.0:1 on the card against the title's
   13.9:1, so the row reads as quieter without becoming faint. That narrows the
   gap to an unlit star to 1.73:1, which would be too little if colour were the
   only thing separating them — but the two are different GLYPHS, ★ against ☆,
   so colour is reinforcing a distinction that is already there in the shape. */
.ccard__star.is-on { color: var(--c-muted); }
.ccard__rcount { font-size: 11px; color: var(--c-soft); font-variant-numeric: tabular-nums; }

/* Title left, price hard right, on one line.

   baseline alignment, so a two-line title and a one-line price still sit on a
   shared first baseline rather than the price floating at the block's centre.
   The gap is the minimum air between them; the title is the only side that
   gives, and it wraps rather than colliding. */
.ccard__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

/* min-width: 0 because the title is a flex item, where min-width defaults to
   auto and floored it at its longest word — 275px for a run-together product
   name in a 169px card.

   CLAMPED AT TWO LINES AND RESERVED AT TWO LINES, at every width. The clamp
   alone only stops a long title from growing; min-height is what stops a short
   one from shrinking. Without the reservation a one-line title pulled
   everything beneath it up by one line, and the prices across a row sat at two
   different heights — which is the whole reason the row looked ragged.

   min-height is derived from the line-height rather than typed as a pixel
   figure, so the reserved box stays exactly two lines if the type changes.

   overflow-wrap is NORMAL, not `anywhere`. `anywhere` was here to stop a long
   word overflowing, and it did, but it also drops the element's min-content
   width to a SINGLE CHARACTER. Next to .ccard__p, which is `flex: none` and
   `white-space: nowrap` and therefore never yields a pixel, that made the
   title the only thing in the row that could absorb a shortfall — and it could
   absorb all of it. On a narrow card with a compare-at price the title was
   squeezed to a one-character column and set itself vertically, one letter per
   line. word-break: normal is stated alongside it so neither property can be
   reintroduced from elsewhere without it being obvious.

   Nothing needs `anywhere` any more: the grid track is minmax(0, 1fr) and
   .ccard is min-width: 0, so neither can be floored by an unbreakable word,
   and .ccard__inner is overflow: hidden, so a word too long for the card is
   clipped rather than pushing the layout. */
.ccard__t {
  /* Takes the remainder of the row and is the only side that shrinks. */
  flex: 1 1 auto;
  /* Explicitly zero. calmy-pdp.css:296 also styles .ccard__t and sets
     `margin: 0 0 3px`; this file loads after it and wins on equal specificity,
     but only for properties it actually declares — so without this line that
     3px survived and every title-to-price gap measured 11px where the foot's
     scale said 8. The foot owns all vertical rhythm; nothing else may add to
     it. */
  margin: 0;
  min-width: 0;
  overflow-wrap: normal;
  word-break: normal;
  --t-lh: 1.35;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  min-height: calc(var(--t-lh) * 2em);
  overflow: hidden;
  text-overflow: ellipsis;
  font-family: var(--c-sans);
  font-size: 12.5px;
  font-weight: 600;
  line-height: var(--t-lh);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-fg);
}

/* One line, always: the current price at the card's full weight, the
   compare-at struck through and muted beside it, 8px apart. nowrap keeps the
   pair together rather than letting a long compare-at drop to a second line. */
.ccard__p {
  flex: none;
  display: flex;
  align-items: baseline;
  gap: var(--gap-base, 8px);
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--c-fg);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.ccard__from { font-size: 9.5px; font-weight: 400; letter-spacing: var(--c-label); text-transform: uppercase; color: var(--c-soft); }
/* .ccard__p del in calmy-pdp.css:298 adds margin-left: 6px, which stacked on
   top of the row's 8px flex gap and set the pair 14px apart. Zeroed at (0,2,0)
   so the gap is the single source of that distance. */
.ccard__p .ccard__was { margin: 0; }
.ccard__was { font-size: 11.5px; font-weight: 400; color: var(--c-soft); text-decoration: line-through; text-decoration-thickness: 1px; }

/* The price hangs on the foot's RIGHT edge, which is also the pill's right
   edge — both sit --pill-inset from the card — so the price and the control
   under it share one vertical. */
.ccard__p { justify-content: flex-end; }

/* Explicit, because calmy-carousel.css orders this row with
   `.ccard__p > span:first-of-type { order: 2 }` — written when the price was
   the first span. Here the FROM label is first, so it collected order 2 and
   the row read "$39 From $80.95", which is backwards. */
/* Compare-at first, so it sits to the LEFT of the figure that replaced it:
   struck through, then the live price. FROM stays immediately before the
   current price. */
.ccard__p.ccard__p .ccard__was { order: 1; }
.ccard__p.ccard__p .ccard__from { order: 2; }
.ccard__p.ccard__p .ccard__now { order: 3; }

/* Quieter than the title and the price above it — a step down in size and
   already a step down in colour. Its margin comes from the foot's scale. */
.ccard__desc {
  display: block;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--c-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Colour swatches ───────────────────────────────────────────────────────
   A row of dots under the descriptor, rendered by calmy-product-card.liquid
   only when the product has a colour option with more than one value.

   Small on purpose. This is a "comes in five finishes" cue, not a picker —
   choosing happens on the product page — so the dots are read as a group
   rather than as five separate controls, and they carry no hit target. */
.ccard__sw {
  display: flex;
  align-items: center;
  gap: 6px;
  /* The row is exactly one swatch tall whether it holds four or one. */
  min-height: 14px;
}

/* AND IT KEEPS ITS ROW WHEN IT IS NOT THERE AT ALL. A product with no colour
   option renders no .ccard__sw — that is deliberate, an empty row of nothing
   is not a swatch row — but the space it would have taken still has to be
   reserved, or a card without finishes is 24px shorter in its foot than the
   card beside it and every line in the two feet stops agreeing.

   :has() lets the foot ask whether the row exists and stand in for it when it
   does not, so the reservation lives with the layout rather than being faked
   with an empty element in the markup. The height and the margin are the same
   two values the real row uses, so the two cases cannot drift apart. */
/* The reservation that stood in for a missing swatch row is gone. It was an
   ::after, so with the button now the last item in the foot it would have sat
   BELOW the button rather than where the swatches would have been. It is also
   no longer needed for what it was for: the foot is bottom-anchored inside a
   flex column whose media absorbs the slack, so the button lands on the same
   line in every card whether or not the card above it has swatches. */

/* Scoped through .ccard__sw so these beat `.ccard__sw span` in
   calmy-pdp.css:302 — an older implementation of this same row that is still
   in the file. At a single class mine lost, so the dots were sized 11px with a
   1px border by that rule, and the "+N" was being squashed into an 11px circle
   along with them. */
.ccard__sw .ccard__swatch {
  flex: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  /* A real 1px hairline in --c-line, the same colour the card's own edge uses.
     .calmy * is border-box, so the 14px is the outer size and the border does
     not push the row wider. This replaces an inset box-shadow: with a fill
     that can now be a photograph, a ring drawn inside the circle was landing
     on top of the image rather than around it. */
  border: 1px solid var(--c-line);
  /* A variant photograph arrives as a background-image. cover crops it to fill
     the circle at any aspect ratio, centred. */
  background-size: cover;
  background-position: 50% 50%;
  background-repeat: no-repeat;
}

/* The overflow count reads as one more item in the row: the same 14px height
   and the same hairline as a swatch, so the row has a single rhythm rather
   than four circles and a stray number. Width is auto — `.ccard__sw span` in
   calmy-pdp.css:302 pins any span in here to 11px square, which clipped the
   digits. */
.ccard__sw .ccard__swmore {
  flex: none;
  width: auto;
  min-width: 14px;
  height: 14px;
  padding: 0 5px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--c-line);
  border-radius: 999px;
  font-family: var(--c-sans);
  font-size: 9.5px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.02em;
  color: var(--c-muted);
  font-variant-numeric: tabular-nums;
}

/* ---- The pill -------------------------------------------------------------
   Positioned, not in flow, so it can slide without resizing the card. Solid
   light fill, inset from the card edges. Visible at rest on touch; on a
   pointer device it waits below the edge until hover. */
/* IN FLOW, not positioned. It used to be absolutely placed against the card's
   bottom inset, which meant the card had to reserve height for it and the gap
   above it was a padding calculation rather than part of the foot's rhythm.
   As the last item in the foot it simply takes its own height, and the foot's
   own bottom-anchoring keeps it level across a row. */
.ccard__buy {
  /* relative, NOT static. static cancels the .cb component's own
     `position: relative`, and .cb__fill (`position: absolute; inset: 0`,
     painted --cb-wipe = near-black) then resolved against .ccard__inner and
     blacked out the entire card on hover. See assets/calmy-cardhover.css. */
  position: relative;
  z-index: 2;
  width: 100%;
  /* 46px is the design height; 44 is the floor a finger needs. min-height
     rather than height so a wrapped label can never crush it below that. */
  height: auto;
  min-height: max(var(--pill-h), 44px);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border-radius: 999px;
  /* Transparent, so the one continuous cream reads straight through the
     button and only the outline separates it. */
  background: transparent;
  /* A hairline as well as the fill. On alternating bands the card ground is
     itself --c-white, so fill alone left the pill invisible on touch, where
     it is the one control on the card and is on screen the whole time. Over
     the hover photograph the fill carries it and the hairline disappears
     into the edge. */
  /* A DARK hairline, not --c-line. The old border was the neutral the card's
     own edge used, which against the cream left the button barely drawn; the
     button is the one control on the card and has to be unmistakable. */
  border: 1px solid var(--t-ink);
  color: var(--c-fg);
  transition: opacity var(--swap) var(--c-ease, ease),
              transform 260ms var(--c-ease, ease),
              background-color 250ms var(--c-ease, ease),
              border-color 250ms var(--c-ease, ease),
              color 250ms var(--c-ease, ease);
}
/* ── The pill as a .cb ──────────────────────────────────────────────────────
   The pill is positioned by its four insets, and the button component's own
   sizing fought every one of them: .cb sets min-height: 50px over the 46px
   --pill-h, and cb--full sets width: 100%, which resolves against the CARD
   rather than the inset box and pushed the pill a full --pill-inset past the
   right edge. That is why it read as oversized, full-bleed and hanging off
   the card's bottom corner.

   cb--full is no longer passed at all. An absolutely positioned box with
   both left and right set and width: auto fills exactly the space between
   them, which is the geometry this pill was designed with. */
.ccard__buy.cb {
  min-height: 0;
  height: var(--pill-h);
  width: auto;
  padding-inline: 14px;
  /* .ccard__buy sets gap: 6px for the old three-span layout. The layers are
     absolute or visually hidden now, so a gap only pads the flow copy. */
  gap: 0;
}

/* ── Truncating the name, and only at rest ─────────────────────────────────
   .cb__label is the copy in normal flow, so it is the one that has to fit.
   Made a flex row so the name can be the only part that gives: BUY and the
   price hold their size, the name takes what is left and ellipses.

   padding-inline-start replaces the text-indent the non-flex label used —
   the tracking is trailing space on the last letter, and without the
   matching lead the label sits visibly left of centre.

   The .cb__i track copies are deliberately NOT covered by this. They are
   max-content and nowrap, so the marquee scrolls the FULL title: the pill
   fits at rest and completes itself on hover. */
.ccard__buy .cb__label {
  display: flex;
  align-items: baseline;
  gap: 0.5ch;
  min-width: 0;
  max-width: 100%;
  text-indent: 0;
  padding-inline-start: var(--t-track, 0.2em);
}
.ccard__buy .cb__label .cb__nm {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The pill's resting fill. The component's outline variant is transparent by
   design; on a card the pill needs its own ground, because at rest it sits
   over a photograph. Hover is left entirely to .cb__fill — an override here
   would repaint the ground the face label is measured against and put white
   text on a cream pill for the length of the wipe, which is the exact fault
   the two-layer fill was built to remove. */
.ccard__buy.cb {
  background: transparent;
  border-color: var(--t-ink);
}

/* ---- Hover, desktop pointers only -----------------------------------------
   THREE conditions, and the width one is not redundant. Some Android browsers
   and any phone paired with a stylus or mouse report `hover: hover` and
   `pointer: fine`, and on those devices a tap LATCHES :hover until you tap
   elsewhere — the card fell into its hover state and stayed there, showing the
   full-bleed image and the pill with the name, price and descriptor faded out.
   That is exactly the "card content is missing on mobile" report.

   The width floor means a phone can never enter this state whatever it claims
   about its pointer, so the resting content is permanent there. */
@media (hover: hover) and (pointer: fine) and (min-width: 1000px) {
  /* THE IMAGE SWAP IS THE ONLY HOVER BEHAVIOUR.

     It used to be five at once: the foot faded out, the category turned white,
     the badge changed colour, the buy pill slid up from below the card edge and
     the product shot faded away. Each was defensible on its own and together
     they meant pointing at a card rearranged it. All removed.

     The pill is consequently visible at rest here, as it already was on touch,
     so the card reads the same way on every device. */
  .ccard--swap .ccard__inner:hover .ccard__hover,
  .ccard--swap .ccard__inner:focus-visible .ccard__hover { opacity: 1; }
}

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

/* ---------- Grid rhythm ---------- */
.ccar__track,.cgrid{gap:34px 14px}
@media(min-width:700px) and (max-width:999px){.ccar__track,.cgrid{grid-template-columns:repeat(3,minmax(0,1fr));gap:48px 20px}}
@media(min-width:1000px){.ccar__track,.cgrid{grid-template-columns:repeat(4,minmax(0,1fr));gap:64px 28px}}

/* ---------- Section headings: one scale, 28 / 38 ---------- */
.ccar__h,.csec__h,.cstory__h,.ced__h,.ccol__h,.csg__h{font-family:var(--c-serif);font-weight:400}
.ccar__h{font-size:28px;letter-spacing:-.026em;line-height:1.08}
@media(min-width:1000px){.ccar__h{font-size:38px}}
.ccar__head{margin-bottom:26px;align-items:baseline}
@media(min-width:1000px){.ccar__head{margin-bottom:44px}}
.ccar{padding:var(--c-sp-tight) 0}
.cstory{padding:var(--c-sp-tight) 0}
.ccar__all{font-size:9px;letter-spacing:var(--c-eyebrow)}
.ccar--surface{background:var(--c-surface)}
.chl__h{font-size:10px;letter-spacing:var(--c-eyebrow);text-transform:uppercase;color:var(--c-soft);margin:0 0 14px;font-weight:400}

/* ---------- Collection toolbar ---------- */
.ccol__head{padding:20px 20px 12px}
@media(min-width:1000px){.ccol__head{padding:48px 40px 24px}}
.ccol__h{letter-spacing:-.026em;font-size:28px;line-height:1.08}
@media(min-width:1000px){.ccol__h{font-size:38px}}
.ccol__d{font-size:13.5px;line-height:1.7;margin:12px auto 0;max-width:46ch}
@media(min-width:1000px){.ccol__d{font-size:14px}}
.ccol__bar{border-top:1px solid var(--c-hair);border-bottom:1px solid var(--c-hair);padding-block:6px;margin-bottom:22px;align-items:center}
@media(min-width:1000px){.ccol__bar{padding-block:8px;margin-bottom:32px}}
.ccol__count{letter-spacing:var(--c-label);font-size:10px;color:var(--c-soft)}
.ccol__tools{gap:22px}
.ccol__btn,.ccol__sel{letter-spacing:var(--c-label);font-size:10px;transition:color .18s var(--c-ease)}
.ccol__btn:hover,.ccol__sel:hover{color:var(--c-clay)}
.ccol__sel{background-image:linear-gradient(45deg,transparent 50%,var(--c-soft) 50%),linear-gradient(135deg,var(--c-soft) 50%,transparent 50%);background-position:calc(100% - 6px) calc(50% + 1px),calc(100% - 2px) calc(50% + 1px);background-size:4px 4px,4px 4px;background-repeat:no-repeat;padding-right:16px}

/* ---------- Benefit band grounds ---------- */
.cben--ivory{background:var(--c-bg);color:var(--c-fg)}
.cben--div.cben--ivory,.cben--div.cben--cream{border-top:1px solid var(--c-hair);border-bottom:1px solid var(--c-hair)}
.cben--ivory .cben__t,.cben--cream .cben__t{color:var(--c-muted);opacity:1}
.cben--ivory .cben__h,.cben--cream .cben__h{color:var(--c-fg)}


/* ═══ RANGE CARD EVENNESS ══════════════════════════════════════════════════ */

/* Equal heights, with the title and price bottom-aligned. The rail's items
   stretch, the inner is a column, and the foot takes the leftover — so a card
   with a short title and one with a long one still put their prices on the
   same line. */
.crange__grid > * { align-self: stretch; }
.crange__grid > * > .ccard,
.crange__grid .ccard { height: 100%; }
.ccard__foot { margin-top: auto; }

/* THE WHOLE PRODUCT, UNCROPPED.

   Back to contain, deliberately. cover filled the frame but cropped the
   jewellery, and a ring with its band cut off is the one thing a product card
   cannot do. contain shows the piece whole at its true proportions; the small
   amount of ground it leaves is the card's own cream, so the media does not
   read as a separate panel inside the card.

   The padding that used to sit around a contained image is gone with it — it
   was what made the product look lost — so the piece fills as much of the
   frame as its own aspect ratio allows. */
.ccard__media.ccard__media.ccard__media {
  flex: 1 1 auto;
  min-height: 0;
  position: relative;
  display: block;
  overflow: hidden;
  /* No radius and no separate ground: the media sits ON the card surface, so
     there is nothing to round off and nothing to distinguish from it. */
  border-radius: 0;
  background: transparent;
}
.ccard__media .ccard__img.ccard__img.ccard__img,
.ccard__media .ccard__hover.ccard__hover.ccard__hover {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  object-fit: contain;
  object-position: center;
}


/* ═══ CARD HOVER: THE SWAP, AND NOTHING ELSE ══════════════════════════════ */

/* Both images in the same fixed-ratio frame, both absolute, so neither can
   contribute height and the swap cannot move the card by a pixel. */
.ccard__media .ccard__hover {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  transition: opacity 250ms var(--c-ease, ease);
  pointer-events: none;
}

/* The card itself never responds. Stated rather than assumed: these were
   measured as already absent, and naming them stops the next change quietly
   reintroducing one. */
.ccard__inner,
.ccard__inner:hover,
.ccard__inner:focus-visible {
  transform: none;
  box-shadow: none;
  transition: none;
}

/* ── Below 700px: the title and the price stack ────────────────────────────
   Side by side, the row gives the price whatever it asks for (flex: none,
   nowrap) and the title whatever is left. On a 169px column with a compare-at
   price that left the title around 60px, which is not a column you can set a
   product name in. Stacked, the title gets the full card width and the price
   sits under it, and neither has to negotiate with the other.

   Above 700px this rule does not apply and the side-by-side row is unchanged. */
@media (max-width: 699px) {
  /* The pill drops the product name. It was ellipsing to "BUY SU… · $39",
     which spends the pill's width on a fragment that identifies nothing — the
     title is directly above it on the card. The separator lives inside .cb__nm
     so hiding the name does not leave a stray "·" behind, and the
     visually-hidden copy that carries the accessible name is a different
     element and still says the whole thing.

     Everything else that used to live in this block — the two-line clamp, the
     right-aligned price, the compare-at ordering — is now unconditional, so
     a card has the same structure at every width. */
  .ccard__buy .cb__nm { display: none; }
}

