/** Shopify CDN: Minification failed

Line 915:10 Expected identifier but found whitespace
Line 915:15 Unexpected ";"

**/
/* The three-step .cdel rules and the one-line .cdelv rules that used to live
   here are gone. The class name is reused by the new dated delivery track, and
   the old grid rules were laying its lead paragraph and its track side by side
   in two narrow columns. Reusing a class means retiring what it used to mean. */
:root{--c-bg:var(--t-page);--c-fg:var(--t-ink);--c-muted:var(--t-neutral);--c-soft:var(--t-neutral);--c-line:var(--t-neutral-lt);--c-hair:var(--t-card);--c-surface:var(--t-page);--c-r:2px;--c-max:1280px;--c-ease:cubic-bezier(.22,.61,.36,1);--c-card-ratio:1}
.calmy,.calmy *{box-sizing:border-box}
.calmy{color:var(--c-fg);-webkit-font-smoothing:antialiased}
.calmy-wrap{max-width:var(--c-max);margin:0 auto;padding:0 20px}
@media(min-width:1000px){.calmy-wrap{padding:0 40px}}
.calmy-sr{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
@media(max-width:999px){.shopify-section:has(> .cpdp){margin-block-start:0}}
body:has(.cstick){padding-bottom:78px}

/* ============================================================================
   SOLE OWNER OF THE PRODUCT PAGE.
   The purchase column is one continuous flow: offer, title, tagline, rating, price,
   benefits, quantity, finish, size, add to cart, payment, trust, delivery. Every element
   is quieter than Add to cart, which is the only heavy object in the column.
   ============================================================================ */

.cpdp{padding-bottom:8px}
@media(min-width:1000px){.cpdp{padding-bottom:24px}}
.cpdp__grid{display:block}
@media(min-width:1000px){.cpdp__grid{display:grid;grid-template-columns:60fr 40fr;gap:72px;align-items:start;max-width:var(--c-max);margin:0 auto;padding:0 40px}}
/* The breadcrumb runs at every width.

   It was desktop-only, which left mobile with no way back to the collection
   except the browser button - and mobile is where that matters most, because
   there is no visible navigation beside it. Compact rather than absent. */
.cbread{display:block;font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--c-soft);padding:2px 20px 0}
.cbread ol{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none}
.cbread ol::-webkit-scrollbar{display:none}
.cbread li{white-space:nowrap}
.cbread a{color:inherit;text-decoration:none}
@media(min-width:1000px){.cbread{display:block;font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--c-soft);padding:20px 40px 12px;max-width:var(--c-max);margin:0 auto}.cbread a{color:inherit;text-decoration:none}.cbread a:hover{color:var(--c-fg)}}

/* ================= Gallery ================= */
.cgal{position:relative;background:var(--c-bg)}
.cgal__track{display:flex;overflow-x:auto;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;scrollbar-width:none;overscroll-behavior-x:contain}
.cgal__track::-webkit-scrollbar{display:none}
.cgal__item{flex:0 0 100%;scroll-snap-align:center;background:var(--c-bg);position:relative;aspect-ratio:1/1;max-height:76vh;overflow:hidden}
.cgal__item img,.cgal__item video{width:100%;height:100%;object-fit:contain;display:block;padding:1% 3% 3%}
.cgal__badge{position:absolute;top:8px;left:20px;z-index:2;font-size:9px;letter-spacing:.16em;text-transform:uppercase;color:var(--c-soft)}
.cgal__count{position:absolute;right:16px;bottom:12px;z-index:2;font-size:10.5px;letter-spacing:.14em;color:var(--c-fg);font-variant-numeric:tabular-nums;pointer-events:none;background:rgb(var(--t-page-rgb) / .86);backdrop-filter:blur(6px);padding:5px 10px;border-radius:999px}
@media(min-width:1000px){
 .cgal__track{display:grid;grid-template-columns:1fr 1fr;gap:0;overflow:visible}
 .cgal__item{aspect-ratio:1/1;max-height:none}
 .cgal__item img,.cgal__item video{padding:6%}
 .cgal__item--wide{grid-column:1 / -1;aspect-ratio:5/4}
 .cgal__item--wide img{padding:5%}
 .cgal__item img{transition:transform .9s var(--c-ease)}
 .cgal__item:hover img{transform:scale(1.03)}
 .cgal__count,.cgal__badge{display:none}
 .cgal--few .cgal__track{grid-template-columns:1fr;max-width:660px}
 .cgal--few .cgal__item--wide{aspect-ratio:1/1}
}

/* ================= Purchase column ================= */
.cinfo{padding:16px 20px 0}
/* The buy column is the TALLER of the two (about 2013px against the gallery's
   733px), so `position: sticky` here never had anything to do: an element
   taller than its scrollport simply scrolls until its bottom edge arrives.
   Meanwhile the short column, which is the one that should pin, was
   `position: relative`. The sticky was on the wrong column - it now lives on
   .cgal, in the gallery block further down. */
@media(min-width:1000px){.cinfo{padding:26px 0 0}}

/* Offer strip: a quiet inset panel, never a coupon banner. */
/* The offer panel is a panel from this column, not a promo banner.

   It had a different ground from everything around it, no corner radius and a
   2px clay rule down its left edge that appears nowhere else on the page. It
   now takes the same treatment as the size finder and the engraving panel -
   same surface, same hairline, same 2px radius - with the accent reduced to a
   hairline so the offer still has an identity without shouting. */
.coffer{display:flex;align-items:center;gap:12px;padding:13px 14px;margin:0 0 18px;
  background:var(--c-white,var(--t-page));border:1px solid var(--c-hair);
  border-left:1px solid var(--c-clay);border-radius:var(--c-r,2px)}
.coffer__ic img{width:22px;height:22px;object-fit:contain;display:block}
.coffer__b{display:flex;flex-direction:column;gap:2px;min-width:0}
.coffer__h{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--c-fg)}
.coffer__t{font-size:12.5px;color:var(--c-muted);line-height:1.5}
.coffer__code{margin-left:auto;font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--c-clay);border:1px dashed var(--c-line);padding:5px 9px;white-space:nowrap}

.cinfo__title{font-family:var(--c-serif,Georgia,serif);font-size:26px;line-height:1.1;letter-spacing:-.028em;margin:0 0 10px;font-weight:400}
@media(min-width:1000px){.cinfo__title{font-size:36px;margin:0 0 12px}}
.cinfo__tagline{font-size:14.5px;line-height:1.6;color:var(--c-muted);margin:0 0 14px;max-width:44ch}
.cinfo__ratinglink{display:block;text-decoration:none;color:inherit;margin:0 0 12px}
.cinfo__ratinglink:hover{opacity:.75}
.cinfo__rating{margin:0;font-size:12px;color:var(--c-muted)}
.cinfo__rating:empty{display:none}
.cinfo__price{display:flex;align-items:baseline;gap:10px;font-size:20px;color:var(--c-fg);margin:0 0 20px;font-variant-numeric:tabular-nums}
@media(min-width:1000px){.cinfo__price{font-size:22px}}
.cinfo__price del{color:var(--c-soft);font-size:15px;text-decoration-thickness:.5px}
.cinfo__price--sale>span:first-child{color:var(--c-clay)}

/* Three benefits: a seal mark, not a bullet dot. */
.cben3{list-style:none;margin:0 0 26px;padding:20px 0;border-top:1px solid var(--c-hair);border-bottom:1px solid var(--c-hair);display:flex;flex-direction:column;gap:11px}
.cben3 li{display:flex;align-items:flex-start;gap:11px;font-size:14px;line-height:1.5;color:var(--c-fg);margin:0}
.cben3 svg{width:15px;height:15px;flex:none;margin-top:2px;fill:none;stroke:var(--c-clay);stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round}

/* Quantity tiers. Totals are price x quantity - no saving is implied anywhere. */
.ctiers{display:flex;flex-direction:column;gap:8px;margin:0 0 26px}
.ctiers input{position:absolute;opacity:0;pointer-events:none}
.ctier{display:flex;align-items:center;gap:12px;padding:10px 14px 10px 10px;cursor:pointer;
  border:1px solid var(--c-line);border-radius:var(--c-r);background:none;
  transition:border-color .18s var(--c-ease),background .18s var(--c-ease)}
.ctier:hover{border-color:var(--c-fg)}
.ctiers input:checked+.ctier{border-color:var(--c-fg);background:var(--c-surface);box-shadow:inset 0 0 0 1px var(--c-fg)}
.ctiers input:focus-visible+.ctier{outline:1px solid var(--c-fg);outline-offset:3px}
.ctier__m{width:44px;height:44px;flex:none;background:var(--c-bg);display:block}
.ctier__m img{width:100%;height:100%;object-fit:contain;display:block}
.ctier__b{display:flex;flex-direction:column;gap:2px;min-width:0}
.ctier__n{font-size:14px;color:var(--c-fg)}
.ctier__s{font-size:11.5px;color:var(--c-soft)}
.ctier__flag{font-size:9px;letter-spacing:.16em;text-transform:uppercase;color:var(--c-clay);margin-left:auto}
.ctier__p{margin-left:auto;font-size:14px;font-variant-numeric:tabular-nums;white-space:nowrap}
.ctier__flag+.ctier__p{margin-left:12px}

/* ================= Selectors ================= */
.cvar{margin:0 0 24px}
.cvar__head{display:flex;justify-content:space-between;align-items:baseline;gap:12px;margin:0 0 12px;min-height:16px}
.cvar__label{font-size:10px;letter-spacing:.22em;text-transform:uppercase;color:var(--c-soft)}
.cvar__value{font-size:13.5px;color:var(--c-fg);margin-left:9px}
.cvar__guide{font-size:10px;letter-spacing:.16em;text-transform:uppercase;background:none;border:0;padding:0;color:var(--c-muted);cursor:pointer;font-family:inherit;text-decoration:underline;text-underline-offset:4px;text-decoration-thickness:.5px;transition:color .18s var(--c-ease)}
.cvar__guide:hover{color:var(--c-clay)}
.cvar__opts{display:flex;flex-wrap:wrap;gap:10px}
.cvar input{position:absolute;opacity:0;pointer-events:none}
.cvar__sw{width:44px;height:44px;border-radius:50%;border:1px solid rgb(var(--t-ink-rgb) / .10);overflow:hidden;cursor:pointer;display:block;background:var(--c-surface);position:relative;transition:box-shadow .22s var(--c-ease)}
.cvar__sw img{width:100%;height:100%;object-fit:cover;display:block}
.cvar input:checked+.cvar__sw{box-shadow:0 0 0 2px var(--c-bg),0 0 0 3px var(--c-fg);border-color:transparent}
.cvar input:focus-visible+.cvar__sw,.cvar input:focus-visible+.cvar__btn{outline:1px solid var(--c-fg);outline-offset:3px}
.cvar__btn{min-width:52px;height:44px;padding:0 14px;border:1px solid var(--c-line);border-radius:var(--c-r);display:inline-flex;align-items:center;justify-content:center;gap:7px;font-size:13.5px;line-height:1;font-family:inherit;cursor:pointer;background:none;color:var(--c-fg);font-variant-numeric:tabular-nums;transition:border-color .18s var(--c-ease),background .18s var(--c-ease),color .18s var(--c-ease)}
.cvar__btn:hover{border-color:var(--c-fg)}
.cvar__btn small{font-size:11px;color:var(--c-soft)}
.cvar input:checked+.cvar__btn{background:var(--c-fg);border-color:var(--c-fg);color:var(--c-bg)}
.cvar input:checked+.cvar__btn small{color:inherit;opacity:.7}
.cvar input:disabled+.cvar__btn{opacity:.4;border-color:var(--c-hair);color:var(--c-soft);cursor:not-allowed;text-decoration:line-through;text-decoration-thickness:.5px}
.cvar input:disabled+.cvar__sw{opacity:.35;cursor:not-allowed;position:relative}
.cvar input:disabled+.cvar__sw:after{content:"";position:absolute;inset:0;background:linear-gradient(to top left,transparent calc(50% - .5px),var(--c-fg) calc(50% - .5px),var(--c-fg) calc(50% + .5px),transparent calc(50% + .5px))}
.cvar__fit{display:inline-flex;align-items:center;gap:10px;font-size:13px;border:1px solid var(--c-hair);background:none;padding:13px 16px;color:var(--c-muted)}
.cvar__fit span{width:4px;height:4px;border-radius:50%;background:var(--c-soft);flex:none}

/* ================= Add to cart ================= */
.catc{display:block;width:100%;height:56px;margin-top:24px;border:0;border-radius:15px;background:var(--c-espresso);color:var(--c-cream);font-family:inherit;font-size:11px;letter-spacing:.2em;text-transform:uppercase;cursor:pointer;transition:background-color .2s var(--c-ease)}
/* THE PALE HOVER WAS opacity:.88 ON A DARK BUTTON OVER A CREAM PAGE — the page
   showed through and the button washed out. Opacity is the wrong tool for a
   hover on a solid control: it fades the label with the ground. A slightly
   lighter brown keeps the button solid and the text light. */
.catc:hover{background-color:#3A322B}
.catc:active{background-color:#191512}
.catc:focus-visible{outline:2px solid var(--c-espresso);outline-offset:3px}
/* The shared button component paints a full-size .cb__fill layer on hover.
   On this control that is a second, competing wash over a button that already
   states its own hover — and it is what made the label pale mid-transition.
   The card's buy pill was fixed the same way. */
.catc .cb__fill{display:none}
.catc .cb__label,.catc .cb__face{color:inherit}
.catc[disabled]{opacity:.35;cursor:not-allowed}
.catc__after{display:none;margin:10px 0 0;font-size:13px;color:var(--c-muted)}
.catc__after a{color:var(--c-fg)}
.is-added .catc__after{display:block}
.cerr{display:none;margin:10px 0 0;font-size:13px;color:var(--t-accent)}
.cerr.is-on{display:block}

/* Payment: understated, and only what checkout accepts. */
.cpay{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:14px 0 0}
.cpay__l{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--c-soft)}
.cpay__list{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.cpay__i{height:22px;width:auto;display:block;opacity:.85}

/* Trust grid: 2 x 2, hairlines only. */
.ctrust{list-style:none;margin:26px 0 0;padding:0;display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--c-hair);border:1px solid var(--c-hair)}
.ctrust li{margin:0;padding:14px 14px 16px;background:var(--c-bg);display:flex;flex-direction:column;gap:5px}
.ctrust__h{font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--c-fg)}
.ctrust__t{font-size:12px;line-height:1.5;color:var(--c-muted)}

/* Delivery sequence: three steps, no calendar date. */

/* ================= Why you'll love it ================= */
.cwhy{padding:0 0 8px}
.cwhy__h{font-size:10px;letter-spacing:.22em;text-transform:uppercase;color:var(--c-soft);margin:0 0 20px;font-weight:400}
.cwhy__l{list-style:none;margin:0;padding:0;display:grid;gap:18px}
@media(min-width:700px){.cwhy__l{grid-template-columns:1fr 1fr;gap:24px 40px}}
.cwhy__l li{margin:0;padding:0 0 0 22px;position:relative;font-size:15px;line-height:1.6;color:var(--c-fg)}
.cwhy__l li:before{content:"";position:absolute;left:0;top:9px;width:8px;height:1px;background:var(--c-clay)}

/* ================= Spec table ================= */
.cspec{padding:34px 0 30px}
.cspec__h{font-size:10px;letter-spacing:.22em;text-transform:uppercase;color:var(--c-soft);margin:0 0 16px;font-weight:400;font-family:inherit}
.cspec__list{margin:0;padding:0;border-top:1px solid var(--c-hair)}
.cspec__row{display:grid;grid-template-columns:1fr;gap:3px;padding:15px 0;border-bottom:1px solid var(--c-hair)}
@media(min-width:600px){.cspec__row{grid-template-columns:150px 1fr;gap:20px;align-items:baseline}}
.cspec__row dt{font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--c-soft);margin:0}
.cspec__row dd{margin:0;font-size:14.5px;line-height:1.7;color:var(--c-fg)}
.cspec__row--rt dd{color:var(--c-muted)}
.cspec__row--rt dd p{margin:0 0 8px}
.cspec__row--rt dd p:last-child{margin:0}

/* ================= Accordions ================= */
.cdet{padding:8px 0 0}
.cdet__in{max-width:760px;margin:0 auto;padding:0 20px}
@media(min-width:1000px){.cdet{padding:24px 0 0}.cdet__in{padding:0 40px}}
.cacc{border-top:1px solid var(--c-hair)}
.cacc details{border-bottom:1px solid var(--c-hair)}
.cacc summary{list-style:none;cursor:pointer;padding:20px 0;font-size:11px;letter-spacing:.16em;text-transform:uppercase;display:flex;justify-content:space-between;align-items:center;gap:12px;min-height:44px;transition:color .18s var(--c-ease)}
.cacc summary:hover{color:var(--c-clay)}
.cacc summary::-webkit-details-marker{display:none}
.cacc summary:after{content:"";width:7px;height:7px;border-right:1px solid var(--c-soft);border-bottom:1px solid var(--c-soft);transform:rotate(45deg) translateY(-2px);transition:transform .25s var(--c-ease);flex:none}
.cacc details[open] summary:after{transform:rotate(225deg) translateY(-2px)}
.cacc__body{padding:0 0 24px;font-size:14.5px;line-height:1.75;color:var(--c-muted)}
.cacc__body p{margin:0 0 10px}
.cacc__body p:last-child{margin:0}

/* ================= Customer content ================= */
.cugc{display:flex;gap:14px;overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;margin:0 -20px;padding:0 20px;overscroll-behavior-x:contain}
.cugc::-webkit-scrollbar{display:none}
.cugc>*{flex:0 0 76%;max-width:76%;scroll-snap-align:start;min-width:0}
.cugc>*:last-child{margin-right:20px}
@media(min-width:1000px){
 .cugc{display:grid;grid-template-columns:repeat(3,1fr);gap:24px;margin:0;padding:0;overflow:visible}
 .cugc>*{flex:auto;max-width:none}
 .cugc>*:last-child{margin-right:0}
}
.cugc__i{display:block;position:relative;aspect-ratio:4/5;background:var(--c-surface);overflow:hidden;text-decoration:none;color:inherit}
.cugc__i img,.cugc__i video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.cugc__c{position:absolute;left:14px;bottom:12px;z-index:2;font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--t-white);text-shadow:0 1px 8px rgb(var(--t-ink-rgb) / .5)}

/* ================= Sticky ATC ================= */
.cstick{position:fixed;left:0;right:0;bottom:0;z-index:60;background:rgb(var(--t-page-rgb) / .96);backdrop-filter:blur(12px);border-top:1px solid var(--c-hair);padding:9px 16px calc(9px + env(safe-area-inset-bottom));display:flex;align-items:center;transform:translateY(110%);transition:transform .3s var(--c-ease)}
.cstick.is-on{transform:translateY(0)}
/* Thumbnail sizing moved to .cstick__thumb; this blanket rule also hit the swatch images. */
.cstick__txt{flex:1;min-width:0;line-height:1.35}
.cstick__t{font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}
.cstick__p{font-size:12px;color:var(--c-soft);font-variant-numeric:tabular-nums}
.cstick .catc{width:auto;padding:0 22px;height:44px;flex:none;margin:0;font-size:10px;letter-spacing:.14em;border-radius:14px}
/* The bar runs at every width now.

   It used to be hidden from 1000px, on the assumption that a desktop visitor
   can always scroll back up. They can, but the buy column here is around
   1560px tall, so "back up" is most of a page - and the swatch row in the bar
   is a real control, which makes it useful rather than merely a shortcut. */
@media (min-width: 1000px) {
  .cstick {
    padding-inline: max(40px, calc((100vw - var(--c-max)) / 2 + 40px));
    gap: 0;
  }
  .cstick__row { gap: 16px; }
  /* Name left, swatches centred, button right. The name stops absorbing the
     slack so the auto margins on the swatch strip can take it instead. */
  .cstick__txt { flex: 0 1 auto; max-width: 34ch; }
  .cstick__sw { margin-inline: auto; gap: 8px; }
  .cstick__swb { width: 32px; height: 32px; }
  .cstick__t { font-size: 13.5px; }
  .cstick__p { font-size: 13.5px; }
  .cstick__cta { min-width: 190px; }
}

/* Mobile reserves room so the bar never covers the last line of the page. */

/* ================= Product story ================= */
.cstory{padding:44px 0}
@media(min-width:1000px){.cstory{padding:80px 0}}
.cstory__h{font-family:var(--c-serif,Georgia,serif);font-size:28px;font-weight:400;margin:0 0 16px;line-height:1.08;letter-spacing:-.026em}
@media(min-width:1000px){.cstory__h{font-size:38px}}
.cstory__p{font-size:15.5px;line-height:1.8;color:var(--c-muted);max-width:46ch;margin:0}
.cstory__p p{margin:0 0 12px}
.cstory__p p:last-child{margin:0}
.chiw{display:grid;gap:28px}
@media(min-width:1000px){.chiw{grid-template-columns:1.15fr 1fr;gap:80px;align-items:center}}
.chiw__media{background:transparent;aspect-ratio:4/5;overflow:hidden}
@media(min-width:1000px){.chiw__media{aspect-ratio:1/1}}
.chiw__media img,.chiw__media video{width:100%;height:100%;object-fit:contain;padding:3%;display:block}
.clife{background:var(--c-surface)}
.clife img{width:100%;display:block;aspect-ratio:4/5;object-fit:cover}
@media(min-width:1000px){.clife img{aspect-ratio:21/9}}
.cgift{display:grid;gap:28px;align-items:center}
@media(min-width:1000px){.cgift{grid-template-columns:1fr 1fr;gap:72px}}
.cgift img{width:100%;display:block;aspect-ratio:4/5;object-fit:cover}
@media(min-width:1000px){.cgift img{aspect-ratio:1/1}}

/* ================= Product rows ================= */
.ccar{padding:40px 0}
@media(min-width:1000px){.ccar{padding:76px 0}}
.ccar__head{display:flex;justify-content:space-between;align-items:baseline;margin:0 0 20px}
@media(min-width:1000px){.ccar__head{margin:0 0 30px}}
.ccar__h{font-family:var(--c-serif,Georgia,serif);font-size:28px;font-weight:400;margin:0;letter-spacing:-.026em}
@media(min-width:1000px){.ccar__h{font-size:38px}}
.ccar__all{font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--c-soft);text-decoration:underline;text-underline-offset:4px;white-space:nowrap}
.ccar__all:hover{color:var(--c-fg)}
/* repeat(2, minmax(0, 1fr)), not 1fr 1fr. A bare `1fr` is shorthand for
   minmax(auto, 1fr), and that `auto` minimum floors the column at the
   widest thing inside it that cannot break. One product title with a long
   unbreakable word measured 378px of min-content, so the second column was
   sized to 378px inside a 350px grid and the row ran 153px past the
   viewport. minmax(0, ...) drops the floor so the columns are free to
   shrink to their share and the card contents deal with the overflow. */
.ccar__track,.cgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:26px 12px;margin:0;padding:0;overflow:visible}
@media(min-width:1000px){.ccar__track,.cgrid{grid-template-columns:repeat(4,minmax(0,1fr));gap:44px 26px}}

/* ================= Product card base ================= */
.ccard{display:block;text-decoration:none;color:inherit;position:relative}
.ccard__media{position:relative;background:var(--c-surface);overflow:hidden;aspect-ratio:var(--c-card-ratio);display:block;border:0}
.ccard__media img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;display:block;transition:opacity .4s var(--c-ease)}
.ccard__img2{opacity:0}
@media(hover:hover){.ccard:hover .ccard__img2{opacity:1}.ccard:hover .ccard__img1{opacity:0}}
/* Badge styling lives in calmy-cardsurface.css - one pill for every card on the site. The copy that was here re-set colour after it and turned the Sale pill's text back to ink on clay. */
.ccard__body{padding:12px 0 0}
.ccard__t{font-size:13px;line-height:1.35;margin:0 0 3px}
.ccard__p{font-size:13px;margin:0;color:var(--c-muted);font-variant-numeric:tabular-nums}
.ccard__p del{color:var(--c-soft);margin-left:6px;font-size:12px}
.ccard__rating{font-size:11px;color:var(--c-soft)}
.ccard__rating:empty{display:none}
.ccard__sw{display:flex;gap:5px;margin:9px 0 0}
.ccard__sw span{width:11px;height:11px;border-radius:50%;border:1px solid rgb(var(--t-ink-rgb) / .10);display:block;background-size:cover;background-position:center}
.ccard__sw i{font-style:normal;font-size:10px;color:var(--c-soft);line-height:11px}
.ccard__qa{display:none}
@media(hover:hover) and (min-width:1000px){
 .ccard__qa{display:block;position:absolute;left:0;right:0;bottom:0;height:42px;border:0;border-radius:0;background:rgb(var(--t-white-rgb) / .92);color:var(--c-fg);font-family:inherit;font-size:9px;letter-spacing:.22em;text-transform:uppercase;cursor:pointer;opacity:0;transform:translateY(6px);transition:opacity .25s var(--c-ease),transform .25s var(--c-ease);z-index:3}
 .ccard:hover .ccard__qa{opacity:1;transform:translateY(0)}
}

/* ================= Collection ================= */
.ccol{padding:0 0 48px}
.ccol__head{padding:24px 20px 18px;text-align:center}
@media(min-width:1000px){.ccol__head{padding:48px 40px 24px}}
.ccol__h{font-family:var(--c-serif,Georgia,serif);font-size:28px;font-weight:400;margin:0;letter-spacing:-.026em}
@media(min-width:1000px){.ccol__h{font-size:38px}}
.ccol__d{font-size:14px;line-height:1.6;color:var(--c-muted);max-width:52ch;margin:12px auto 0}
.ccol__bar{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:0 20px 14px;margin:0 0 20px}
@media(min-width:1000px){.ccol__bar{padding:0 40px 14px;margin:0 0 30px}}
.ccol__count{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--c-soft)}
.ccol__tools{display:flex;align-items:center;gap:16px}
.ccol__btn{background:none;border:0;padding:0;font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--c-fg);cursor:pointer;min-height:44px;display:inline-flex;align-items:center;gap:7px;font-family:inherit}
.ccol__sel{appearance:none;background:none;border:0;font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--c-fg);font-family:inherit;cursor:pointer;min-height:44px;padding-right:14px}
/* var(--c-gutter), not a bare 20px. The bar directly above this grid uses
   `padding: 14px var(--c-gutter, 20px) 12px` (assets/calmy-collection.css),
   so the two were only ever aligned because the token happens to be 20px.
   Move --c-gutter and the count/filter row moved while the cards stayed put,
   and at a larger gutter the grid would sit outside the page's own margin.
   Both read the same token now, so they cannot drift.

   The columns are sized from what is left after this padding and the grid's
   own column gap, so at 390px: 390 - 20 - 20 = 350 for the track, minus a
   12px gap = 338, two columns of 169. Nothing extends past the viewport. */
.ccol__grid{padding:0 var(--c-gutter, 20px)}
@media(min-width:1000px){.ccol__grid{padding:0 40px;max-width:var(--c-max);margin:0 auto}}
.ccol__empty{padding:56px 20px;text-align:center;color:var(--c-soft);font-size:14px}
.ccol__pag{display:flex;justify-content:center;gap:18px;padding:40px 20px 0;font-size:12px;letter-spacing:.1em}
.ccol__pag a,.ccol__pag span{color:var(--c-soft);text-decoration:none}
.ccol__pag a:hover{color:var(--c-fg)}
.ccol__pag .is-cur{color:var(--c-fg)}
.ccol__preview,.ccar__preview{text-align:center;font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--c-soft);padding:0 20px 14px;margin:0}
.ccar__preview{text-align:left;padding:0 0 12px}

/* Filters */
.cfil__g{border-bottom:1px solid var(--c-hair)}
.cfil__g summary{list-style:none;cursor:pointer;padding:17px 20px;font-size:11px;letter-spacing:.16em;text-transform:uppercase;display:flex;justify-content:space-between;align-items:center}
.cfil__g summary::-webkit-details-marker{display:none}
.cfil__g summary:after{content:"";width:7px;height:7px;border-right:1px solid var(--c-soft);border-bottom:1px solid var(--c-soft);transform:rotate(45deg) translateY(-2px)}
.cfil__g[open] summary:after{transform:rotate(225deg) translateY(-2px)}
.cfil__list{padding:0 20px 16px;display:flex;flex-direction:column;gap:2px}
.cfil__list label{display:flex;align-items:center;gap:11px;font-size:14px;color:var(--c-muted);min-height:44px;cursor:pointer}
.cfil__list input{width:16px;height:16px;accent-color:var(--c-fg)}
.cfil__price{padding:0 20px 18px;display:flex;align-items:center;gap:10px}
.cfil__price input{width:100%;height:44px;border:1px solid var(--c-hair);background:none;padding:0 12px;font-size:14px;font-family:inherit;color:var(--c-fg)}

/* ================= Size guide ================= */
.csg::backdrop{background:rgb(var(--t-ink-rgb) / .45)}
.csg{border:0;padding:0;background:var(--c-bg);color:var(--c-fg);width:100%;max-width:520px;border-radius:var(--c-r);margin:auto auto 0;max-height:88vh}
@media(min-width:1000px){.csg{margin:auto;max-height:80vh}}
.csg__in{padding:26px 22px calc(30px + env(safe-area-inset-bottom));overflow:auto;max-height:88vh;position:relative}
.csg__h{font-family:var(--c-serif,Georgia,serif);font-size:20px;font-weight:400;margin:0 0 14px}
.csg__x{position:absolute;top:14px;right:16px;background:none;border:0;font-size:20px;line-height:1;cursor:pointer;color:var(--c-soft);min-width:44px;min-height:44px}
.csg__note{font-size:14px;line-height:1.6;color:var(--c-muted);margin:0 0 12px}
.csg__note:last-child{margin:0}
.csg table{width:100%;border-collapse:collapse;font-size:13px;margin:14px 0;font-variant-numeric:tabular-nums}
.csg th,.csg td{text-align:left;padding:9px 6px;border-bottom:1px solid var(--c-hair)}
.csg th{font-weight:400;color:var(--c-soft);font-size:10px;text-transform:uppercase;letter-spacing:.14em}
.crt-h{font-weight:500;color:var(--c-fg)}
.crt-list{margin:0 0 10px;padding-left:18px}

/* ---- Sticky buy bar -------------------------------------------------------
   Name and price on the left, live finish swatches, buy button on the right.
   The swatch row is a real control set, so it gets real hit areas. */
.cstick__row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-width: 0;
}

.cstick__thumb {
  width: 38px;
  height: 38px;
  flex: none;
  object-fit: cover;
  border-radius: var(--c-r, 2px);
  background: var(--c-surface);
}

.cstick__txt {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  flex: 1 1 auto;
}

.cstick__t {
  font-size: 12.5px;
  line-height: 1.25;
  color: var(--c-fg);
  /* The name is the first thing to give up space; the button never does. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cstick__p {
  font-size: 12.5px;
  color: var(--c-muted);
  font-variant-numeric: tabular-nums;
}

.cstick__cta {
  flex: none;
  min-width: 116px;
  margin: 0;
  padding-inline: 16px;
}

/* Swatches. Inline on the row at four finishes or fewer; on their own
   scrollable row above it past that, set by .cstick--wrap in Liquid. */
.cstick__sw {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
}
.cstick__sw input { position: absolute; opacity: 0; pointer-events: none; }

.cstick__swb {
  position: relative;
  display: block;
  width: 28px;
  height: 28px;
  flex: none;
  border-radius: 999px;
  overflow: hidden;
  cursor: pointer;
  background-size: cover;
  box-shadow: 0 0 0 1px var(--c-line);
  transition: box-shadow 0.2s var(--c-ease);
}
.cstick__swb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cstick__sw input:checked + .cstick__swb { box-shadow: 0 0 0 1.5px var(--c-fg); }
.cstick__sw input:disabled + .cstick__swb { opacity: 0.35; cursor: not-allowed; }

/* 28px is smaller than 44px, so the target is grown without moving the dot. */
/* -9, not -8. The swatch paints at 26px, so -8 gave a 42px target — two
   pixels under the 44px floor held everywhere else in this theme, and it
   escaped the sweep because a <label> wrapping a hidden radio is not caught
   by an a/button/input selector. -9 lands it on exactly 44. */
.cstick__swb::after {
  content: '';
  position: absolute;
  inset: -9px;
}

/* Past four finishes the strip takes its own line above the row rather than
   squeezing the name and the button. Same DOM either way - it is a flex-basis
   and an order, not a second copy of the markup. */
.cstick--wrap .cstick__row { flex-wrap: wrap; }
.cstick--wrap .cstick__sw {
  order: -1;
  flex-basis: 100%;
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: 2px;
}
.cstick--wrap .cstick__sw::-webkit-scrollbar { display: none; }

/* The bar is one flex row on mobile; the swatches sit between the text and the
   button, so name truncation absorbs any shortfall. */
@media (max-width: 419px) {
  .cstick__cta { min-width: 104px; font-size: 11px; padding-inline: 12px; }
  .cstick__swb { width: 26px; height: 26px; }
}

/* ---- Size finder entry card ------------------------------------------------
   A row, not a link: the whole card is the target, so it clears 44px without
   needing a padded label inside it. */
.cfind {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  margin: 4px 0 18px;
  padding: 13px 14px;
  min-height: 44px;
  text-align: left;
  background: var(--c-surface);
  border: 1px solid var(--c-hair);
  border-radius: var(--c-r, 2px);
  font: inherit;
  color: inherit;
  cursor: pointer;
  transition: border-color 0.3s var(--c-ease), background-color 0.3s var(--c-ease);
}
.cfind:hover { border-color: var(--c-line); background: var(--c-white, var(--t-white)); }

.cfind__ic { flex: none; width: 20px; height: 20px; color: var(--c-soft); }
.cfind__ic svg { width: 100%; height: 100%; display: block; }
.cfind__txt { flex: 1 1 auto; min-width: 0; }
.cfind__h { display: block; font-size: 14px; }
.cfind__t {
  display: block;
  margin-top: 2px;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--c-muted);
  text-wrap: pretty;
}
/* An explicit action rather than a bare arrow: on a quiet card the arrow alone
   does not read as something you can press. */
.cfind__go {
  flex: none;
  color: var(--c-clay);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border-bottom: 1px solid currentColor;
  padding-bottom: 1px;
  white-space: nowrap;
}

/* ---- Collapsible detail blocks --------------------------------------------
   Native <details>, so they work with JS off, take keyboard focus for free and
   open when find-in-page lands inside them. */
.cfolds { margin-top: 26px; border-top: 1px solid var(--c-hair); }

.cfold { border-bottom: 1px solid var(--c-hair); }

.cfold__s {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  min-height: 52px;
  padding-block: 14px;
  cursor: pointer;
  list-style: none;
  font-size: 14px;
  color: var(--c-fg);
}
.cfold__s::-webkit-details-marker { display: none; }
.cfold__s:focus-visible { outline: 2px solid var(--c-clay); outline-offset: 2px; }

/* Plus that becomes a minus. Drawn rather than typed so it stays optically
   centred at any font size. */
.cfold__ic {
  position: relative;
  flex: none;
  width: 12px;
  height: 12px;
}
.cfold__ic::before,
.cfold__ic::after {
  content: "";
  position: absolute;
  background: var(--c-soft);
  transition: transform 0.3s var(--c-ease), opacity 0.3s var(--c-ease);
}
.cfold__ic::before { left: 0; top: 5.5px; width: 12px; height: 1px; }
.cfold__ic::after { top: 0; left: 5.5px; width: 1px; height: 12px; }
.cfold[open] .cfold__ic::after { transform: scaleY(0); opacity: 0; }

.cfold__b {
  padding-bottom: 18px;
  font-size: 13.5px;
  line-height: 1.68;
  color: var(--c-muted);
  max-width: 60ch;
  text-wrap: pretty;
}
.cfold__b > :first-child { margin-top: 0; }
.cfold__b > :last-child { margin-bottom: 0; }
.cfold__b ul { padding-left: 1.1em; margin: 0.5em 0; }
.cfold__b li { margin-block: 0.35em; }
.cfold__b a { color: var(--c-clay); }

@media (prefers-reduced-motion: reduce) {
  .cfind,
  .cfold__ic::before,
  .cfold__ic::after { transition: none; }
}

/* ---- Inline gallery video --------------------------------------------------
   Sized like an image frame rather than a player. */
.cgal__vid { position: relative; display: block; width: 100%; height: 100%; }
.cgal__vid video,
.cgal__vid iframe {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Shopify wraps video media in its own container; make it fill the frame too. */
.cgal__vid > * { width: 100%; height: 100%; }

/* Caption on an editorial frame. Sits over the image bottom with a short
   gradient behind it so it stays readable on a light crop. */
.cgal__cap {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 34px 16px 14px;
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--c-white, var(--t-white));
  background: linear-gradient(to top, rgb(var(--t-ink-rgb) / 0.5), transparent);
  pointer-events: none;
}

/* ---- Finish descriptor -----------------------------------------------------
   The line that turns a swatch from a colour into a named finish. */
.cvar__desc {
  margin: 9px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--c-muted);
  max-width: 46ch;
  text-wrap: pretty;
}
.cvar__desc[hidden] { display: none; }

/* ---- Finish tone filters ---------------------------------------------------
   Only rendered on products with enough finishes to be worth filtering. */
.cvar__tones {
  display: flex;
  gap: 6px;
  margin: 0 0 12px;
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: 2px;
}
.cvar__tones::-webkit-scrollbar { display: none; }

.cvar__tone {
  flex: none;
  min-height: 44px;
  padding: 9px 14px;
  background: transparent;
  border: 1px solid var(--c-hair);
  border-radius: 999px;
  font: inherit;
  font-size: 12px;
  color: var(--c-muted);
  white-space: nowrap;
  cursor: pointer;
  transition: color 0.3s var(--c-ease), border-color 0.3s var(--c-ease);
}
.cvar__tone.is-active { color: var(--c-fg); border-color: var(--c-fg); }

/* Filtered-out swatches leave the flow entirely rather than dimming, so the
   remaining row closes up instead of showing gaps. */
.cvar__opts input[data-tone].is-filtered + label,
.cvar__opts input[data-tone].is-filtered { display: none; }

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

/* ═══ Buy column as a panel ═══════════════════════════════════════════════════
   The decision sits in its own surface, separate from the photography. On
   desktop it sticks, because the buy card is short and the gallery is long -
   scrolling the images should not scroll the price away. */
.cinfo__card {
  background: var(--c-surface);
  border-radius: 10px;
  box-shadow: inset 0 0 0 1px rgb(var(--t-ink-rgb) / 0.07);
  padding: 22px 18px 24px;
}

@media (min-width: 1000px) {
  .cinfo { padding: 0; }
  .cinfo__card { padding: 32px 30px 34px; }

}

/* The panel already supplies the surface, so elements that drew their own
   surface inside it would stack tone on tone. */
.cinfo__card .cfind,
.cinfo__card .coffer {
  background: var(--c-white, var(--t-white));
}

/* ═══ Gallery ═════════════════════════════════════════════════════════════════
   Mobile: full-width snap scroller, dots beneath, no rail. A thumbnail strip on
   a 390px screen costs height that belongs to the photograph. */
.cgal { position: relative; display: block; background: var(--c-bg); }
.cgal__stage { position: relative; }

.cgal__item {
  background: var(--c-surface);
  border-radius: var(--c-r, 2px);
}

/* Full bleed on mobile.

   An earlier rule higher up this file still put `padding: 1% 3% 3%` on the
   image, which left a 12px cream margin down both sides of a frame that is
   supposed to run edge to edge, and `object-fit: contain` letterboxed it
   inside that. Desktop already sets padding 0 and cover; mobile now matches,
   so the treatment is one thing at both sizes rather than two. The radius goes
   too - a rounded corner against the screen edge is not a bleed. */
@media (max-width: 999px) {
  .cgal__item.cgal__item { border-radius: 0; }
  .cgal__item img,
  .cgal__item video {
    padding: 0;
    object-fit: cover;
  }
}

/* A slim segmented progress bar, not dots.

   Dots are a fixed size each, so their row grows with the image count: at six
   they fit, at twelve they crowd the width and at twenty they wrap. The
   segments here share the width with `flex: 1`, so the indicator is the same
   size whatever the product carries - two frames or twenty - and can never
   overflow.

   It reuses the .is-on class that calmy-pdp.js already toggles in paint(), so
   there is no JavaScript change and no second source of truth for which frame
   is showing. */
.cgal__dots {
  display: flex;
  gap: 3px;
  padding: 14px var(--c-gutter, 20px) 2px;
}

.cgal__dot {
  flex: 1 1 0;
  min-width: 0;
  height: 2px;
  border-radius: 999px;
  background: var(--c-line);
  transition: background-color 0.3s var(--c-ease);
}
.cgal__dot.is-on { background: var(--c-fg); }

/* Video frames get a play mark on their thumbnail; the frame itself needs no
   affordance because it is already moving. */
.cgal__play {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--c-white, var(--t-white));
  background: rgb(var(--t-ink-rgb) / 0.22);
  pointer-events: none;
}
.cgal__play svg { width: 22px; height: 22px; }

/* The rail is desktop-only. Rendered always so the markup is one thing, hidden
   here rather than branched in Liquid. */
.cgal__railwrap { display: none; }

@media (min-width: 1000px) {
  .cgal {
    display: grid;
    grid-template-columns: 76px minmax(0, 1fr);
    gap: 14px;
    align-items: start;

    /* ── The sticky gallery ──────────────────────────────────────────────────
       This is the element that pins, not .cinfo. It works here and did not
       work there for one reason: sticky only travels while its own box is
       SHORTER than the space it has to travel through. .cgal is 733-850px
       inside a grid area as tall as the buy column (about 2013px), so it has
       roughly 1200px of travel. .cinfo filled its own area exactly and had
       none.

       The ancestor chain was checked the whole way up - .cpdp__grid, .cpdp,
       the section and main are all `overflow: visible`, and the grid is
       `align-items: start`, which is what keeps this item at its content
       height instead of stretching it to the row (a stretched item is exactly
       as tall as its area and can never stick). The scroll container is
       .page-wrapper, which the header also sticks to, so both offsets are
       measured from the same origin. */
    position: sticky;
    top: calc(var(--c-head-h) + 24px);
  }

  .cgal__railwrap {
    display: block;
    position: relative;
    /* Stretch to the row so the rail starts level with the top of the
       photograph and ends level with its bottom.

       It used to be capped at 76vh while the stage had no cap at all, so on a
       900px viewport the rail stopped 162px short of the image's bottom edge -
       and because the "more" chevron is anchored to this wrapper's bottom, the
       chevron sat in mid-air beside the picture rather than under the last
       thumbnail. Stretching ties the two together at both edges. */
    align-self: stretch;
    min-height: 0;
  }

  .cgal__rail {
    display: flex;
    flex-direction: column;
    gap: 8px;
    /* Of the wrapper, which now has a definite height from the stretch above.
       Fewer thumbnails than fit simply leave the rail short, and syncMore()
       in calmy-pdp.js keeps the chevron hidden in that case. */
    max-height: 100%;
    overflow-y: auto;
    scroll-behavior: smooth;
    scrollbar-width: none;
    padding-bottom: 2px;
  }
  .cgal__rail::-webkit-scrollbar { display: none; }

  .cgal__thumb {
    position: relative;
    flex: none;
    width: 76px;
    height: 76px;
    padding: 0;
    border: 0;
    background: var(--c-surface);
    border-radius: var(--c-r, 2px);
    overflow: hidden;
    cursor: pointer;
    box-shadow: inset 0 0 0 1px rgb(var(--t-ink-rgb) / 0.07);
    transition: box-shadow 0.25s var(--c-ease);
  }
  .cgal__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .cgal__thumb:hover { box-shadow: inset 0 0 0 1px var(--c-line); }
  .cgal__thumb.is-active { box-shadow: inset 0 0 0 1.5px var(--c-fg); }

  /* Only shown when the rail actually overflows - calmy-pdp.js unhides it. */
  /* Same trap as the rail foot: display:grid below would otherwise beat the
     UA's [hidden] rule and show a chevron that scrolls nothing. */
  .cgal__railmore[hidden] { display: none; }

  .cgal__railmore {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 76px;
    height: 30px;
    display: grid;
    place-items: center;
    border: 0;
    cursor: pointer;
    color: var(--c-fg);
    background: linear-gradient(to top, var(--c-bg) 45%, transparent);
  }
  .cgal__railmore svg { width: 18px; height: 18px; }

  /* Stage shows one frame at a time; the rail does the switching. */
  .cgal__track {
    display: block;
    overflow: visible;
  }
  .cgal__item { display: none; }
  .cgal__item.is-active { display: block; }
  /* No height cap on the stage.

     max-height: 76vh capped the frame at 684px, and a 4:5 frame 684 tall is
     only 547 wide - in a 700px column that left 150px of empty page beside the
     photograph. The ratio now decides the height and the column decides the
     width, so the image fills its side exactly. The buy card runs to about
     1560px, so an 875px image is not what makes this page long. */
  /* Capped to the viewport, because a sticky element taller than the
     scrollport can never be fully seen - it pins with its bottom permanently
     below the fold, which is a worse failure than the one this replaces.

     At 4/5 in a 677px column the frame wants about 846px; a 900px viewport
     less the 80px header and 48px of breathing room leaves 772px. The image is
     already `object-fit: cover` on desktop, so the cap takes the height and the
     column keeps the full width - no empty page beside the photograph, which is
     what the earlier `max-height: 76vh` was removed for. */
  .cgal__item,
  .cgal__item--wide {
    aspect-ratio: 4 / 5;
    max-height: calc(100svh - var(--c-head-h) - 48px);
  }
  .cgal__item img,
  .cgal__item video { object-fit: cover; padding: 0; }

  .cgal__dots { display: none; }
  .cgal__count { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .cgal__dot,
  .cgal__thumb { transition: none; }
  .cgal__rail { scroll-behavior: auto; }
}

/* ═══ Delivery line ═══════════════════════════════════════════════════════════ */
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 18px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--c-muted);
}

/* No sticky column here.

   Two attempts, both wrong for this layout. Sticking the buy card pins a
   1560px card in a 1000px viewport, so its bottom never comes back. Sticking
   the gallery unpins a third of the way down, because a grid item under
   align-items:start is only as tall as its own content and that is the sticky
   element's containing block. Keeping the purchase reachable is the sticky
   BAR's job, which is a better answer at both widths anyway. */

/* Link from the finish swatches down to the finishes section. Hidden in the
   markup and revealed by JS only when the target exists on this template. */
.cvar__more {
  display: inline-block;
  margin-top: 8px;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-clay);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding-bottom: 1px;
}
.cvar__more[hidden] { display: none; }

/* ═══ Bundle tiers ════════════════════════════════════════════════════════════
   Large selectable cards. The whole card is the control - the radio is visually
   hidden and the label carries everything, so the tap target is the card. */
.ctiers__eyebrow {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 4px 0 14px;
  font-size: 10px;
  letter-spacing: var(--c-eyebrow, 0.2em);
  text-transform: uppercase;
  color: var(--c-clay);
}
.ctiers__eyebrow span { flex: 1 1 auto; height: 1px; background: var(--c-hair); }

.ctiers { display: grid; gap: 10px; margin: 0 0 20px; }
.ctiers input { position: absolute; opacity: 0; pointer-events: none; }

.ctier {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 14px;
  padding: 13px 14px;
  min-height: 44px;
  cursor: pointer;
  background: var(--c-white, var(--t-white));
  border: 1.5px solid var(--c-hair);
  border-radius: 10px;
  transition: border-color 0.25s var(--c-ease), background-color 0.25s var(--c-ease), box-shadow 0.25s var(--c-ease);
}
.ctier:hover { border-color: var(--c-line); }

.ctiers input:checked + .ctier {
  border-color: var(--c-clay);
  background: color-mix(in srgb, var(--c-clay) 6%, var(--c-white, var(--t-white)));
  box-shadow: 0 10px 26px -18px rgb(var(--t-accent-rgb) / 0.55);
}
.ctiers input:focus-visible + .ctier { outline: 2px solid var(--c-clay); outline-offset: 2px; }

.ctier__m {
  position: relative;
  display: block;
  width: 62px;
  height: 62px;
  flex: none;
  border-radius: 8px;
  overflow: hidden;
  background: var(--c-surface);
  box-shadow: inset 0 0 0 1px rgb(var(--t-ink-rgb) / 0.06);
}
.ctier__m img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* The multiplier, so a Duo card reads as two rings rather than one photo. */
.ctier__count {
  position: absolute;
  right: 3px;
  bottom: 3px;
  padding: 1px 5px;
  border-radius: 999px;
  background: rgb(var(--t-ink-rgb) / 0.72);
  color: var(--c-white, var(--t-white));
  font-size: 9.5px;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
}

.ctier__b { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ctier__n { font-size: 15px; color: var(--c-fg); }
.ctier__s { font-size: 12.5px; color: var(--c-muted); }
.ctier__save { font-size: 12.5px; color: var(--c-clay); }
.ctier__save[hidden] { display: none; }

.ctier__prices { text-align: right; display: flex; flex-direction: column; gap: 1px; }
.ctier__was {
  font-size: 12px;
  color: var(--c-soft);
  text-decoration: line-through;
  text-decoration-thickness: 0.5px;
  font-variant-numeric: tabular-nums;
}
.ctier__was[hidden] { display: none; }
.ctier__p { font-size: 15px; color: var(--c-fg); font-variant-numeric: tabular-nums; }

/* Badge on the card edge, clear of the content. */
.ctier__flag {
  position: absolute;
  top: -9px;
  left: 14px;
  z-index: 2;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--c-fg);
  color: var(--c-white, var(--t-white));
  font-size: 9px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1.4;
}
.ctiers input:checked + .ctier .ctier__flag { background: var(--c-clay); }

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

/* ═══ Engraving ═══════════════════════════════════════════════════════════════
   A quiet panel inside the buy card, not a headline. */
.ceng {
  margin: 0 0 18px;
  padding: 13px 14px 12px;
  background: var(--c-white, var(--t-white));
  border: 1px solid var(--c-hair);
  border-radius: var(--c-r, 2px);
}

.ceng__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.ceng__label {
  font-size: 10px;
  letter-spacing: var(--c-eyebrow, 0.2em);
  text-transform: uppercase;
  color: var(--c-fg);
}
.ceng__free { font-size: 11.5px; color: var(--c-clay); }

.ceng__input {
  width: 100%;
  margin-top: 10px;
  padding: 11px 12px;
  border: 1px solid var(--c-hair);
  border-radius: var(--c-r, 2px);
  background: var(--c-surface);
  /* The serif, because what goes in here is what gets engraved. */
  font-family: var(--c-serif);
  font-size: max(16px, 1em);
  color: var(--c-fg);
  outline: none;
  transition: border-color 0.25s var(--c-ease);
}
.ceng__input::placeholder { font-family: var(--c-sans); font-size: 14px; color: var(--c-soft); }
.ceng__input:focus { border-color: var(--c-fg); }

.ceng__foot {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin: 7px 0 0;
  font-size: 11.5px;
  color: var(--c-soft);
  font-variant-numeric: tabular-nums;
}
.ceng__where { font-variant-numeric: normal; }

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

/* ═══ Finish pills ════════════════════════════════════════════════════════════
   The name lives in the control. A bare dot makes you hover to learn what a
   finish is called, and on touch there is no hover to give. */
.cvar__pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 8px 14px 8px 8px;
  border: 1px solid var(--c-hair);
  border-radius: 999px;
  background: var(--c-white, var(--t-white));
  cursor: pointer;
  transition: border-color 0.25s var(--c-ease), background-color 0.25s var(--c-ease);
}
.cvar__pill:hover { border-color: var(--c-line); }

.cvar__opts input:checked + .cvar__pill {
  border-color: var(--c-fg);
  background: var(--c-fg);
}
.cvar__opts input:checked + .cvar__pill .cvar__pilltxt { color: var(--c-white, var(--t-white)); }
.cvar__opts input:focus-visible + .cvar__pill { outline: 2px solid var(--c-clay); outline-offset: 2px; }
.cvar__opts input:disabled + .cvar__pill { opacity: 0.4; cursor: not-allowed; }

.cvar__dot {
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: 999px;
  overflow: hidden;
  display: block;
  background-size: cover;
  background-position: center;
  box-shadow: inset 0 0 0 1px rgb(var(--t-ink-rgb) / 0.12);
}
.cvar__dot img { width: 100%; height: 100%; object-fit: cover; display: block; }

.cvar__pilltxt {
  font-size: 13.5px;
  line-height: 1;
  color: var(--c-fg);
  white-space: nowrap;
  transition: color 0.25s var(--c-ease);
}

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

/* ═══ Inline reviews ══════════════════════════════════════════════════════════
   Prefix is crevin, not crev: the standalone reviews section already owns .crev
   and both appear on the product template. Reusing it meant the section's large
   serif pull-quote styling landing on this small in-column note.
   A single quote at a time with arrows either side, sitting on hairlines rather
   than in a box - it is a note inside the buy column, not another panel. */
.crevin {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 6px;
  margin: 0 0 18px;
  padding: 14px 0;
  border-top: 1px solid var(--c-hair);
  border-bottom: 1px solid var(--c-hair);
}

.crevin__go {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--c-soft);
  cursor: pointer;
  transition: color 0.2s var(--c-ease);
}
.crevin__go:hover { color: var(--c-fg); }
.crevin__go svg { width: 15px; height: 15px; }

.crevin__track { min-width: 0; }
.crevin__i[hidden] { display: none; }
.crevin__i { margin: 0; }

.crevin__head { display: flex; align-items: center; gap: 10px; }

/* Initials by default: a photograph of a customer needs their permission, two
   letters need nobody's. */
.crevin__av {
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 999px;
  overflow: hidden;
  display: grid;
  place-items: center;
  background: var(--c-surface);
  color: var(--c-muted);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  box-shadow: inset 0 0 0 1px rgb(var(--t-ink-rgb) / 0.08);
}
.crevin__av img { width: 100%; height: 100%; object-fit: cover; display: block; }

.crevin__who { min-width: 0; }
.crevin__name {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 13px;
  color: var(--c-fg);
}
.crevin__tick { display: inline-flex; width: 13px; height: 13px; color: var(--c-clay); }
.crevin__tick svg { width: 100%; height: 100%; }

.crevin__stars { display: inline-flex; gap: 1px; font-size: 11px; line-height: 1; margin-top: 2px; }
.crevin__star { color: var(--c-line); }
.crevin__star.is-on { color: var(--c-clay); }

/* Doubled-up class: Horizon styles bare <blockquote> as a display pull-quote -
   centred Playfair at around 24px - from a stylesheet that lands later, and at
   equal specificity that one wins. This is a note in a buy column, not a pull
   quote. */
.crevin .crevin__q {
  margin: 8px 0 0;
  padding: 0;
  border: 0;
  text-align: left;
  font-family: var(--c-sans);
  font-style: normal;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--c-muted);
  /* Two lines, so the buy column does not jump as reviews cycle. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

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

/* ═══ Delivery track ══════════════════════════════════════════════════════════
   Hidden until the script has produced real dates, so no half-written promise
   is ever on screen. */
.cdel {
  margin: 18px 0 0;
  padding: 14px 14px 16px;
  background: var(--c-white, var(--t-white));
  border: 1px solid var(--c-hair);
  border-radius: var(--c-r, 2px);
}
.cdel[hidden] { display: none; }

.cdel__lead {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--c-muted);
  text-wrap: pretty;
}
.cdel__lead b { font-weight: 400; color: var(--c-fg); }
.cdel__lead .cdel__clock {
  color: var(--c-clay);
  /* Tabular figures hold the seconds still without reserving a fixed width -
     a min-width sized for the longest possible countdown left a visible gap
     after it for most of the day. The one reflow is 9h to 10h, once. */
  font-variant-numeric: tabular-nums;
}

.cdel__track {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
}

.cdel__step {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 7px;
}

/* The connector is drawn from each step back to the previous one, so it can
   never overhang the ends of the track. */
.cdel__step + .cdel__step::before {
  content: "";
  position: absolute;
  right: 50%;
  top: 5px;
  width: 100%;
  border-top: 1px dashed var(--c-line);
}

.cdel__dot {
  position: relative;
  z-index: 1;
  width: 11px;
  height: 11px;
  border-radius: 999px;
  border: 1.5px solid var(--c-line);
  background: var(--c-white, var(--t-white));
}
.cdel__step.is-on .cdel__dot { border-color: var(--c-clay); background: var(--c-clay); }

.cdel__label {
  font-size: 9.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--c-fg);
}
.cdel__when {
  font-size: 11px;
  line-height: 1.35;
  color: var(--c-soft);
  min-height: 1.35em;
}

/* The discount code is a button that copies itself. Its label is the code, so
   a blocked clipboard costs the visitor nothing. */
.coffer__code {
  border: 1px dashed var(--c-clay);
  border-radius: 999px;
  background: transparent;
  color: var(--c-clay);
  font: inherit;
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 6px 12px;
  min-height: 32px;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.2s var(--c-ease), color 0.2s var(--c-ease), border-style 0.2s var(--c-ease);
}
.coffer__code:hover { background: var(--c-clay); color: var(--c-white, var(--t-white)); }
.coffer__code.is-copied { border-style: solid; background: var(--c-clay); color: var(--c-white, var(--t-white)); }
/* Grows the target to 44px without moving the pill. */
.coffer__code { position: relative; }
.coffer__code::after { content: ''; position: absolute; inset: -6px -4px; }

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

/* Star rating row under the subtitle. Renders only from figures a merchant can
   evidence, or from a connected provider - never from nothing. */
.crate {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 12px;
  font-size: 12.5px;
  color: var(--c-muted);
}
.crate__stars { display: inline-flex; gap: 1.5px; font-size: 12px; line-height: 1; }
.crate__star { color: var(--c-line); }
.crate__star.is-on { color: var(--c-clay); }
.crate__txt { font-variant-numeric: tabular-nums; }

/* A half star, so a 4.8 does not light five. Drawn by clipping a second copy of
   the glyph over the empty one, which needs no extra asset. */
.crate__star.is-half { position: relative; color: var(--c-line); }
.crate__star.is-half::before {
  content: "\2605";
  position: absolute;
  left: 0;
  top: 0;
  width: 50%;
  overflow: hidden;
  color: var(--c-clay);
}

/* Desktop drag on the gallery stage. The cursor is the only affordance a mouse
   user gets, so it has to say "this moves" before they try. */
@media (hover: hover) and (min-width: 1000px) {
  .cgal__track { cursor: grab; touch-action: pan-y; }
  .cgal__track.is-dragging { cursor: grabbing; }
  /* Dragging an image is the browser's default and fights the gesture. */
  .cgal__track img { user-select: none; -webkit-user-drag: none; }
}

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

/* ═══ Customer clips in the buy column ════════════════════════════════════════
   Vertical clips on a snap rail. Sized so three sit across the buy column at
   desktop and two and a bit at 390px — enough of the third showing that the row
   reads as scrollable without needing an arrow. */
.cugin {
  margin: 22px 0 0;
  padding-top: 20px;
  border-top: 1px solid var(--c-hair);
}

.cugin__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.cugin__h {
  margin: 0;
  font-size: 10px;
  letter-spacing: var(--c-eyebrow, 0.2em);
  text-transform: uppercase;
  color: var(--c-soft);
}

.cugin__cta {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--c-clay);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding-bottom: 1px;
  white-space: nowrap;
}

.cugin__rail {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding-bottom: 2px;
}
.cugin__rail::-webkit-scrollbar { display: none; }

.cugin__i {
  position: relative;
  flex: 0 0 38%;
  max-width: 150px;
  scroll-snap-align: start;
  aspect-ratio: 9 / 16;
  border-radius: 6px;
  overflow: hidden;
  background: var(--c-surface);
  box-shadow: inset 0 0 0 1px rgb(var(--t-ink-rgb) / 0.07);
}
.cugin__i video,
.cugin__i img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Shopify wraps video media in its own element. */
.cugin__i > *:not(.cugin__sound):not(.cugin__c) { position: absolute; inset: 0; width: 100%; height: 100%; }

/* The sound button IS the clip: the whole tile is the target, and the icon in
   the corner only says what pressing it will do. */
.cugin__sound {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  display: block;
}
.cugin__ic {
  position: absolute;
  right: 6px;
  bottom: 6px;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: rgb(var(--t-ink-rgb) / 0.55);
  backdrop-filter: blur(4px);
  color: var(--c-white, var(--t-page));
}
.cugin__ic svg { width: 14px; height: 14px; }
.cugin__ic--on { display: none; }
.cugin__sound[aria-pressed="true"] .cugin__ic--off { display: none; }
.cugin__sound[aria-pressed="true"] .cugin__ic--on { display: grid; }

.cugin__c {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  padding: 22px 8px 7px;
  font-size: 11px;
  line-height: 1.35;
  color: var(--c-white, var(--t-page));
  background: linear-gradient(to top, rgb(var(--t-ink-rgb) / 0.6), transparent);
  pointer-events: none;
}

@media (min-width: 1000px) {
  .cugin__i { flex-basis: 31%; }
}

/* The offer strip stacks once it holds a gate.

   Icon, copy and a code button fit on one line; icon, copy and an email field
   with a submit do not - at 390px that left the scratch panel 149px wide, which
   is too small a target to scratch with a thumb. The gate takes its own full
   width underneath. */
.coffer:has(.cgate) {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 8px 10px;
  align-items: start;
}
.coffer:has(.cgate) .cgate {
  grid-column: 1 / -1;
  margin-top: 4px;
}

/* ═══ A3: badge, and the tax note beside the price ════════════════════════════ */

/* The badge was small-caps text laid straight on the photograph in --c-soft,
   which is a muted grey: over a light image it barely read, over a dark one it
   disappeared. It was also `display: none` from 1000px, so the one breakpoint
   with room for it did not show it.

   Now a filled pill, so it carries its own contrast whatever is behind it, and
   present at both sizes. */
.cgal__badge.cgal__badge {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 3;
  display: inline-block;
  padding: 5px 11px;
  border-radius: 999px;
  background: var(--c-fg);
  color: var(--c-white, var(--t-white));
  font-size: 9px;
  letter-spacing: 0.16em;
  line-height: 1.4;
  text-transform: uppercase;
}

@media (min-width: 1000px) {
  /* Beats the earlier `.cgal__count,.cgal__badge{display:none}` in this file. */
  .cgal__badge.cgal__badge { display: inline-block; top: 18px; left: 18px; }
}

/* Tax note. Sits on the price line, after the compare-at, deliberately quieter
   than both - it is a qualifier on the number, not a second number. */
.cinfo__tax {
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--c-soft);
  align-self: baseline;
}

/* ═══ Offer pill ════════════════════════════════════════════════════════════
   One line under the price, where a full panel used to sit below the
   add-to-cart. Quiet ground, not a banner and not a card — it should read as
   an aside next to the price, not compete with it. */
.cpill {
  margin: -8px 0 20px;
  border: 1px solid var(--c-line);
  border-radius: 999px;
  background: var(--c-surface);
}

.cpill__row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 0 6px 0 16px;
}

.cpill__t {
  flex: 1;
  min-width: 0;
  font-size: var(--t-b3, 13px);
  line-height: 1.35;
  color: var(--c-muted);
}

/* The code, inset. Its own ground so it reads as a thing to take, not a word
   in a sentence. */
.cpill__code {
  position: relative;
  flex: none;
  border: 1px dashed var(--c-line);
  border-radius: 999px;
  background: var(--c-bg);
  padding: 5px 12px;
  font-family: var(--c-sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  color: var(--c-fg);
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.cpill__code:hover { border-style: solid; border-color: var(--c-fg); }

/* "Copied" replaces the code in place, so the control never changes width and
   the row does not reflow when it is pressed. */
.cpill__copied {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: var(--c-fg);
  color: var(--c-bg);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s var(--c-ease, ease);
}
.cpill__code.is-copied .cpill__copied { opacity: 1; }

.cpill__more {
  flex: none;
  border: 0;
  background: none;
  padding: 6px 4px;
  font-family: var(--c-sans);
  font-size: 12px;
  color: var(--c-fg);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.cpill__x {
  flex: none;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border: 0;
  background: none;
  color: var(--c-soft);
  cursor: pointer;
}
.cpill__x svg { width: 13px; height: 13px; }
.cpill__x:hover { color: var(--c-fg); }
/* The 44px target comes from the row, not the glyph. */
/* The dismiss button's tap target must resolve against the BUTTON.

   It was `position: static` with an `inset: 0` pseudo-element, so the
   pseudo-element's containing block was the nearest positioned ancestor —
   .cpill__row — and the invisible target stretched across the entire offer
   bar. Every click anywhere in that row, including on "Get the code", was
   landing on dismiss. The button is positioned now, so inset: 0 means the
   button's own box, which is what it was always meant to mean. */
.cpill__row { position: relative; }
.cpill__x { position: relative; }
/* Negative inset: the mark stays 32px, the target is 44px. inset: 0 was
   correct once the button became positioned, but correct is not the same as
   large enough — it handed back a 32px target on a phone. */
.cpill__x::after { content: ""; position: absolute; inset: -6px; }

.cpill__fold {
  padding: 4px 16px 14px;
  border-top: 1px solid var(--c-hair);
  margin-top: 2px;
}
.cpill__fold[hidden] { display: none; }

/* Expanded, the pill stops being a pill — a rounded capsule around a form
   field reads as a mistake. */
.cpill.is-open { border-radius: var(--c-r, 2px); }

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

/* ═══════════════════════════════════════════════════════════════════════════
   PDP TOP — rebuilt left column and the run down the buy column.
   Appended last on purpose: everything here either retunes a rule declared
   earlier in this same file or adds one that has to win at equal specificity,
   so cascade position is the mechanism rather than an accident.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Left column ────────────────────────────────────────────────────────────
   One square stage and three square thumbs. Both hold their height with
   aspect-ratio rather than a padding hack, so an empty slot occupies exactly
   the space its photograph will take and filling it moves nothing. */
.cpgal { padding-inline: 20px; }
.cpgal__bread { padding: 0; margin: 0 0 14px; }

.cpgal__main {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--t-card);
  border-radius: var(--c-r, 2px);
  overflow: hidden;
  display: grid;
  place-items: center;
}
.cpgal__img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* The empty slot states what belongs in it. Quiet enough to read as
   scaffolding in the editor, not as a design element on the storefront. */
.cpgal__empty {
  font-family: var(--c-sans);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--t-neutral);
  text-align: center;
  padding-inline: 12px;
}
.cpgal__empty--sm { font-size: 8.5px; letter-spacing: 0.1em; }

.cpgal__flag {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 2;
  background: var(--t-ink);
  color: var(--t-page);
  font-family: var(--c-sans);
  font-size: 9.5px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 7px 13px;
  border-radius: 999px;
  /* The tracking is trailing space on the last letter; without the matching
     lead the word sits visibly left inside its pill. */
  text-indent: 0.18em;
}

.cpgal__thumbs {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}
.cpgal__thumb {
  position: relative;
  margin: 0;
  aspect-ratio: 1 / 1;
  background: var(--t-card);
  border-radius: var(--c-r, 2px);
  overflow: hidden;
  display: grid;
  place-items: center;
}

/* Width control. On mobile the page gutter is the only width there is to give
   back, so the three settings trade it away by degrees; the breadcrumb and the
   thumb row keep their gutter at every setting, because a full-bleed
   photograph is a deliberate effect and a full-bleed breadcrumb is a mistake. */
.cpgal--wide { padding-inline: 8px; }
.cpgal--wide .cpgal__bread { padding-inline: 12px; }
.cpgal--full { padding-inline: 0; }
.cpgal--full .cpgal__main { border-radius: 0; }
.cpgal--full .cpgal__bread,
.cpgal--full .cpgal__thumbs { padding-inline: 20px; }

@media (min-width: 990px) {
  /* THE GRID ITEM ITSELF STICKS, and it is short.

     align-self: start, so it is only as tall as the gallery instead of being
     stretched to the row. That matters because a sticky grid item takes the
     GRID CONTAINER's content box as its constraint rectangle, not its own
     height — so a short item still travels the whole row. Stretching it and
     sticking an inner wrapper also travelled, but the sticky offset then
     applied to a box whose top edge was not the column's top edge, and the
     difference showed as empty space above the gallery.

     The offset is the measured header height published by calmy-headerh.js,
     not the --c-head-h token. That token is a guess: 56px, 80px from 1150px
     up, and it knows nothing about the announcement bar, a wrapped nav or a
     font swapping in. Sticking to a guessed height is what put the gap there.
     The fallback only applies for the frame before the script runs. */
  .cpgal {
    align-self: start;
    position: sticky;
    /* Exactly the header height, with nothing added.

       Any positive offset here IS the gap. The product section starts flush
       under the header, so the column's natural top already sits at the header
       edge — and sticky clamps an element down to its top offset whenever the
       natural position is above it, at rest as much as mid-scroll. The
       previous "+ 16px" therefore pushed the gallery 15px below the buy column
       on a page that had not been scrolled at all. Breathing room, if it is
       ever wanted, belongs in the section's padding where it moves both
       columns together. */
    top: var(--calmy-header-h, 80px);
    padding-inline: 0;
  }
  .cpgal--wide { margin-inline: -24px; }
  .cpgal--full { margin-inline: -40px; }
  /* Below 990px the column is static: a sticky gallery on a phone would pin
     the picture over the buy column, which is the thing being scrolled to. */
  .cpgal--full .cpgal__bread,
  .cpgal--full .cpgal__thumbs { padding-inline: 40px; }
  .cpgal--wide .cpgal__bread { padding-inline: 24px; }
  .cpgal__thumbs { gap: 12px; margin-top: 12px; }
}

/* ── Buy column ─────────────────────────────────────────────────────────── */

/* The offer bar now opens the column, so it carries the space above the H1
   rather than sitting in the middle of the run. */
.cinfo__card > .cpill { margin: 0 0 18px; }

.cinfo__title {
  font-size: clamp(32px, 9vw, 40px);
  line-height: 1.02;
  letter-spacing: -0.03em;
  margin: 0 0 8px;
}

/* One line, in the display serif and italic — it is a caption on the name,
   not body copy, and setting it in the body face made it read as the start
   of the description. */
.cinfo__tagline {
  font-family: var(--c-serif, Georgia, serif);
  font-style: italic;
  font-size: 16px;
  line-height: 1.45;
  color: var(--t-neutral);
  margin: 0 0 14px;
  max-width: 40ch;
}

/* The stars stay unmarked; only the figure beside them is underlined, so the
   link reads as a link without turning the whole row into one. */
.cinfo__ratinglink { margin: 0 0 16px; }
.cinfo__ratinglink .crate__txt {
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
.cinfo__ratinglink:hover { opacity: 1; }
.cinfo__ratinglink:hover .crate__txt { color: var(--t-accent); }

/* Price row. The current figure is the display serif at a size that carries
   the row; the compare-at sits before it, struck and quiet. */
.cinfo__price { gap: 12px; flex-wrap: wrap; margin: 0 0 18px; }
.cinfo__now {
  font-family: var(--c-serif, Georgia, serif);
  font-size: 30px;
  line-height: 1;
  letter-spacing: -0.02em;
}
.cinfo__price del {
  font-family: var(--c-serif, Georgia, serif);
  font-size: 19px;
}
/* Was `.cinfo__price--sale > span:first-child`, which stopped matching the
   moment the struck-through figure was moved in front of the price — the
   sale colour would have silently landed on the <del> instead. Named, so
   the order of the row and the colour of the number are independent. */
.cinfo__price--sale .cinfo__now { color: var(--t-accent); }

.cinfo__sale {
  align-self: center;
  background: var(--t-accent);
  color: var(--t-page);
  font-family: var(--c-sans);
  font-size: 9.5px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 5px 11px;
  border-radius: 999px;
  text-indent: 0.16em;
}
.cinfo__tax { font-size: 11.5px; color: var(--t-neutral); align-self: center; }

/* The one divider in the column. */
.cinfo__rule {
  height: 1px;
  border: 0;
  /* --c-hair, not --c-line, was invisible here: it resolves to --t-card, which
     is exactly the ground this panel is painted in, so the divider was drawing
     itself in its own background colour. --c-line is the theme's hairline. */
  background: var(--c-line);
  margin: 0 0 18px;
}

/* Quote held to three lines. A review that runs to a paragraph pushes the
   variant pickers off the first screen, and the carousel is a taste of the
   reviews rather than the reviews themselves. */
.crevin .crevin__q {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Circular filled ticks. The shared check icon is a bare stroke path, so the
   disc is drawn by the list item and the path sits inside it. */
.cben3 { border: 0; padding: 0; margin: 0 0 24px; gap: 13px; }
.cben3 li { align-items: center; gap: 12px; }
.cben3 svg {
  width: 18px;
  height: 18px;
  margin: 0;
  padding: 4px;
  border-radius: 50%;
  background: var(--t-ink);
  stroke: var(--t-page);
  stroke-width: 2.4;
  box-sizing: border-box;
}

/* ── Tap targets on the two elements this rebuild put on screen ─────────────
   Neither was ever flagged before because neither was ever visible: the offer
   bar's "Get the code" button only renders once the block has a heading, and
   the rating row only renders now that its empty state is visible. Both are
   real controls on a 390px screen and both were under 44px. */
.cinfo__ratinglink {
  display: flex;
  align-items: center;
  min-height: 44px;
  /* The row grew by 24px, so the margin gives most of it back and the
     vertical rhythm of the column is left where it was. */
  margin: 0 0 4px;
}
.cpill__more {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* ═══ TIERS, LOW STOCK, PAYMENT — the run below the bullets ════════════════ */

/* The eyebrow's rules were drawn in --c-hair, which resolves to --t-card —
   the exact ground this panel is painted in, so both rules were invisible and
   the label looked like a stray centred line. Same fault as the divider. */
.ctiers__eyebrow span { background: var(--c-line); }

/* Selected tier takes the terracotta edge. The old rule painted the edge in
   --c-fg and added an inset ring, which read as "pressed" rather than
   "chosen" and was the same colour as every card's hover. */
.ctiers input:checked + .ctier {
  border-color: var(--t-accent);
  box-shadow: inset 0 0 0 1px var(--t-accent);
  background: transparent;
}
.ctier:hover { border-color: var(--t-accent-mut); }

/* A card with no variant behind it cannot be chosen, and says so quietly
   rather than looking broken. */
.ctier--unset { opacity: 0.55; cursor: not-allowed; }
.ctier__p--unset {
  font-family: var(--c-sans);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--t-neutral);
}

/* The badge overlaps the corner rather than sitting inside it, so it reads as
   applied to the card instead of as another line of card content. */
.ctier__flag {
  position: absolute;
  top: -9px;
  left: 12px;
  margin: 0;
  z-index: 2;
  background: var(--t-ink);
  color: var(--t-page);
  font-family: var(--c-sans);
  font-size: 8.5px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 5px 10px;
  border-radius: 999px;
  text-indent: 0.16em;
}

/* The card's square. Holds 1:1 whether a picture arrives or not. */
.ctier__m {
  width: 64px;
  height: 64px;
  aspect-ratio: 1 / 1;
  background: var(--t-card);
  border-radius: var(--c-r, 2px);
  overflow: hidden;
  display: grid;
  place-items: center;
}
.ctier__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ctier__empty {
  font-family: var(--c-sans);
  font-size: 7.5px;
  line-height: 1.35;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--t-neutral);
  text-align: center;
}

.ctier__n {
  font-family: var(--c-serif, Georgia, serif);
  font-size: 17px;
  line-height: 1.15;
  letter-spacing: -0.01em;
}
.ctier__note {
  display: block;
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--t-neutral);
  margin-top: 2px;
}

/* Low stock. The dot is the only red in the theme and it is deliberate: it is
   the one place a number is meant to feel like a countdown. It is decoration
   with the text beside it carrying the meaning, so it is aria-hidden. */
.clow {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: -8px 0 20px;
  font-size: 12.5px;
  color: var(--t-neutral);
}
.clow[hidden] { display: none; }
.clow__dot {
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 50%;
  background: #B3261E;
}

/* Payment marks as bordered pills rather than bare logos on the ground. */
.cpay__list { gap: 7px; }
.cpay__i {
  height: 30px;
  width: 46px;
  padding: 5px 7px;
  border: 1px solid var(--c-line);
  border-radius: 6px;
  background: var(--t-white);
  object-fit: contain;
  opacity: 1;
  box-sizing: border-box;
}

/* "0/20 characters · inside the band" as one line, with the dot supplied by
   the layout rather than typed into either string — so blanking the helper
   leaves "0/20 characters" and no orphaned separator. */
.ceng__foot { display: flex; align-items: baseline; gap: 5px; flex-wrap: wrap; }
.ceng__unit { color: inherit; }
.ceng__where::before { content: "·"; margin-right: 5px; }

/* ═══ BELOW THE PAYMENT ROW ════════════════════════════════════════════════ */

/* ── Trust: 2x2 bordered cards ──────────────────────────────────────────── */
.ctrust {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  list-style: none;
  margin: 22px 0 0;
  padding: 0;
}
.ctrust li {
  display: block;
  margin: 0;
  padding: 16px 14px;
  border: 1px solid var(--c-line);
  border-radius: var(--c-r, 2px);
  background: transparent;
}
/* The li carried decorative pseudo-elements from the old inline row. */
.ctrust li::before,
.ctrust li::after { display: none; }
.ctrust__h {
  display: block;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--t-ink);
  margin: 0 0 4px;
}
.ctrust__t {
  display: block;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--t-neutral);
}

/* ── Delivery box ───────────────────────────────────────────────────────── */
.cdel {
  margin: 20px 0 0;
  padding: 16px 14px 14px;
  border: 1px solid var(--c-line);
  border-radius: var(--c-r, 2px);
}
.cdel[hidden] { display: none; }
.cdel__lead {
  margin: 0 0 16px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--t-neutral);
}
/* The two facts the sentence exists to carry. */
.cdel__lead b,
.cdel__clock { color: var(--t-ink); font-weight: 600; }
.cdel__clock { font-variant-numeric: tabular-nums; }

.cdel__track {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0;
  list-style: none;
  margin: 0;
  padding: 0;
}
.cdel__step {
  position: relative;
  margin: 0;
  padding: 0 4px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
/* Dotted connector, drawn between steps rather than under them: it starts at
   the dot's centre and stops at the next one, so it never overhangs the row. */
.cdel__step + .cdel__step::before {
  content: "";
  position: absolute;
  top: 4px;
  right: 50%;
  left: -50%;
  height: 1px;
  background-image: linear-gradient(to right, var(--c-line) 0 3px, transparent 3px 6px);
  background-size: 6px 1px;
  background-repeat: repeat-x;
}
.cdel__dot {
  position: relative;
  z-index: 1;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--t-page);
  box-shadow: inset 0 0 0 1px var(--c-line);
}
/* Only the first stop has happened. */
.cdel__step.is-on .cdel__dot {
  background: var(--t-accent);
  box-shadow: inset 0 0 0 1px var(--t-accent);
}
.cdel__label {
  font-size: 8.5px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--t-ink);
}
.cdel__when { font-size: 10.5px; line-height: 1.35; color: var(--t-neutral); }

/* ── Accordions: + becomes x, not a minus ──────────────────────────────── */
/* The vertical bar used to scale to zero, leaving a minus. Rotating the whole
   mark 45 degrees keeps both bars and makes the close glyph an x, which is
   what the open state should read as. */
.cfold__ic { transition: transform 220ms var(--c-ease, ease); }
.cfold[open] .cfold__ic { transform: rotate(45deg); }
.cfold[open] .cfold__ic::after { transform: none; opacity: 1; }

/* ── Spec table ─────────────────────────────────────────────────────────── */
.cspec { margin: 14px 0 0; padding: 0; }
.cspec__r {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 9px 0;
  border-top: 1px solid var(--c-line);
}
.cspec__r:last-child { border-bottom: 1px solid var(--c-line); }
.cspec dt {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--t-neutral);
  margin: 0;
}
.cspec dd {
  margin: 0;
  font-size: 13px;
  color: var(--t-ink);
  text-align: right;
}

/* ── Care list ──────────────────────────────────────────────────────────────
   .cpcare, not .ccare — that name is already a whole section component in
   calmy-care.css (the care page), and reusing it meant the two clobbered each
   other in both directions: this heading was inheriting a 24px display size
   from there, and .ccare's full-bleed section padding was being applied to a
   list inside an accordion. */
.cpcare__h {
  margin: 18px 0 8px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--t-ink);
}
.cpcare { margin: 0; padding-left: 18px; list-style: disc; }
.cpcare li {
  margin: 0 0 6px;
  padding: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--t-neutral);
}
.cpcare li::marker { color: var(--t-accent-mut); }

@media (min-width: 1000px) {
  .ctrust { gap: 12px; }
  .cdel { padding: 18px 18px 16px; }
}

/* ============================================================================
   Deal cards, restyled — and the urgency line above Add to cart.
   Appended, so it overrides the earlier .ctier rules in this same sheet
   rather than editing them in place and losing their reasoning.
   ========================================================================= */

.ctiers { gap: 12px; }

.ctier {
  /* 18–22px, and 20 sits with the card radius used everywhere else. */
  border-radius: 20px;
  padding: 16px;
  gap: 14px;
  border-width: 1.5px;
}




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

/* ═══ Engraving ═══════════════════════════════════════════════════════════════
   A quiet panel inside the buy card, not a headline. */
.ceng {
  margin: 0 0 18px;
  padding: 13px 14px 12px;
  background: var(--c-white, var(--t-white));
  border: 1px solid var(--c-hair);
  border-radius: var(--c-r, 2px);
}

.ceng__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.ceng__label {
  font-size: 10px;
  letter-spacing: var(--c-eyebrow, 0.2em);
  text-transform: uppercase;
  color: var(--c-fg);
}
.ceng__free { font-size: 11.5px; color: var(--c-clay); }

.ceng__input {
  width: 100%;
  margin-top: 10px;
  padding: 11px 12px;
  border: 1px solid var(--c-hair);
  border-radius: var(--c-r, 2px);
  background: var(--c-surface);
  /* The serif, because what goes in here is what gets engraved. */
  font-family: var(--c-serif);
  font-size: max(16px, 1em);
  color: var(--c-fg);
  outline: none;
  transition: border-color 0.25s var(--c-ease);
}
.ceng__input::placeholder { font-family: var(--c-sans); font-size: 14px; color: var(--c-soft); }
.ceng__input:focus { border-color: var(--c-fg); }

.ceng__foot {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin: 7px 0 0;
  font-size: 11.5px;
  color: var(--c-soft);
  font-variant-numeric: tabular-nums;
}
.ceng__where { font-variant-numeric: normal; }

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

/* ═══ Finish pills ════════════════════════════════════════════════════════════
   The name lives in the control. A bare dot makes you hover to learn what a
   finish is called, and on touch there is no hover to give. */
.cvar__pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 8px 14px 8px 8px;
  border: 1px solid var(--c-hair);
  border-radius: 999px;
  background: var(--c-white, var(--t-white));
  cursor: pointer;
  transition: border-color 0.25s var(--c-ease), background-color 0.25s var(--c-ease);
}
.cvar__pill:hover { border-color: var(--c-line); }

.cvar__opts input:checked + .cvar__pill {
  border-color: var(--c-fg);
  background: var(--c-fg);
}
.cvar__opts input:checked + .cvar__pill .cvar__pilltxt { color: var(--c-white, var(--t-white)); }
.cvar__opts input:focus-visible + .cvar__pill { outline: 2px solid var(--c-clay); outline-offset: 2px; }
.cvar__opts input:disabled + .cvar__pill { opacity: 0.4; cursor: not-allowed; }

.cvar__dot {
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: 999px;
  overflow: hidden;
  display: block;
  background-size: cover;
  background-position: center;
  box-shadow: inset 0 0 0 1px rgb(var(--t-ink-rgb) / 0.12);
}
.cvar__dot img { width: 100%; height: 100%; object-fit: cover; display: block; }

.cvar__pilltxt {
  font-size: 13.5px;
  line-height: 1;
  color: var(--c-fg);
  white-space: nowrap;
  transition: color 0.25s var(--c-ease);
}

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

/* ═══ Inline reviews ══════════════════════════════════════════════════════════
   Prefix is crevin, not crev: the standalone reviews section already owns .crev
   and both appear on the product template. Reusing it meant the section's large
   serif pull-quote styling landing on this small in-column note.
   A single quote at a time with arrows either side, sitting on hairlines rather
   than in a box - it is a note inside the buy column, not another panel. */
.crevin {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 6px;
  margin: 0 0 18px;
  padding: 14px 0;
  border-top: 1px solid var(--c-hair);
  border-bottom: 1px solid var(--c-hair);
}

.crevin__go {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--c-soft);
  cursor: pointer;
  transition: color 0.2s var(--c-ease);
}
.crevin__go:hover { color: var(--c-fg); }
.crevin__go svg { width: 15px; height: 15px; }

.crevin__track { min-width: 0; }
.crevin__i[hidden] { display: none; }
.crevin__i { margin: 0; }

.crevin__head { display: flex; align-items: center; gap: 10px; }

/* Initials by default: a photograph of a customer needs their permission, two
   letters need nobody's. */
.crevin__av {
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 999px;
  overflow: hidden;
  display: grid;
  place-items: center;
  background: var(--c-surface);
  color: var(--c-muted);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  box-shadow: inset 0 0 0 1px rgb(var(--t-ink-rgb) / 0.08);
}
.crevin__av img { width: 100%; height: 100%; object-fit: cover; display: block; }

.crevin__who { min-width: 0; }
.crevin__name {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 13px;
  color: var(--c-fg);
}
.crevin__tick { display: inline-flex; width: 13px; height: 13px; color: var(--c-clay); }
.crevin__tick svg { width: 100%; height: 100%; }

.crevin__stars { display: inline-flex; gap: 1px; font-size: 11px; line-height: 1; margin-top: 2px; }
.crevin__star { color: var(--c-line); }
.crevin__star.is-on { color: var(--c-clay); }

/* Doubled-up class: Horizon styles bare <blockquote> as a display pull-quote -
   centred Playfair at around 24px - from a stylesheet that lands later, and at
   equal specificity that one wins. This is a note in a buy column, not a pull
   quote. */
.crevin .crevin__q {
  margin: 8px 0 0;
  padding: 0;
  border: 0;
  text-align: left;
  font-family: var(--c-sans);
  font-style: normal;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--c-muted);
  /* Two lines, so the buy column does not jump as reviews cycle. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

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

/* ═══ Delivery track ══════════════════════════════════════════════════════════
   Hidden until the script has produced real dates, so no half-written promise
   is ever on screen. */
.cdel {
  margin: 18px 0 0;
  padding: 14px 14px 16px;
  background: var(--c-white, var(--t-white));
  border: 1px solid var(--c-hair);
  border-radius: var(--c-r, 2px);
}
.cdel[hidden] { display: none; }

.cdel__lead {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--c-muted);
  text-wrap: pretty;
}
.cdel__lead b { font-weight: 400; color: var(--c-fg); }
.cdel__lead .cdel__clock {
  color: var(--c-clay);
  /* Tabular figures hold the seconds still without reserving a fixed width -
     a min-width sized for the longest possible countdown left a visible gap
     after it for most of the day. The one reflow is 9h to 10h, once. */
  font-variant-numeric: tabular-nums;
}

.cdel__track {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
}

.cdel__step {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 7px;
}

/* The connector is drawn from each step back to the previous one, so it can
   never overhang the ends of the track. */
.cdel__step + .cdel__step::before {
  content: "";
  position: absolute;
  right: 50%;
  top: 5px;
  width: 100%;
  border-top: 1px dashed var(--c-line);
}

.cdel__dot {
  position: relative;
  z-index: 1;
  width: 11px;
  height: 11px;
  border-radius: 999px;
  border: 1.5px solid var(--c-line);
  background: var(--c-white, var(--t-white));
}
.cdel__step.is-on .cdel__dot { border-color: var(--c-clay); background: var(--c-clay); }

.cdel__label {
  font-size: 9.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--c-fg);
}
.cdel__when {
  font-size: 11px;
  line-height: 1.35;
  color: var(--c-soft);
  min-height: 1.35em;
}

/* The discount code is a button that copies itself. Its label is the code, so
   a blocked clipboard costs the visitor nothing. */
.coffer__code {
  border: 1px dashed var(--c-clay);
  border-radius: 999px;
  background: transparent;
  color: var(--c-clay);
  font: inherit;
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 6px 12px;
  min-height: 32px;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.2s var(--c-ease), color 0.2s var(--c-ease), border-style 0.2s var(--c-ease);
}
.coffer__code:hover { background: var(--c-clay); color: var(--c-white, var(--t-white)); }
.coffer__code.is-copied { border-style: solid; background: var(--c-clay); color: var(--c-white, var(--t-white)); }
/* Grows the target to 44px without moving the pill. */
.coffer__code { position: relative; }
.coffer__code::after { content: ''; position: absolute; inset: -6px -4px; }

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

/* Star rating row under the subtitle. Renders only from figures a merchant can
   evidence, or from a connected provider - never from nothing. */
.crate {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 12px;
  font-size: 12.5px;
  color: var(--c-muted);
}
.crate__stars { display: inline-flex; gap: 1.5px; font-size: 12px; line-height: 1; }
.crate__star { color: var(--c-line); }
.crate__star.is-on { color: var(--c-clay); }
.crate__txt { font-variant-numeric: tabular-nums; }

/* A half star, so a 4.8 does not light five. Drawn by clipping a second copy of
   the glyph over the empty one, which needs no extra asset. */
.crate__star.is-half { position: relative; color: var(--c-line); }
.crate__star.is-half::before {
  content: "\2605";
  position: absolute;
  left: 0;
  top: 0;
  width: 50%;
  overflow: hidden;
  color: var(--c-clay);
}

/* Desktop drag on the gallery stage. The cursor is the only affordance a mouse
   user gets, so it has to say "this moves" before they try. */
@media (hover: hover) and (min-width: 1000px) {
  .cgal__track { cursor: grab; touch-action: pan-y; }
  .cgal__track.is-dragging { cursor: grabbing; }
  /* Dragging an image is the browser's default and fights the gesture. */
  .cgal__track img { user-select: none; -webkit-user-drag: none; }
}

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

/* ═══ Customer clips in the buy column ════════════════════════════════════════
   Vertical clips on a snap rail. Sized so three sit across the buy column at
   desktop and two and a bit at 390px — enough of the third showing that the row
   reads as scrollable without needing an arrow. */
.cugin {
  margin: 22px 0 0;
  padding-top: 20px;
  border-top: 1px solid var(--c-hair);
}

.cugin__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.cugin__h {
  margin: 0;
  font-size: 10px;
  letter-spacing: var(--c-eyebrow, 0.2em);
  text-transform: uppercase;
  color: var(--c-soft);
}

.cugin__cta {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--c-clay);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding-bottom: 1px;
  white-space: nowrap;
}

.cugin__rail {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding-bottom: 2px;
}
.cugin__rail::-webkit-scrollbar { display: none; }

.cugin__i {
  position: relative;
  flex: 0 0 38%;
  max-width: 150px;
  scroll-snap-align: start;
  aspect-ratio: 9 / 16;
  border-radius: 6px;
  overflow: hidden;
  background: var(--c-surface);
  box-shadow: inset 0 0 0 1px rgb(var(--t-ink-rgb) / 0.07);
}
.cugin__i video,
.cugin__i img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Shopify wraps video media in its own element. */
.cugin__i > *:not(.cugin__sound):not(.cugin__c) { position: absolute; inset: 0; width: 100%; height: 100%; }

/* The sound button IS the clip: the whole tile is the target, and the icon in
   the corner only says what pressing it will do. */
.cugin__sound {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  display: block;
}
.cugin__ic {
  position: absolute;
  right: 6px;
  bottom: 6px;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: rgb(var(--t-ink-rgb) / 0.55);
  backdrop-filter: blur(4px);
  color: var(--c-white, var(--t-page));
}
.cugin__ic svg { width: 14px; height: 14px; }
.cugin__ic--on { display: none; }
.cugin__sound[aria-pressed="true"] .cugin__ic--off { display: none; }
.cugin__sound[aria-pressed="true"] .cugin__ic--on { display: grid; }

.cugin__c {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  padding: 22px 8px 7px;
  font-size: 11px;
  line-height: 1.35;
  color: var(--c-white, var(--t-page));
  background: linear-gradient(to top, rgb(var(--t-ink-rgb) / 0.6), transparent);
  pointer-events: none;
}

@media (min-width: 1000px) {
  .cugin__i { flex-basis: 31%; }
}

/* The offer strip stacks once it holds a gate.

   Icon, copy and a code button fit on one line; icon, copy and an email field
   with a submit do not - at 390px that left the scratch panel 149px wide, which
   is too small a target to scratch with a thumb. The gate takes its own full
   width underneath. */
.coffer:has(.cgate) {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 8px 10px;
  align-items: start;
}
.coffer:has(.cgate) .cgate {
  grid-column: 1 / -1;
  margin-top: 4px;
}

/* ═══ A3: badge, and the tax note beside the price ════════════════════════════ */

/* The badge was small-caps text laid straight on the photograph in --c-soft,
   which is a muted grey: over a light image it barely read, over a dark one it
   disappeared. It was also `display: none` from 1000px, so the one breakpoint
   with room for it did not show it.

   Now a filled pill, so it carries its own contrast whatever is behind it, and
   present at both sizes. */
.cgal__badge.cgal__badge {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 3;
  display: inline-block;
  padding: 5px 11px;
  border-radius: 999px;
  background: var(--c-fg);
  color: var(--c-white, var(--t-white));
  font-size: 9px;
  letter-spacing: 0.16em;
  line-height: 1.4;
  text-transform: uppercase;
}

@media (min-width: 1000px) {
  /* Beats the earlier `.cgal__count,.cgal__badge{display:none}` in this file. */
  .cgal__badge.cgal__badge { display: inline-block; top: 18px; left: 18px; }
}

/* Tax note. Sits on the price line, after the compare-at, deliberately quieter
   than both - it is a qualifier on the number, not a second number. */
.cinfo__tax {
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--c-soft);
  align-self: baseline;
}

/* ═══ Offer pill ════════════════════════════════════════════════════════════
   One line under the price, where a full panel used to sit below the
   add-to-cart. Quiet ground, not a banner and not a card — it should read as
   an aside next to the price, not compete with it. */
.cpill {
  margin: -8px 0 20px;
  border: 1px solid var(--c-line);
  border-radius: 999px;
  background: var(--c-surface);
}

.cpill__row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 0 6px 0 16px;
}

.cpill__t {
  flex: 1;
  min-width: 0;
  font-size: var(--t-b3, 13px);
  line-height: 1.35;
  color: var(--c-muted);
}

/* The code, inset. Its own ground so it reads as a thing to take, not a word
   in a sentence. */
.cpill__code {
  position: relative;
  flex: none;
  border: 1px dashed var(--c-line);
  border-radius: 999px;
  background: var(--c-bg);
  padding: 5px 12px;
  font-family: var(--c-sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  color: var(--c-fg);
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.cpill__code:hover { border-style: solid; border-color: var(--c-fg); }

/* "Copied" replaces the code in place, so the control never changes width and
   the row does not reflow when it is pressed. */
.cpill__copied {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: var(--c-fg);
  color: var(--c-bg);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s var(--c-ease, ease);
}
.cpill__code.is-copied .cpill__copied { opacity: 1; }

.cpill__more {
  flex: none;
  border: 0;
  background: none;
  padding: 6px 4px;
  font-family: var(--c-sans);
  font-size: 12px;
  color: var(--c-fg);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.cpill__x {
  flex: none;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border: 0;
  background: none;
  color: var(--c-soft);
  cursor: pointer;
}
.cpill__x svg { width: 13px; height: 13px; }
.cpill__x:hover { color: var(--c-fg); }
/* The 44px target comes from the row, not the glyph. */
/* The dismiss button's tap target must resolve against the BUTTON.

   It was `position: static` with an `inset: 0` pseudo-element, so the
   pseudo-element's containing block was the nearest positioned ancestor —
   .cpill__row — and the invisible target stretched across the entire offer
   bar. Every click anywhere in that row, including on "Get the code", was
   landing on dismiss. The button is positioned now, so inset: 0 means the
   button's own box, which is what it was always meant to mean. */
.cpill__row { position: relative; }
.cpill__x { position: relative; }
/* Negative inset: the mark stays 32px, the target is 44px. inset: 0 was
   correct once the button became positioned, but correct is not the same as
   large enough — it handed back a 32px target on a phone. */
.cpill__x::after { content: ""; position: absolute; inset: -6px; }

.cpill__fold {
  padding: 4px 16px 14px;
  border-top: 1px solid var(--c-hair);
  margin-top: 2px;
}
.cpill__fold[hidden] { display: none; }

/* Expanded, the pill stops being a pill — a rounded capsule around a form
   field reads as a mistake. */
.cpill.is-open { border-radius: var(--c-r, 2px); }

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

/* ═══════════════════════════════════════════════════════════════════════════
   PDP TOP — rebuilt left column and the run down the buy column.
   Appended last on purpose: everything here either retunes a rule declared
   earlier in this same file or adds one that has to win at equal specificity,
   so cascade position is the mechanism rather than an accident.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Left column ────────────────────────────────────────────────────────────
   One square stage and three square thumbs. Both hold their height with
   aspect-ratio rather than a padding hack, so an empty slot occupies exactly
   the space its photograph will take and filling it moves nothing. */
.cpgal { padding-inline: 20px; }
.cpgal__bread { padding: 0; margin: 0 0 14px; }

.cpgal__main {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--t-card);
  border-radius: var(--c-r, 2px);
  overflow: hidden;
  display: grid;
  place-items: center;
}
.cpgal__img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* The empty slot states what belongs in it. Quiet enough to read as
   scaffolding in the editor, not as a design element on the storefront. */
.cpgal__empty {
  font-family: var(--c-sans);
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--t-neutral);
  text-align: center;
  padding-inline: 12px;
}
.cpgal__empty--sm { font-size: 8.5px; letter-spacing: 0.1em; }

.cpgal__flag {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 2;
  background: var(--t-ink);
  color: var(--t-page);
  font-family: var(--c-sans);
  font-size: 9.5px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 7px 13px;
  border-radius: 999px;
  /* The tracking is trailing space on the last letter; without the matching
     lead the word sits visibly left inside its pill. */
  text-indent: 0.18em;
}

.cpgal__thumbs {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}
.cpgal__thumb {
  position: relative;
  margin: 0;
  aspect-ratio: 1 / 1;
  background: var(--t-card);
  border-radius: var(--c-r, 2px);
  overflow: hidden;
  display: grid;
  place-items: center;
}

/* Width control. On mobile the page gutter is the only width there is to give
   back, so the three settings trade it away by degrees; the breadcrumb and the
   thumb row keep their gutter at every setting, because a full-bleed
   photograph is a deliberate effect and a full-bleed breadcrumb is a mistake. */
.cpgal--wide { padding-inline: 8px; }
.cpgal--wide .cpgal__bread { padding-inline: 12px; }
.cpgal--full { padding-inline: 0; }
.cpgal--full .cpgal__main { border-radius: 0; }
.cpgal--full .cpgal__bread,
.cpgal--full .cpgal__thumbs { padding-inline: 20px; }

@media (min-width: 990px) {
  /* THE GRID ITEM ITSELF STICKS, and it is short.

     align-self: start, so it is only as tall as the gallery instead of being
     stretched to the row. That matters because a sticky grid item takes the
     GRID CONTAINER's content box as its constraint rectangle, not its own
     height — so a short item still travels the whole row. Stretching it and
     sticking an inner wrapper also travelled, but the sticky offset then
     applied to a box whose top edge was not the column's top edge, and the
     difference showed as empty space above the gallery.

     The offset is the measured header height published by calmy-headerh.js,
     not the --c-head-h token. That token is a guess: 56px, 80px from 1150px
     up, and it knows nothing about the announcement bar, a wrapped nav or a
     font swapping in. Sticking to a guessed height is what put the gap there.
     The fallback only applies for the frame before the script runs. */
  .cpgal {
    align-self: start;
    position: sticky;
    /* Exactly the header height, with nothing added.

       Any positive offset here IS the gap. The product section starts flush
       under the header, so the column's natural top already sits at the header
       edge — and sticky clamps an element down to its top offset whenever the
       natural position is above it, at rest as much as mid-scroll. The
       previous "+ 16px" therefore pushed the gallery 15px below the buy column
       on a page that had not been scrolled at all. Breathing room, if it is
       ever wanted, belongs in the section's padding where it moves both
       columns together. */
    top: var(--calmy-header-h, 80px);
    padding-inline: 0;
  }
  .cpgal--wide { margin-inline: -24px; }
  .cpgal--full { margin-inline: -40px; }
  /* Below 990px the column is static: a sticky gallery on a phone would pin
     the picture over the buy column, which is the thing being scrolled to. */
  .cpgal--full .cpgal__bread,
  .cpgal--full .cpgal__thumbs { padding-inline: 40px; }
  .cpgal--wide .cpgal__bread { padding-inline: 24px; }
  .cpgal__thumbs { gap: 12px; margin-top: 12px; }
}

/* ── Buy column ─────────────────────────────────────────────────────────── */

/* The offer bar now opens the column, so it carries the space above the H1
   rather than sitting in the middle of the run. */
.cinfo__card > .cpill { margin: 0 0 18px; }

.cinfo__title {
  font-size: clamp(32px, 9vw, 40px);
  line-height: 1.02;
  letter-spacing: -0.03em;
  margin: 0 0 8px;
}

/* One line, in the display serif and italic — it is a caption on the name,
   not body copy, and setting it in the body face made it read as the start
   of the description. */
.cinfo__tagline {
  font-family: var(--c-serif, Georgia, serif);
  font-style: italic;
  font-size: 16px;
  line-height: 1.45;
  color: var(--t-neutral);
  margin: 0 0 14px;
  max-width: 40ch;
}

/* The stars stay unmarked; only the figure beside them is underlined, so the
   link reads as a link without turning the whole row into one. */
.cinfo__ratinglink { margin: 0 0 16px; }
.cinfo__ratinglink .crate__txt {
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
.cinfo__ratinglink:hover { opacity: 1; }
.cinfo__ratinglink:hover .crate__txt { color: var(--t-accent); }

/* Price row. The current figure is the display serif at a size that carries
   the row; the compare-at sits before it, struck and quiet. */
.cinfo__price { gap: 12px; flex-wrap: wrap; margin: 0 0 18px; }
.cinfo__now {
  font-family: var(--c-serif, Georgia, serif);
  font-size: 30px;
  line-height: 1;
  letter-spacing: -0.02em;
}
.cinfo__price del {
  font-family: var(--c-serif, Georgia, serif);
  font-size: 19px;
}
/* Was `.cinfo__price--sale > span:first-child`, which stopped matching the
   moment the struck-through figure was moved in front of the price — the
   sale colour would have silently landed on the <del> instead. Named, so
   the order of the row and the colour of the number are independent. */
.cinfo__price--sale .cinfo__now { color: var(--t-accent); }

.cinfo__sale {
  align-self: center;
  background: var(--t-accent);
  color: var(--t-page);
  font-family: var(--c-sans);
  font-size: 9.5px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 5px 11px;
  border-radius: 999px;
  text-indent: 0.16em;
}
.cinfo__tax { font-size: 11.5px; color: var(--t-neutral); align-self: center; }

/* The one divider in the column. */
.cinfo__rule {
  height: 1px;
  border: 0;
  /* --c-hair, not --c-line, was invisible here: it resolves to --t-card, which
     is exactly the ground this panel is painted in, so the divider was drawing
     itself in its own background colour. --c-line is the theme's hairline. */
  background: var(--c-line);
  margin: 0 0 18px;
}

/* Quote held to three lines. A review that runs to a paragraph pushes the
   variant pickers off the first screen, and the carousel is a taste of the
   reviews rather than the reviews themselves. */
.crevin .crevin__q {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Circular filled ticks. The shared check icon is a bare stroke path, so the
   disc is drawn by the list item and the path sits inside it. */
.cben3 { border: 0; padding: 0; margin: 0 0 24px; gap: 13px; }
.cben3 li { align-items: center; gap: 12px; }
.cben3 svg {
  width: 18px;
  height: 18px;
  margin: 0;
  padding: 4px;
  border-radius: 50%;
  background: var(--t-ink);
  stroke: var(--t-page);
  stroke-width: 2.4;
  box-sizing: border-box;
}

/* ── Tap targets on the two elements this rebuild put on screen ─────────────
   Neither was ever flagged before because neither was ever visible: the offer
   bar's "Get the code" button only renders once the block has a heading, and
   the rating row only renders now that its empty state is visible. Both are
   real controls on a 390px screen and both were under 44px. */
.cinfo__ratinglink {
  display: flex;
  align-items: center;
  min-height: 44px;
  /* The row grew by 24px, so the margin gives most of it back and the
     vertical rhythm of the column is left where it was. */
  margin: 0 0 4px;
}
.cpill__more {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* ═══ TIERS, LOW STOCK, PAYMENT — the run below the bullets ════════════════ */

/* The eyebrow's rules were drawn in --c-hair, which resolves to --t-card —
   the exact ground this panel is painted in, so both rules were invisible and
   the label looked like a stray centred line. Same fault as the divider. */
.ctiers__eyebrow span { background: var(--c-line); }

/* Selected tier takes the terracotta edge. The old rule painted the edge in
   --c-fg and added an inset ring, which read as "pressed" rather than
   "chosen" and was the same colour as every card's hover. */
.ctiers input:checked + .ctier {
  border-color: var(--t-accent);
  box-shadow: inset 0 0 0 1px var(--t-accent);
  background: transparent;
}
.ctier:hover { border-color: var(--t-accent-mut); }

/* A card with no variant behind it cannot be chosen, and says so quietly
   rather than looking broken. */
.ctier--unset { opacity: 0.55; cursor: not-allowed; }
.ctier__p--unset {
  font-family: var(--c-sans);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--t-neutral);
}

/* The badge overlaps the corner rather than sitting inside it, so it reads as
   applied to the card instead of as another line of card content. */
.ctier__flag {
  position: absolute;
  top: -9px;
  left: 12px;
  margin: 0;
  z-index: 2;
  background: var(--t-ink);
  color: var(--t-page);
  font-family: var(--c-sans);
  font-size: 8.5px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 5px 10px;
  border-radius: 999px;
  text-indent: 0.16em;
}

/* The card's square. Holds 1:1 whether a picture arrives or not. */
.ctier__m {
  width: 64px;
  height: 64px;
  aspect-ratio: 1 / 1;
  background: var(--t-card);
  border-radius: var(--c-r, 2px);
  overflow: hidden;
  display: grid;
  place-items: center;
}
.ctier__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ctier__empty {
  font-family: var(--c-sans);
  font-size: 7.5px;
  line-height: 1.35;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--t-neutral);
  text-align: center;
}

.ctier__n {
  font-family: var(--c-serif, Georgia, serif);
  font-size: 17px;
  line-height: 1.15;
  letter-spacing: -0.01em;
}
.ctier__note {
  display: block;
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--t-neutral);
  margin-top: 2px;
}

/* Low stock. The dot is the only red in the theme and it is deliberate: it is
   the one place a number is meant to feel like a countdown. It is decoration
   with the text beside it carrying the meaning, so it is aria-hidden. */
.clow {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: -8px 0 20px;
  font-size: 12.5px;
  color: var(--t-neutral);
}
.clow[hidden] { display: none; }
.clow__dot {
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 50%;
  background: #B3261E;
}

/* Payment marks as bordered pills rather than bare logos on the ground. */
.cpay__list { gap: 7px; }
.cpay__i {
  height: 30px;
  width: 46px;
  padding: 5px 7px;
  border: 1px solid var(--c-line);
  border-radius: 6px;
  background: var(--t-white);
  object-fit: contain;
  opacity: 1;
  box-sizing: border-box;
}

/* "0/20 characters · inside the band" as one line, with the dot supplied by
   the layout rather than typed into either string — so blanking the helper
   leaves "0/20 characters" and no orphaned separator. */
.ceng__foot { display: flex; align-items: baseline; gap: 5px; flex-wrap: wrap; }
.ceng__unit { color: inherit; }
.ceng__where::before { content: "·"; margin-right: 5px; }

/* ═══ BELOW THE PAYMENT ROW ════════════════════════════════════════════════ */

/* ── Trust: 2x2 bordered cards ──────────────────────────────────────────── */
.ctrust {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  list-style: none;
  margin: 22px 0 0;
  padding: 0;
}
.ctrust li {
  display: block;
  margin: 0;
  padding: 16px 14px;
  border: 1px solid var(--c-line);
  border-radius: var(--c-r, 2px);
  background: transparent;
}
/* The li carried decorative pseudo-elements from the old inline row. */
.ctrust li::before,
.ctrust li::after { display: none; }
.ctrust__h {
  display: block;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--t-ink);
  margin: 0 0 4px;
}
.ctrust__t {
  display: block;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--t-neutral);
}

/* ── Delivery box ───────────────────────────────────────────────────────── */
.cdel {
  margin: 20px 0 0;
  padding: 16px 14px 14px;
  border: 1px solid var(--c-line);
  border-radius: var(--c-r, 2px);
}
.cdel[hidden] { display: none; }
.cdel__lead {
  margin: 0 0 16px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--t-neutral);
}
/* The two facts the sentence exists to carry. */
.cdel__lead b,
.cdel__clock { color: var(--t-ink); font-weight: 600; }
.cdel__clock { font-variant-numeric: tabular-nums; }

.cdel__track {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0;
  list-style: none;
  margin: 0;
  padding: 0;
}
.cdel__step {
  position: relative;
  margin: 0;
  padding: 0 4px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
/* Dotted connector, drawn between steps rather than under them: it starts at
   the dot's centre and stops at the next one, so it never overhangs the row. */
.cdel__step + .cdel__step::before {
  content: "";
  position: absolute;
  top: 4px;
  right: 50%;
  left: -50%;
  height: 1px;
  background-image: linear-gradient(to right, var(--c-line) 0 3px, transparent 3px 6px);
  background-size: 6px 1px;
  background-repeat: repeat-x;
}
.cdel__dot {
  position: relative;
  z-index: 1;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--t-page);
  box-shadow: inset 0 0 0 1px var(--c-line);
}
/* Only the first stop has happened. */
.cdel__step.is-on .cdel__dot {
  background: var(--t-accent);
  box-shadow: inset 0 0 0 1px var(--t-accent);
}
.cdel__label {
  font-size: 8.5px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--t-ink);
}
.cdel__when { font-size: 10.5px; line-height: 1.35; color: var(--t-neutral); }

/* ── Accordions: + becomes x, not a minus ──────────────────────────────── */
/* The vertical bar used to scale to zero, leaving a minus. Rotating the whole
   mark 45 degrees keeps both bars and makes the close glyph an x, which is
   what the open state should read as. */
.cfold__ic { transition: transform 220ms var(--c-ease, ease); }
.cfold[open] .cfold__ic { transform: rotate(45deg); }
.cfold[open] .cfold__ic::after { transform: none; opacity: 1; }

/* ── Spec table ─────────────────────────────────────────────────────────── */
.cspec { margin: 14px 0 0; padding: 0; }
.cspec__r {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 9px 0;
  border-top: 1px solid var(--c-line);
}
.cspec__r:last-child { border-bottom: 1px solid var(--c-line); }
.cspec dt {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--t-neutral);
  margin: 0;
}
.cspec dd {
  margin: 0;
  font-size: 13px;
  color: var(--t-ink);
  text-align: right;
}

/* ── Care list ──────────────────────────────────────────────────────────────
   .cpcare, not .ccare — that name is already a whole section component in
   calmy-care.css (the care page), and reusing it meant the two clobbered each
   other in both directions: this heading was inheriting a 24px display size
   from there, and .ccare's full-bleed section padding was being applied to a
   list inside an accordion. */
.cpcare__h {
  margin: 18px 0 8px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--t-ink);
}
.cpcare { margin: 0; padding-left: 18px; list-style: disc; }
.cpcare li {
  margin: 0 0 6px;
  padding: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--t-neutral);
}
.cpcare li::marker { color: var(--t-accent-mut); }

@media (min-width: 1000px) {
  .ctrust { gap: 12px; }
  .cdel { padding: 18px 18px 16px; }
}

/* ============================================================================
   Deal cards, restyled — and the urgency line above Add to cart.
   Appended, so it overrides the earlier .ctier rules in this same sheet
   rather than editing them in place and losing their reasoning.
   ========================================================================= */

.ctiers { gap: 12px; }

.ctier {
  /* 18–22px, and 20 sits with the card radius used everywhere else. */
  border-radius: 20px;
  padding: 16px;
  gap: 14px;
  border-width: 1.5px;
}

/* RESERVED SPACE FOR THE BADGE.

   The badge used to be an inline child with margin-left:auto, which put it on
   the same row as the price and made the two negotiate for width. It is now
   pinned to the top right corner, out of flow — and the reservation is made on
   EVERY card in the group, not only the badged ones, so all three keep the
   same internal geometry and the row of cards still lines up. :has() on the
   group is what lets one badge anywhere pay for the space everywhere. */
.ctier__flag {
  position: absolute;
  top: 10px;
  right: 12px;
  /* SHRINK TO THE WORDS. .ctier is a grid container, and an absolutely
     positioned child of one is still aligned by the grid: justify-self
     defaults to stretch, so the pill spanned the whole card and read as a
     banner rather than a badge. max-content pins it to its own text, and
     left:auto keeps it anchored to the right edge only. */
  left: auto;
  width: max-content;
  max-width: calc(100% - 24px);
  margin: 0;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--c-surface);
  box-shadow: inset 0 0 0 1px rgb(var(--t-ink-rgb) / 0.12);
  font-size: 9.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--c-fg);
  white-space: nowrap;
  pointer-events: none;
}
.ctiers:has(.ctier__flag) .ctier { padding-top: 30px; }
.ctiers input:checked + .ctier .ctier__flag {
  background: var(--t-ink);
  box-shadow: none;
  color: var(--t-page);
}

/* SELECTED: a stronger DARK outline and a subtle warm fill, replacing the
   clay border and clay tint. Dark reads as "chosen" at a glance where a
   mid-tone does not, and the fill stays warm rather than becoming a grey. */
.ctiers input:checked + .ctier {
  border-color: var(--t-ink);
  background: color-mix(in srgb, var(--c-clay, var(--t-accent)) 7%, var(--t-page));
  box-shadow: inset 0 0 0 1px var(--t-ink);
}
.ctiers input:focus-visible + .ctier { outline: 2px solid var(--t-ink); outline-offset: 3px; }

.ctier__m { width: 60px; height: 60px; border-radius: 12px; }
.ctier__n { font-size: 15px; font-weight: 600; }
.ctier__s { font-size: 12.5px; }
.ctier__note { font-size: 12.5px; color: var(--c-muted); line-height: 1.4; }

/* Price right, compare-at BELOW it — the brief's order, and the one that reads
   as "this is the price, that was the price". */
.ctier__prices { align-items: flex-end; gap: 2px; }
.ctier__p { font-size: 16px; font-weight: 600; margin-left: 0; }
.ctier__was { order: 2; }
.ctier__p--unset {
  font-size: 11.5px;
  font-weight: 400;
  color: var(--c-muted);
  text-align: right;
  max-width: 130px;
  white-space: normal;
  line-height: 1.35;
}

/* ── the urgency line ───────────────────────────────────────────────────── */
.curg {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0 0 10px;
  font-family: var(--c-sans);
  font-size: 13px;
  line-height: 1.45;
  color: var(--c-fg);
}
.curg[hidden] { display: none; }
.curg__dot {
  flex: none;
  width: 7px;
  height: 7px;
  margin-top: 5px;
  border-radius: 50%;
  background: #C08A2E;
}
.curg--green .curg__dot { background: #2E7D5B; }
.curg__t { min-width: 0; }

/* Opacity and a few pixels, once. Not a flashing banner. */
@media (prefers-reduced-motion: no-preference) {
  .curg--anim { animation: curg-in 420ms var(--c-ease, ease) both; }
}
@keyframes curg-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}

.curg--todo {
  color: var(--c-muted);
  font-size: 12px;
  border: 1px dashed var(--c-line);
  border-radius: 10px;
  padding: 8px 10px;
}


/* THE FLOATING DISCOUNT TAB AND THE OFFER STRIP OFFER THE SAME THING.

   Both are a discount, and on the product page the strip is the one attached
   to what the customer is actually looking at. Showing the floating tab as
   well put a second, competing offer over the right edge of the deal cards —
   and, on a narrow screen, over the coupon controls once the code is
   revealed. So on any page carrying the gate, the tab stands down.

   Scoped with :has() to the gate itself rather than to the product template,
   so a page that does not carry the strip keeps its tab. */
body:has([data-calmy-gate]) .cspin__tab { display: none !important; }

/* ── Purchase panel: hook, saving, benefit rows ─────────────────────────── */
.cinfo__hook {
  margin: 6px 0 0;
  font-family: var(--c-sans);
  /* 14–16px on a phone, per the brief, with room to breathe. */
  font-size: 15px;
  line-height: 1.5;
  color: var(--c-muted);
  max-width: 34ch;
}
.cinfo__save {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--c-clay, var(--t-accent));
  color: var(--t-page);
  font-family: var(--c-sans);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
/* Consistent check icons, 8–12px apart, readable on a phone. */
.cben3 { margin: 14px 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 10px; }
.cben3 li {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  font-family: var(--c-sans);
  font-size: 15px;
  line-height: 1.45;
  color: var(--c-fg);
}
.cben3 li svg { flex: none; margin-top: 2px; width: 15px; height: 15px; color: var(--club-olive, #6B7355); }

/* ── Restock progress ───────────────────────────────────────────────────── */
.crst {
  margin: 0 0 12px;
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--t-card);
  font-family: var(--c-sans);
}
.crst__head { margin: 0 0 8px; display: flex; align-items: center; gap: 8px; font-size: 12.5px; font-weight: 600; color: var(--c-fg); }
.crst__dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--club-olive, #6B7355); }
.crst--low .crst__dot { background: #C08A2E; }
.crst__low {
  margin-left: auto;
  padding: 2px 8px;
  border-radius: 999px;
  background: #C08A2E;
  color: var(--t-page);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
}
.crst__nums { margin: 0 0 7px; display: flex; justify-content: space-between; gap: 12px; font-size: 12.5px; color: var(--c-muted); font-variant-numeric: tabular-nums; }
.crst__track { height: 6px; border-radius: 999px; background: rgb(var(--t-ink-rgb) / 0.09); overflow: hidden; }
.crst__fill { display: block; height: 100%; border-radius: 999px; background: var(--club-olive, #6B7355); width: var(--pct, 0%); }
/* Once, to its real value. Never a crawl toward full. */
@media (prefers-reduced-motion: no-preference) {
  .crst__fill { animation: crst-fill 800ms var(--c-ease, ease) both; }
}
@keyframes crst-fill { from { width: 0; } to { width: var(--pct, 0%); } }
.crst__scope, .crst__asof { margin: 7px 0 0; font-size: 11.5px; line-height: 1.45; color: var(--c-soft); }
.crst--todo {
  background: transparent;
  border: 1px dashed var(--c-line);
  font-size: 12px;
  line-height: 1.5;
  color: var(--c-muted);
}

/* ── Countdown ──────────────────────────────────────────────────────────── */
.ccd {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  font-family: var(--c-sans);
  /* Visually secondary, per the brief. */
  font-size: 11.5px;
  color: var(--c-muted);
  white-space: nowrap;
}
.ccd__t {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--c-fg);
  /* Reserved so a digit change cannot nudge the layout. */
  min-width: 8ch;
  display: inline-block;
}
.ccd[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) { .crst__fill { animation: none; } }

/* ── Offer cards: proportions ───────────────────────────────────────────────
   The thumbnail was 60px and the price column carried a full sentence of
   merchant instruction, which squeezed the title into a sliver and doubled the
   card's height. The instruction has moved out of the card entirely (editor
   only, below it), so the three columns can take their intended proportions:
   a small fixed thumbnail, a flexible middle that gets all the slack, and a
   price column only as wide as a price. */
.ctier { grid-template-columns: 52px minmax(0, 1fr) auto; gap: 12px; }
.ctier__m { width: 52px; height: 52px; border-radius: 10px; }
.ctier__b { min-width: 0; }
.ctier__n, .ctier__s, .ctier__note { overflow-wrap: anywhere; }
.ctier__prices { min-width: 0; white-space: nowrap; }
.ctier__setup {
  margin: -4px 0 4px;
  padding: 8px 10px;
  border: 1px dashed var(--c-line);
  border-radius: 10px;
  font-family: var(--c-sans);
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--c-muted);
}
.ctier__setup strong { color: var(--c-fg); }

/* Reassurance under Add to cart. */
.cinfo__reassure {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 10px 0 0;
  font-family: var(--c-sans);
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--c-muted);
}
.cinfo__reassure svg { flex: none; margin-top: 2px; width: 14px; height: 14px; color: var(--club-olive, #6B7355); }

/* Merchant-supplied payment logos: one visual height, real aspect ratios. */
.cpay__i--custom { height: 26px; width: auto; display: block; object-fit: contain; }
.cpay__todo {
  margin: 8px 0 0;
  padding: 8px 10px;
  border: 1px dashed var(--c-line);
  border-radius: 10px;
  font-family: var(--c-sans);
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--c-muted);
}

/* Editor-only UGC slot placeholders. */
.cugin__i--todo {
  display: grid;
  place-items: center;
  aspect-ratio: 3 / 4;
  border: 1px dashed var(--c-line);
  border-radius: 14px;
  background: var(--t-card);
}
.cugin__todo {
  padding: 10px;
  text-align: center;
  font-family: var(--c-sans);
  font-size: 11px;
  line-height: 1.45;
  color: var(--c-muted);
}
.cugin__todo strong { display: block; margin-bottom: 4px; color: var(--c-fg); font-size: 12px; }
.crst--preview { border: 1px dashed var(--c-line); background: transparent; }
.crst--preview .crst__low { background: var(--c-muted); }

/* ── Compact featured review (replaces the engraving field) ─────────────── */
.cfrev {
  margin: 0 0 18px;
  padding: 13px;
  border-radius: 14px;
  /* A subtly contrasting surface, not a bordered testimonial panel. */
  background: var(--t-card);
  font-family: var(--c-sans);
}
.cfrev__who { display: flex; align-items: center; gap: 10px; }
.cfrev__av {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
  background: var(--t-page);
}
.cfrev__id { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.cfrev__name {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 13px;
  font-weight: 600;
  color: var(--c-fg);
}
.cfrev__tick { display: inline-flex; color: #2E7D5B; }
.cfrev__tick svg { display: block; }
.cfrev__stars { display: inline-flex; gap: 1.5px; }
.cfrev__stars svg { fill: rgb(var(--t-ink-rgb) / 0.18); display: block; }
.cfrev__stars svg.is-on { fill: var(--club-olive, #6B7355); }
.cfrev__q {
  margin: 8px 0 0;
  font-size: 14px;
  line-height: 1.4;
  color: var(--c-fg);
}
/* No quotation marks and no italics — this is a short line of evidence in the
   buying column, not a pull quote. */
.cfrev--todo {
  background: transparent;
  border: 1px dashed var(--c-line);
  font-size: 12px;
  line-height: 1.5;
  color: var(--c-muted);
}
.cfrev--todo strong { display: block; color: var(--c-fg); margin-bottom: 3px; }


/* ─────────────────────────────────────────────────────────────────────────
   NOTE ON PLACEMENT: this file has accumulated several appended blocks, and
   two later ones also style .ctier__flag (a corner badge and a pill). The
   ribbon has to be the LAST word on that selector, so it lives at the end of
   the file on purpose. Moving it earlier silently restores the pill.
   ───────────────────────────────────────────────────────────────────────── */
/* ── THE OFFER RIBBON ───────────────────────────────────────────────────────
   A small black ribbon straddling the card's top border, near the right edge,
   with folded ends tucked behind it.

   OVERFLOW. The ribbon is half outside its card, so every box between it and
   the page must let it out — .ctier and .ctiers are stated visible rather than
   assumed, because one `overflow: hidden` anywhere on that chain would clip
   the top half and nothing would look wrong in the CSS.

   RESERVED SPACE, twice over. The cards carry extra top padding so the ribbon
   never sits on a title or a price, and the group's gap is widened so the half
   that hangs above a card cannot land on the card before it. Both are applied
   to EVERY card in the group via :has(), so the three stay aligned. */
.ctiers { overflow: visible; }
.ctiers:has(.ctier__flag) { row-gap: 22px; }
.ctier { overflow: visible; }
.ctiers:has(.ctier__flag) .ctier { padding-top: 26px; }

.ctier__flag {
  position: absolute;
  /* Half above the border: 26px tall, so -13px straddles it exactly. */
  top: -13px;
  right: 16px;
  left: auto;
  z-index: 3;
  height: 26px;
  display: inline-flex;
  align-items: center;
  padding: 0 12px;
  margin: 0;
  width: max-content;
  max-width: calc(100% - 32px);
  background: #111111;
  color: #FFFFFF;
  /* Square at the top where it meets the fold, softly rounded below. */
  border-radius: 2px 2px 7px 7px;
  box-shadow: none;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1;
  white-space: nowrap;
  pointer-events: none;
}
/* The folded ends. Two darker triangles sitting BEHIND the ribbon at each
   end, so the band reads as cloth turned back on itself rather than a pill. */
.ctier__flag::before,
.ctier__flag::after {
  content: "";
  position: absolute;
  top: 0;
  z-index: -1;
  border-style: solid;
  border-color: transparent;
}
.ctier__flag::before {
  left: -7px;
  border-width: 0 7px 7px 0;
  border-right-color: #000000;
}
.ctier__flag::after {
  right: -7px;
  border-width: 0 0 7px 7px;
  border-left-color: #000000;
}
/* Black in every state — a ribbon that changes colour on selection reads as a
   control rather than a label. */
.ctier:hover .ctier__flag,
.ctiers input:checked + .ctier .ctier__flag { background: #111111; color: #FFFFFF; }

/* ── Offer countdown and free-shipping line ─────────────────────────────────
   Appended last on purpose: an earlier .ccd block in this file styles the
   timer as a small inline span beside a heading, and this is the centred,
   icon-led line that replaces it. Source order is what decides. */
.ccd {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  flex-wrap: wrap;
  margin: 14px 0;
  font-family: var(--c-sans);
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.4;
  /* Dark burgundy by default; the merchant can change it. */
  color: var(--ccd-col, #6B2D3C);
  text-align: center;
}
.ccd__ic { flex: none; display: block; }
.ccd__l { color: inherit; }
.ccd__t {
  font-weight: 600;
  /* Tabular figures and a reserved width, so a ticking second cannot nudge
     the line and shift the cards under it. */
  font-variant-numeric: tabular-nums;
  min-width: 7.5ch;
  text-align: left;
  display: inline-block;
  color: inherit;
}
.ccd[hidden] { display: none; }
.ccd--preview { opacity: 0.85; }
.ccd__pv {
  flex-basis: 100%;
  font-size: 10.5px;
  font-weight: 400;
  color: var(--c-muted);
}

.cshipl {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: 8px;
  margin: 0 0 14px;
  font-family: var(--c-sans);
  font-size: 14px;
  line-height: 1.4;
  color: var(--c-fg);
  text-align: left;
}
.cshipl__ic { flex: none; margin-top: 1px; color: var(--c-fg); }
.cshipl a { color: inherit; text-decoration: underline; text-underline-offset: 3px; margin-left: 5px; }
.cshipl--preview { color: var(--c-muted); }
.cshipl--preview em {
  display: block;
  margin-top: 3px;
  font-style: normal;
  font-size: 10.5px;
  line-height: 1.45;
}
