/* Crystalwala — the elevation layer.

   The base design (storefront.css) is correct but reads as "a website with
   products on it". This file is the difference between that and a store that
   feels expensive. It is loaded last, so it is the layer that wins.

   What the category actually does, from tearing down gemsmantra.com and
   divinehindu.in (2026-08-31): metallic gold rather than flat gold, hard
   numbers rather than adjectives, dense product cards carrying price, saving
   and action together, and warm dark bands breaking up the cream.

   ONE THING WE DELIBERATELY DO NOT COPY: both competitors lean on
   "Govt. Certified", "Lab-Certified" and "100% CERTIFIED" badges. We hold no
   certification data at all -- that is ticket CW-13, unanswered -- and
   SESSION-LOG section 9 records that the copy we replaced made exactly these
   unbackable claims, which in India engage the Drugs and Magic Remedies
   (Objectionable Advertisements) Act 1954 and the Consumer Protection
   (E-Commerce) Rules 2020. So the premium feel here is bought with CRAFT,
   not with borrowed credentials. Every number below is one we can stand behind.
*/

:root {
	/* Gold as a metal, not a colour. A flat fill reads as mustard; the
	   highlight band at 30-70% is what makes it read as leaf. */
	--cw-foil: linear-gradient(100deg,
		#9C6F22 0%, #C89A3C 18%, #F2E0AE 38%, #D9B45C 52%,
		#F6EAC4 66%, #C89A3C 84%, #9C6F22 100%);

	--cw-foil-soft: linear-gradient(100deg,
		rgba(200,154,60,0) 0%, rgba(200,154,60,.55) 22%,
		rgba(246,234,196,.95) 50%, rgba(200,154,60,.55) 78%, rgba(200,154,60,0) 100%);

	/* A single grain tile, inlined. Flat dark fills band badly on wide
	   gradients; a little noise hides it and reads as paper rather than screen. */
	--cw-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.32'/%3E%3C/svg%3E");
}

/* ---------- typographic authority ---------- */

/* Bigger, tighter, more confident. The single cheapest thing that separates a
   premium store from a catalogue is that the display type is not timid. */
.cw-sec__title {
	font-size: clamp(2.1rem, 4.8vw, 3.4rem);
	letter-spacing: -0.022em;
	text-wrap: balance;
}

.cw-hero__title {
	font-size: clamp(2.9rem, 7vw, 5.4rem);
	letter-spacing: -0.028em;
}

.cw-sec__eyebrow {
	display: inline-flex;
	align-items: center;
	gap: .6rem;
	letter-spacing: .24em;
}

/* Hairline rules flanking the eyebrow. Small, and it makes a heading read as
   composed rather than typed. */
.cw-sec__head .cw-sec__eyebrow::before,
.cw-sec__head .cw-sec__eyebrow::after {
	content: "";
	width: 1.6rem;
	height: 1px;
	background: var(--cw-foil-soft);
}

.cw-sec__head--row .cw-sec__eyebrow::before,
.cw-sec__head--row .cw-sec__eyebrow::after { display: none; }

/* ---------- hero ---------- */

.cw-hero::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	background-image: var(--cw-grain);
	opacity: .16;
	mix-blend-mode: overlay;
	pointer-events: none;
}

.cw-hero__wrap { position: relative; z-index: 2; }

.cw-hero__title span {
	background: var(--cw-foil);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
	-webkit-text-fill-color: transparent;
}

.cw-tag {
	background: rgba(255, 246, 232, .09);
	backdrop-filter: blur(6px);
	border-color: rgba(246, 233, 206, .34);
}

/* The hero rule becomes real foil rather than a flat gold line. */
.cw-hero::after {
	height: 2px;
	background: var(--cw-foil);
	opacity: 1;
}

.cw-pill--solid {
	background: var(--cw-foil);
	color: #3A2408;
	border: 0;
	box-shadow: 0 12px 30px -14px rgba(200, 154, 60, .85);
}

/* ---------- credential bar ---------- */

/* Hard numbers, on a dark ground, immediately under the hero. Every figure is
   derived from the catalogue or from a decision already taken -- none is
   marketing. */
.cw-cred {
	background: var(--cw-color-maroon-dark);
	color: #F6E9CE;
	position: relative;
	isolation: isolate;
}

.cw-cred::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background-image: var(--cw-grain);
	opacity: .2;
}

.cw-cred__inner {
	max-width: var(--cw-wide);
	margin-inline: auto;
	padding: 1.4rem var(--cw-space-30);
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 1rem;
	text-align: center;
}

.cw-cred__item { position: relative; }

.cw-cred__item + .cw-cred__item::before {
	content: "";
	position: absolute;
	left: 0;
	top: 12%;
	bottom: 12%;
	width: 1px;
	background: linear-gradient(rgba(246,233,206,0), rgba(246,233,206,.4), rgba(246,233,206,0));
}

.cw-cred__n {
	display: block;
	font-family: var(--cw-font-display);
	font-size: clamp(1.3rem, 2.4vw, 1.85rem);
	font-weight: 600;
	line-height: 1.1;
	background: var(--cw-foil);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
	-webkit-text-fill-color: transparent;
	font-variant-numeric: tabular-nums;
}

.cw-cred__l {
	display: block;
	margin-top: .2rem;
	font-size: .74rem;
	letter-spacing: .13em;
	text-transform: uppercase;
	color: rgba(246, 233, 206, .72);
}

@media (max-width: 760px) {
	.cw-cred__inner { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.2rem .5rem; }
	.cw-cred__item:nth-child(3)::before { display: none; }
}

/* ---------- product card ---------- */

/* Competitors carry photo, name, price, saving and action in one tight block.
   Ours was airier and read as editorial rather than shoppable. */
.cw-card {
	display: flex;
	flex-direction: column;
	background: var(--cw-color-surface);
	border: 1px solid transparent;
	border-radius: var(--cw-r, 14px);
	overflow: hidden;
	padding: 0 0 1rem;
	box-shadow: var(--cw-shadow-soft);
	transition: transform 320ms cubic-bezier(.22,.61,.36,1),
	            box-shadow 320ms ease, border-color 320ms ease;
}

.cw-card:hover {
	transform: translateY(-6px);
	border-color: rgba(200, 154, 60, .55);
	box-shadow: 0 4px 10px rgba(42,29,22,.06), 0 34px 60px -30px rgba(42,29,22,.5);
}

/* The image well gets an inner ring, so a cut-out on a white ground still
   reads as a framed object rather than as a floating PNG. The client's
   photography is plain cut-outs on mixed grounds (SESSION-LOG section 8) and
   this is the CSS that makes a mixed set read as one catalogue. */
.cw-card__media {
	position: relative;
	display: grid;
	place-items: center;
	aspect-ratio: 1;
	padding: 6%;
	margin: 0 0 .85rem;
	background: radial-gradient(120% 90% at 50% 8%, #FFFFFF 0%, #FFFCF6 44%, #F4EADB 100%);
	box-shadow: inset 0 -1px 0 var(--cw-color-line);
	overflow: hidden;
}

.cw-card__media img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	transition: transform 700ms cubic-bezier(.22,.61,.36,1);
}

.cw-card:hover .cw-card__media img { transform: scale(1.07); }

.cw-card__title {
	margin: 0;
	padding-inline: .95rem;
	font-family: var(--cw-font-body);
	font-size: .9375rem;
	font-weight: 500;
	line-height: 1.4;
	letter-spacing: -0.005em;
	/* Two lines, so a long name cannot make one card taller than its row. */
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.cw-card__title a { color: var(--cw-color-ink); text-decoration: none; }
.cw-card:hover .cw-card__title a { color: var(--cw-color-maroon); }

.cw-card__price {
	padding: .5rem .95rem 0;
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: .45rem;
	font-size: 1.0625rem;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	color: var(--cw-color-ink);
}

/* Bagisto emits the price as HTML with its own <del>/<ins>. Style what it
   sends rather than trying to reformat it. */
.cw-card__price del,
.cw-card__price .price__old {
	color: var(--cw-color-muted);
	font-size: .875rem;
	font-weight: 500;
	text-decoration-thickness: 1px;
}

.cw-card__price ins { text-decoration: none; color: var(--cw-color-sale); }

.cw-card__cta { margin-top: auto; padding: .8rem .95rem 0; }

.cw-card__cta a,
.cw-card__cta button {
	display: block;
	width: 100%;
	border: 0;
	border-radius: 999px;
	padding: .72rem 1rem;
	font-family: var(--cw-font-body);
	font-size: .8125rem;
	font-weight: 600;
	letter-spacing: .02em;
	text-align: center;
	text-decoration: none;
	cursor: pointer;
	background: var(--cw-color-gold-soft);
	color: var(--cw-color-maroon);
	transition: background-color 200ms ease, color 200ms ease;
}

.cw-card:hover .cw-card__cta a,
.cw-card:hover .cw-card__cta button {
	background: var(--cw-color-maroon);
	color: #fff;
}

/* A sold-out product must not wear a buyable button. 277 of 1,278 products are
   out of stock, so on this catalogue the wrong state shows constantly. */
.cw-card__cta .cw-btn--soldout,
.cw-card:hover .cw-card__cta .cw-btn--soldout {
	background: transparent;
	color: var(--cw-color-muted);
	border: 1px solid var(--cw-color-line);
	cursor: default;
}

.cw-badge--sale {
	position: absolute;
	top: .6rem;
	z-index: 2;
	margin: 0;
	border-radius: 999px;
	padding: .26rem .7rem;
	background: var(--cw-color-save);
	color: #fff;
	font-size: .68rem;
	font-weight: 700;
	letter-spacing: .05em;
	text-transform: uppercase;
	left: .6rem;
}

/* ---------- grids ---------- */

.cw-grid__items {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--cw-space-30);
}

@media (max-width: 1024px) { .cw-grid__items { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 760px)  { .cw-grid__items { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ---------- rashi ---------- */

/* The glyph disc becomes a struck medal rather than a flat circle. */
.cw-rashi__glyph {
	background:
		radial-gradient(circle at 34% 26%, #FFF8E6 0%, #F3DFAE 46%, #DCBE79 100%);
	box-shadow:
		inset 0 1px 0 rgba(255,255,255,.9),
		inset 0 0 0 1px rgba(200,154,60,.5),
		0 2px 6px -2px rgba(122,31,35,.28);
	color: var(--cw-color-maroon);
	font-size: 1.75rem;
}

.cw-rashi__tile:hover .cw-rashi__glyph {
	background: radial-gradient(circle at 34% 26%, #E9C87E 0%, #C89A3C 60%, #A97C26 100%);
	color: #fff;
}

/* ---------- category tiles ---------- */

/* A thin foil edge inside the tile: it reads as a mounted plate rather than a
   photograph with text on it. */
.cw-cat::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 2;
	border-radius: inherit;
	box-shadow: inset 0 0 0 1px rgba(246, 234, 196, .22);
	pointer-events: none;
	transition: box-shadow 420ms ease;
}

.cw-cat:hover::after { box-shadow: inset 0 0 0 1px rgba(246, 234, 196, .6); }

.cw-cat__name { font-size: 1.6rem; letter-spacing: -0.015em; }

/* ---------- intent tiles ---------- */

.cw-intent__tile { padding: 1.5rem 1.25rem; }

.cw-intent__tile::before { background: var(--cw-foil); height: 2px; }

/* ---------- promise band ---------- */

.cw-promise {
	position: relative;
	isolation: isolate;
	background:
		radial-gradient(90% 120% at 50% -20%, #8E2A2C 0%, var(--cw-color-maroon) 46%, #5E1417 100%);
}

.cw-promise::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background-image: var(--cw-grain);
	opacity: .18;
}

.cw-promise::after {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 2px;
	background: var(--cw-foil);
}

/* ---------- footer ---------- */

.cw-footer { position: relative; }

.cw-footer::before {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 2px;
	background: var(--cw-foil);
}

.cw-foot-h { letter-spacing: .18em; }

/* ---------- reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
	.cw-card:hover { transform: none; }
	.cw-card:hover .cw-card__media img { transform: none; }
}

/* =========================================================================
   Bagisto's own components, restyled.

   Cart, checkout, the account area and the product page are Bagisto's views,
   untouched (ARCHITECTURE 5.1). They are dressed here instead: every rule below
   targets a class Bagisto already emits, so the flow keeps working and only the
   appearance changes. Restyling beats overriding -- an override is a file to
   keep in sync forever, a restyle is not.
   ========================================================================= */

/* ---------- buttons ---------- */

.primary-button {
	background: var(--cw-color-maroon) !important;
	border: 0 !important;
	border-radius: 999px !important;
	color: #fff !important;
	font-family: var(--cw-font-body) !important;
	font-weight: 600 !important;
	letter-spacing: .02em;
	box-shadow: 0 12px 26px -16px rgba(122, 31, 35, .9);
	transition: background-color 200ms ease, transform 200ms ease;
}

.primary-button:hover {
	background: var(--cw-color-maroon-dark) !important;
	transform: translateY(-1px);
}

.secondary-button {
	background: var(--cw-color-gold-soft) !important;
	border: 1px solid rgba(200, 154, 60, .5) !important;
	border-radius: 999px !important;
	color: var(--cw-color-maroon) !important;
	font-family: var(--cw-font-body) !important;
	font-weight: 600 !important;
	transition: background-color 200ms ease, color 200ms ease;
}

.secondary-button:hover {
	background: var(--cw-color-maroon) !important;
	color: #fff !important;
}

/* ---------- product page ---------- */

/* The name is the loudest thing on the page, then the price, then the action.
   Bagisto's default gives all three roughly equal weight. */
.cw-body main h1 {
	font-size: clamp(1.9rem, 3.4vw, 2.6rem);
	letter-spacing: -0.02em;
	text-wrap: balance;
}

/* Bagisto renders the price block with `text-2xl font-semibold`. Ours is
   heavier and uses tabular figures so a column of prices lines up. */
.cw-body main .text-2xl,
.cw-body main .text-xl {
	font-variant-numeric: tabular-nums;
}

/* The gallery stage: a framed plate rather than a bare white box, matching the
   image well on the cards. */
.cw-body main img {
	border-radius: 10px;
}

/* Bagisto's tab strip sits on a cool grey that fights the cream ground. */
.cw-body main .bg-zinc-100,
.cw-body main .bg-gray-100,
.cw-body main .bg-\[\#F5F5F5\] {
	background: var(--cw-color-ground-alt) !important;
}

.cw-body main .bg-white {
	background: var(--cw-color-surface);
}

/* Body copy on the product page was mid-grey on cream, which is thin at
   16px. Ink-soft is the token meant for secondary prose and clears 4.5:1. */
.cw-body main .text-zinc-500,
.cw-body main .text-gray-500,
.cw-body main .text-zinc-600 {
	color: var(--cw-color-ink-soft) !important;
}

/* ---------- category / listing page ---------- */

/* A listing with no heading reads as a search result, not a department. */
.cw-cathead {
	background: var(--cw-color-ground-alt);
	border-bottom: 1px solid var(--cw-color-line);
	padding: var(--cw-space-40) var(--cw-space-30);
	margin-bottom: var(--cw-space-40);
}

.cw-cathead__inner {
	max-width: var(--cw-wide);
	margin-inline: auto;
}

.cw-cathead__crumbs {
	font-size: var(--cw-text-xs);
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--cw-color-muted);
}

.cw-cathead__crumbs a { color: var(--cw-color-maroon); text-decoration: none; }

.cw-cathead__title {
	margin: .4rem 0 0;
	font-family: var(--cw-font-display);
	font-weight: 600;
	font-size: clamp(2.1rem, 4.6vw, 3.2rem);
	line-height: 1.05;
	letter-spacing: -0.02em;
}

.cw-cathead__count {
	margin: .5rem 0 0;
	color: var(--cw-color-muted);
	font-size: var(--cw-text-sm);
	font-variant-numeric: tabular-nums;
}

/* Bagisto's sort and per-page selects. */
.cw-body main select {
	font-family: var(--cw-font-body);
	border-radius: 999px !important;
	border-color: var(--cw-color-line) !important;
	background-color: var(--cw-color-surface) !important;
	color: var(--cw-color-ink) !important;
}

/* ---------- focus ---------- */

/* One visible focus style everywhere, including on Bagisto's own controls.
   Never removed -- a keyboard user with no focus ring cannot shop. */
.cw-body a:focus-visible,
.cw-body button:focus-visible,
.cw-body input:focus-visible,
.cw-body select:focus-visible {
	outline: 2px solid var(--cw-color-maroon);
	outline-offset: 2px;
	border-radius: 6px;
}

/* ---------- filter sidebar ---------- */

/* Bagisto's price slider ships navy, which belongs to no part of this palette. */
.cw-body input[type="range"] { accent-color: var(--cw-color-maroon); }

.cw-body main input[type="checkbox"] { accent-color: var(--cw-color-maroon); }

/* The slider track and thumb are styled elements, not a native range input. */
.cw-body .bg-navyBlue,
.cw-body [class*="bg-navyBlue"] { background-color: var(--cw-color-maroon) !important; }

.cw-body main [class*="border-navyBlue"] { border-color: var(--cw-color-maroon) !important; }

/* Filter group headings, to match the section eyebrows elsewhere. */
.cw-body main .filter-title,
.cw-body aside h3 {
	font-family: var(--cw-font-body);
	letter-spacing: .04em;
}

/* =========================================================================
   Scroll reveal — additive only.

   The ported stylesheet hides `.cw-reveal` at `opacity: 0` as soon as JS adds
   `cw-js` to <html>, and depends on JS adding `is-in` to bring it back. On this
   build `is-in` never landed, so six whole sections — categories, rashi, the
   product grid, intent, deity and the promise band — were present in the DOM
   and invisible. The page looked empty below the credential bar.

   SESSION-LOG 5.2 already records this exact failure on the WooCommerce build:
   "Content invisible if JS failed". Porting the CSS brought the pattern back
   with it. The lesson is not "add another failsafe" — it is that content must
   never be hidden waiting for JavaScript at all.

   So: the hidden state is neutralised, and the reveal becomes an animation that
   plays when `is-in` arrives and changes nothing when it does not. Worst case is
   now a section that appears without animating, instead of one that never
   appears.
   ========================================================================= */

.cw-js .cw-reveal,
.cw-js .cw-reveal.is-in {
	opacity: 1;
	transform: none;
}

.cw-js .cw-reveal.is-in {
	animation: cw-rise 640ms cubic-bezier(.22, .61, .36, 1) both;
	animation-delay: var(--d, 0s);
}

/* The staggered children keep their choreography, but only ever as an
   animation on an element that is already visible. */
.cw-js .cw-rashi.is-in .cw-rashi__tile,
.cw-js .cw-cats.is-in .cw-cat,
.cw-js .cw-grid.is-in .cw-grid__items > li {
	animation: cw-rise 600ms cubic-bezier(.22, .61, .36, 1) both;
	animation-delay: calc(var(--i, 0) * 55ms);
}

.cw-js .cw-rashi:not(.is-in) .cw-rashi__tile,
.cw-js .cw-cats:not(.is-in) .cw-cat,
.cw-js .cw-grid:not(.is-in) .cw-grid__items > li {
	animation: none;
	opacity: 1;
	transform: none;
}

@media (prefers-reduced-motion: reduce) {
	.cw-js .cw-reveal.is-in,
	.cw-js .cw-rashi.is-in .cw-rashi__tile,
	.cw-js .cw-cats.is-in .cw-cat,
	.cw-js .cw-grid.is-in .cw-grid__items > li {
		animation: none;
	}
}

/* ---------- brand mark ---------- */

/* ⚠️ THE MARK IS SQUARE, SO `max-width` IS ALSO ITS HEIGHT. The client's logo
   (CW-48) is a 1:1 circle, not the horizontal lockup this header was first
   built for, and it is a genuinely transparent PNG cut by
   scripts/logo/build-logo.py. Nothing needs blending away — `normal` is
   restated only because storefront.css sets a blend mode on this selector's
   ancestor chain in older deploys and the cascade should not be left to luck. */
.cw-logo img {
	mix-blend-mode: normal;
	max-width: 104px;
}

.cw-scrolled .cw-logo img { max-width: 84px; }

/* =========================================================================
   Forms — checkout, account, address book, contact.

   These are Bagisto's own views and stay Bagisto's (ARCHITECTURE 5.1). But
   checkout is where a customer decides whether to trust a shop with their card,
   and unstyled system inputs on a cream ground read as unfinished. Every rule
   below targets an element Bagisto already emits.
   ========================================================================= */

.cw-body input[type="text"],
.cw-body input[type="email"],
.cw-body input[type="password"],
.cw-body input[type="tel"],
.cw-body input[type="number"],
.cw-body input[type="search"],
.cw-body input[type="date"],
.cw-body select,
.cw-body textarea {
	font-family: var(--cw-font-body);
	font-size: 0.9375rem;
	color: var(--cw-color-ink);
	background-color: var(--cw-color-surface);
	border: 1px solid var(--cw-color-line) !important;
	border-radius: 12px !important;
	padding: 0.8rem 1rem;
	transition: border-color 180ms ease, box-shadow 180ms ease;
}

.cw-body textarea { border-radius: 12px !important; }

.cw-body input::placeholder,
.cw-body textarea::placeholder {
	color: var(--cw-color-muted);
	opacity: 1;
}

.cw-body input:focus,
.cw-body select:focus,
.cw-body textarea:focus {
	outline: none;
	border-color: var(--cw-color-gold) !important;
	box-shadow: 0 0 0 3px rgba(200, 154, 60, .22);
}

/* A field the customer must fill is worth marking clearly, and an error must
   be obvious without relying on colour alone -- hence the weight change too. */
.cw-body label {
	font-family: var(--cw-font-body);
	font-size: 0.8125rem;
	font-weight: 600;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: var(--cw-color-ink-soft);
}

.cw-body .text-red-600,
.cw-body .text-red-500,
.cw-body [class*="text-red"] {
	color: var(--cw-color-sale) !important;
	font-weight: 500;
}

/* Bagisto's links default to Tailwind blue, which belongs to no part of this
   palette. "Sign In" and "Apply Coupon" on the checkout were bright blue. */
.cw-body a.text-blue-700,
.cw-body [class*="text-blue"],
.cw-body .text-navyBlue {
	color: var(--cw-color-maroon) !important;
}

/* Checkout section headings and the cart summary. */
.cw-body main h2,
.cw-body main h3 {
	font-family: var(--cw-font-display);
	letter-spacing: -0.015em;
}

/* Panels on checkout sit on white; give them the same edge as our cards so the
   page reads as one design rather than two. */
.cw-body main .rounded-xl,
.cw-body main .rounded-2xl,
.cw-body main .rounded-lg {
	border-radius: 14px;
}

/* =========================================================================
   Listing page — filters and product grid.

   Two structural problems in Bagisto's defaults on a 1,278-product catalogue:

   1. The filter sidebar is `max-h-[1320px] overflow-y-auto`, so it grows its
      OWN scrollbar next to the page's. Two scrollbars side by side is a
      confusing control: the shopper cannot tell which one the wheel will move.
      It is also 342px wide, which on a 1440px screen is a quarter of the page
      spent on controls before a single product is seen.

   2. The product grid is hard-coded to three columns at every desktop width.
      Browsing a 209-product category three at a time is a lot of scrolling, and
      it leaves the cards oversized so each one reads as a feature rather than
      as one of many.
   ========================================================================= */

/* ---------- filter sidebar ---------- */

/* ⚠️ STILL A SIDEBAR ON /search, AND NO LONGER ONE ON A CATEGORY PAGE.

   CW-39 moved the CATEGORY filters into a collapsible full-width panel above
   the grid. The SEARCH page renders the same `categories.filters` include from
   Bagisto's own, un-overridden view and still lays it out as a left column, so
   these rules must stay exactly as they were or search regresses — measured
   2026-09-04: relaxing the width here dropped the search sidebar from 268px to
   310px of shrink-wrapped content beside a grid still expecting a column.

   The category treatment is scoped to `.cw-filterpanel .panel-side` in
   brand.css, which loads after this file. Do not move it here, and do not
   generalise this rule to match both. */
.cw-body .panel-side {
	/* Sticky beneath the header rather than internally scrolled: the filters
	   stay reachable the whole way down a long result set without owning a
	   scrollbar of their own. */
	max-height: none !important;
	overflow: visible !important;
	position: sticky;
	top: 5.5rem;
	min-width: 0 !important;
	width: 268px;
	flex: 0 0 268px;
}

@media (max-width: 1180px) {
	.cw-body .panel-side { width: 232px; flex-basis: 232px; }
}

/* Each filter group becomes a card, so the sidebar reads as a set of controls
   rather than one long undifferentiated column. */
.cw-body .panel-side > div > div {
	border-radius: 12px;
}

.cw-body .panel-side .filter-title,
.cw-body .panel-side p.font-medium,
.cw-body .panel-side p.font-semibold {
	font-family: var(--cw-font-body);
	font-size: .74rem !important;
	font-weight: 700;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--cw-color-muted);
}

/* The option list scrolls INSIDE its own group when it is long, rather than
   making the whole sidebar tall. This is the scroll the shopper actually
   wants, scoped to one control.

   This rule was written as `.panel-side [class*="max-h-"]` and MATCHED
   NOTHING: Bagisto's option list is `<ul class="pb-3 text-base text-gray-700">`
   and carries no max-height class at all, so for as long as the rule existed
   the comment above it described behaviour the site did not have. The sidebar
   ran to 4,370px on /rudraksha and 5,078px on /search.

   It is now addressed by the class the list actually has. The height cap is
   secondary to the real fix -- CategoryApiController stopped the API offering
   options that do not exist in the category, which took /rudraksha from ten
   groups to three and from 4,370px to 520px -- but a broad category such as
   Crystals & Stones legitimately has 41 sizes, and this keeps that one group
   from owning the page. */
.cw-body .panel-side ul[class~="pb-3"] {
	max-height: 15rem;
	overflow-y: auto;
	scrollbar-width: thin;
}

.cw-body .panel-side ul[class~="pb-3"]::-webkit-scrollbar { width: 5px; }

.cw-body .panel-side ul[class~="pb-3"]::-webkit-scrollbar-thumb {
	background: var(--cw-color-line);
	border-radius: 999px;
}

/* A whole row is the hit target, not just the 16px box -- 44px minimum. */
.cw-body .panel-side label {
	display: flex;
	align-items: center;
	gap: .55rem;
	min-height: 2.1rem;
	padding: .1rem .3rem;
	margin-inline: -.3rem;
	border-radius: 8px;
	font-size: .9rem;
	font-weight: 400;
	letter-spacing: 0;
	text-transform: none;
	color: var(--cw-color-ink);
	cursor: pointer;
	transition: background-color 140ms ease;
}

.cw-body .panel-side label:hover { background: var(--cw-color-ground-alt); }

.cw-body .panel-side input[type="checkbox"] {
	width: 1.05rem;
	height: 1.05rem;
	flex: none;
	accent-color: var(--cw-color-maroon);
}

/* The per-filter search box is a utility, not a form field: smaller, quieter. */
.cw-body .panel-side input[type="text"],
.cw-body .panel-side input[type="search"] {
	padding: .5rem .8rem .5rem 2.1rem;
	font-size: .85rem;
	border-radius: 999px !important;
	background-color: var(--cw-color-ground);
}

/* ---------- product grid ---------- */

/* Four across on a wide screen, three on a laptop, two on a phone. Denser than
   Bagisto's fixed three, which is what makes a category feel like a shop. */
@media (min-width: 1280px) {
	.cw-body main .grid.grid-cols-3 { grid-template-columns: repeat(4, minmax(0, 1fr)) !important; }
}

@media (min-width: 1061px) and (max-width: 1279px) {
	.cw-body main .grid.grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
}

.cw-body main .grid.grid-cols-3 { gap: 1.35rem !important; }

/* Bagisto's card caps itself at 291px and hangs its information panel off a
   negative margin so it slides on hover. Ours is a plain block: the price and
   the button are always visible, because hiding the price until hover is a
   dark pattern on a considered purchase, and it is invisible on touch. */
.cw-body main .grid.grid-cols-3 > div { max-width: none !important; }

.cw-body main .grid.grid-cols-3 .max-w-\[291px\],
.cw-body main .grid.grid-cols-3 .max-h-\[300px\] {
	max-width: none !important;
	max-height: none !important;
}

/* ---------- toolbar ---------- */

.cw-body main .grid.grid-cols-3 ~ *,
.cw-toolbar { font-variant-numeric: tabular-nums; }

/* The footer credit sits quietly: it is an attribution, not a call to action. */
.cw-footer__legal a {
	color: rgba(253, 246, 236, .82);
	text-decoration: none;
	border-bottom: 1px solid rgba(200, 154, 60, .5);
}

.cw-footer__legal a:hover { color: var(--cw-color-gold); }

/* ---------- mega-menu ---------- */

/* CSS-only, opened by :hover AND :focus-within so it is keyboard-operable and
   needs no JavaScript. Every entry is a real anchor, so the menu is crawlable
   and survives a script failure -- the same discipline as the rest of the
   storefront. */
.cw-nav__item { position: relative; }

.cw-nav__panel {
	position: absolute;
	top: 100%;
	left: 50%;
	transform: translate(-50%, 6px);
	min-width: 15rem;
	padding: .7rem;
	display: grid;
	gap: .1rem;
	background: var(--cw-color-surface);
	border: 1px solid var(--cw-color-line);
	border-radius: 14px;
	box-shadow: var(--cw-shadow-lift);
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition: opacity 180ms ease, transform 220ms cubic-bezier(.22,.61,.36,1);
	z-index: 40;
}

/* A gold hairline at the top edge, matching the section eyebrows. */
.cw-nav__panel::before {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 2px;
	border-radius: 14px 14px 0 0;
	background: var(--cw-foil);
}

.cw-nav__item:hover .cw-nav__panel,
.cw-nav__item:focus-within .cw-nav__panel {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
	transform: translate(-50%, 0);
}

/* A bridge across the gap, so the pointer can travel from the label to the
   panel without passing through dead space and closing it. */
.cw-nav__item::after {
	content: "";
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	height: 10px;
}

.cw-nav__panel a {
	display: block;
	padding: .5rem .75rem;
	border-radius: 8px;
	border-bottom: 0;
	font-size: .9rem;
	font-weight: 400;
	color: var(--cw-color-ink);
	white-space: nowrap;
	transition: background-color 140ms ease, color 140ms ease;
}

.cw-nav__panel a:hover {
	background: var(--cw-color-ground-alt);
	color: var(--cw-color-maroon);
	border-bottom: 0;
}

.cw-nav__all {
	font-weight: 600 !important;
	color: var(--cw-color-maroon) !important;
	border-bottom: 1px solid var(--cw-color-line) !important;
	border-radius: 8px 8px 0 0 !important;
	margin-bottom: .25rem;
}

.cw-nav__panel--wide {
	grid-template-columns: repeat(2, minmax(0, 1fr));
	min-width: 26rem;
}

@media (max-width: 900px) {
	.cw-nav__panel { display: none; }
}

/* ---------- full-bleed image band ---------- */

.cw-band {
	position: relative;
	isolation: isolate;
	margin-top: clamp(3.5rem, 8vw, 6rem);
	min-height: min(60vh, 460px);
	display: grid;
	align-items: center;
	overflow: hidden;
	color: #FFF6E8;
}

.cw-band__media {
	position: absolute;
	inset: 0;
	z-index: -2;
	background-size: cover;
	background-position: center;
	/* A slow drift, so the band is not a static slab. Transform only, so it
	   composites on the GPU and never triggers layout. */
	animation: cw-drift 26s ease-in-out infinite alternate;
}

@keyframes cw-drift {
	from { transform: scale(1.04) translate3d(0, 0, 0); }
	to   { transform: scale(1.1) translate3d(-1.5%, -1%, 0); }
}

/* The scrim guarantees contrast regardless of what the photograph does. */
.cw-band::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: linear-gradient(90deg,
		rgba(24, 8, 9, .94) 0%, rgba(38, 12, 13, .84) 34%,
		rgba(52, 16, 16, .42) 62%, rgba(60, 20, 20, .18) 100%);
}

.cw-band::after {
	content: "";
	position: absolute;
	inset: auto 0 0 0;
	height: 2px;
	background: var(--cw-foil);
}

.cw-band__inner {
	max-width: var(--cw-wide);
	width: 100%;
	margin-inline: auto;
	padding: clamp(3rem, 8vw, 5.5rem) var(--cw-space-30);
}

.cw-band__title {
	margin: .4rem 0 0;
	max-width: 22ch;
	font-family: var(--cw-font-display);
	font-weight: 600;
	font-size: clamp(2.1rem, 5vw, 3.6rem);
	line-height: 1.06;
	letter-spacing: -0.022em;
	color: #FFF6E8;
}

.cw-band__title span {
	background: var(--cw-foil);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
	-webkit-text-fill-color: transparent;
	font-style: italic;
	font-weight: 400;
}

.cw-band__body {
	margin: 1.1rem 0 0;
	max-width: 34rem;
	color: rgba(255, 246, 232, .84);
	line-height: 1.75;
}

.cw-band .cw-sec__eyebrow { color: var(--cw-color-gold); }

.cw-band .cw-sec__eyebrow::before,
.cw-band .cw-sec__eyebrow::after { display: none; }

/* ---------- split section ---------- */

.cw-split {
	max-width: var(--cw-wide);
	margin: clamp(3.5rem, 8vw, 6rem) auto 0;
	padding-inline: var(--cw-space-30);
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	gap: clamp(2rem, 5vw, 4rem);
	align-items: center;
}

.cw-split__media {
	border-radius: 18px;
	overflow: hidden;
	box-shadow: var(--cw-shadow-lift);
	aspect-ratio: 4 / 3;
}

.cw-split__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform 900ms cubic-bezier(.22,.61,.36,1);
}

.cw-split:hover .cw-split__media img { transform: scale(1.04); }

.cw-split__list {
	list-style: none;
	margin: var(--cw-space-30) 0 var(--cw-space-30);
	padding: 0;
	display: grid;
	gap: 1.1rem;
}

.cw-split__list li {
	padding-left: 1.1rem;
	border-left: 2px solid transparent;
	border-image: var(--cw-foil) 1;
}

.cw-split__list strong {
	display: block;
	font-size: 1.02rem;
	font-weight: 600;
	letter-spacing: -0.005em;
}

.cw-split__list span {
	display: block;
	margin-top: .15rem;
	color: var(--cw-color-ink-soft);
	font-size: .9375rem;
	line-height: 1.6;
}

@media (max-width: 860px) {
	.cw-split { grid-template-columns: 1fr; }
	.cw-split__media { order: -1; }
}

@media (prefers-reduced-motion: reduce) {
	.cw-band__media { animation: none; }
	.cw-split:hover .cw-split__media img { transform: none; }
}

/* ---------- product gallery: contain the image ---------- */

/* Bagisto's gallery image carries `min-w-[450px]` and no height constraint, so
   a PORTRAIT photograph resolves to 560x840 inside a box capped at 610px and
   spills 230px over the copy beneath it. Measured, not guessed: the image
   computed to `object-fit: fill` and `max-height: none`.
   `max-height: inherit` picks up the container's own cap.

   ⚠️ These rules were once written as `main [class*="max-h-["]`, and that
   substring selector is a trap on a Tailwind build: EVERY arbitrary max-height
   in the theme matches it. It caught the filter sidebar — Bagisto ships it as
   `panel-side grid max-h-[1320px] grid-cols-[1fr]` — forced `display: flex` over
   its `grid`, and laid all fifteen filter groups out in a ROW inside a 268px
   column. Each group collapsed to 83px, five of them sat at negative x off the
   left edge, and the rest overlapped the product grid. It also centre-aligned
   the thumbnail RAIL, which is a scroll container: `justify-content: center`
   makes overflow unreachable in the start direction.

   None of the three verifiers caught it, because the sidebar never produced a
   horizontal scrollbar and the spill check only compared HEIGHT.

   So the gallery is now addressed by the exact boxes it owns. If Bagisto
   changes those numbers the rule stops applying and the image grows again --
   which is a visible, diagnosable failure, unlike a selector that silently
   reaches across the whole storefront. `scripts/ui-checks/verify.mjs` now
   asserts the sidebar is a single column, so the regression cannot return
   unnoticed. */
.cw-body main .max-h-\[610px\] > img,
.cw-body main .max-h-\[610px\] img,
.cw-body main .max-h-\[540px\] img {
	max-height: inherit;
	max-width: 100%;
	min-width: 0 !important;
	height: auto;
	object-fit: contain;
}

/* Only the base-image well is centred. The thumbnail rail above it is
   deliberately left alone: it is `flex flex-col overflow-auto`, and centring a
   scroll container hides its own content. */
.cw-body main .max-h-\[610px\] {
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
}

/* ---------- header nav: never wrap ---------- */

/* Eight items at 678px plus seven 24px gaps needs 846px in 752px of space, so
   the bar wrapped to two rows and the header grew from 78px to 136px. Fewer
   inline items, a tighter gap, and an explicit nowrap. */
.cw-nav {
	flex-wrap: nowrap;
	gap: clamp(.6rem, 1.4vw, 1.35rem);
	min-width: 0;
}

.cw-nav > .cw-nav__item > a {
	white-space: nowrap;
	font-size: clamp(.82rem, 1.05vw, .95rem);
}

.cw-header__inner { flex-wrap: nowrap; }

/* The search field yields first when space is tight -- it has a placeholder to
   spare, whereas a truncated category name is a broken label. */
.cw-search input { min-width: 0; width: clamp(7rem, 16vw, 15rem); }

@media (max-width: 1100px) {
	.cw-nav { gap: .55rem; }
}

/* ---------- nav item height ---------- */

/* The link's padding made it 30px inside a 28px inline-level parent. Flex makes
   the item take its child's height instead of the line box's. */
.cw-nav__item {
	display: flex;
	align-items: center;
}

/* ---------- tap targets ---------- */

/* WCAG 2.5.8 wants 24x24 minimum. Inline links inside a sentence are exempt,
   but a breadcrumb is a standalone control and was 45x15. */
.cw-cathead__crumbs a {
	display: inline-block;
	padding: .35rem .15rem;
	min-height: 24px;
	line-height: 1.5;
}

/* The card title is the card's main link, so it gets a real hit area rather
   than the height of its text. */
.cw-card__title a {
	display: block;
	padding-block: .15rem;
}

/* =========================================================================
   Mobile navigation — added 2026-09-02.

   `.cw-nav { display: none }` fires at 900px (components.css) and nothing
   replaced it, so below that width the storefront had NO route to any
   category. On an India-first D2C store that is the majority of traffic.

   Built on a native <details>, so it needs no JavaScript and no ARIA of our
   own: the browser owns the expanded/collapsed state and announces it. The
   scrim is the summary's ::after, which means a tap outside the panel lands on
   the same element that opened it and closes it -- no click-outside handler,
   nothing to fail.
   ========================================================================= */

.cw-mobnav { display: none; }

.cw-mobnav > summary {
	list-style: none;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	margin-inline-start: -.35rem;
	border-radius: 10px;
	cursor: pointer;
	position: relative;
	z-index: 62;
}

/* When open the toggle leaves the header's flow and pins itself to a KNOWN
   corner. It has to: the announce bar wraps to two lines at 390px, so the
   header's height is not a constant, and a panel padded to clear a variable
   header either overlaps the close control or wastes 60px of a phone screen.
   Fixed at 12px, the panel's top padding is a fixed number too. */
.cw-mobnav[open] > summary {
	position: fixed;
	top: .75rem;
	inset-inline-start: .75rem;
}

.cw-mobnav > summary::-webkit-details-marker { display: none; }

.cw-mobnav > summary:focus-visible {
	outline: 2px solid var(--cw-color-maroon);
	outline-offset: 2px;
}

/* Three bars, drawn rather than iconfont-loaded: the header must not depend on
   a webfont arriving to show its only navigation control. */
.cw-mobnav__bars,
.cw-mobnav__bars::before,
.cw-mobnav__bars::after {
	display: block;
	width: 20px;
	height: 2px;
	border-radius: 2px;
	background: var(--cw-color-ink);
	transition: transform 200ms ease, opacity 160ms ease;
}

.cw-mobnav__bars { position: relative; }

.cw-mobnav__bars::before,
.cw-mobnav__bars::after {
	content: "";
	position: absolute;
	left: 0;
}

.cw-mobnav__bars::before { top: -6px; }
.cw-mobnav__bars::after  { top: 6px; }

.cw-mobnav[open] .cw-mobnav__bars { background: transparent; }
.cw-mobnav[open] .cw-mobnav__bars::before { transform: translateY(6px) rotate(45deg); }
.cw-mobnav[open] .cw-mobnav__bars::after  { transform: translateY(-6px) rotate(-45deg); }

/* The scrim hangs off the <details>, NOT off the summary.

   It was on `summary::after` first, and that was wrong: the summary carries a
   z-index, so it opens a stacking context and every z-index inside it -- the
   scrim included -- is resolved against the summary's own level, not the
   page's. The scrim therefore painted OVER the panel and the whole drawer came
   up washed grey with the category names barely legible. <details> itself sets
   no z-index, so its pseudo lands in the header's stacking context where the
   58 / 60 / 62 ordering below actually means something.

   pointer-events: none so a tap meant for the page is not swallowed; tap-to-
   close is layered on as an enhancement in the header partial, and the close
   control is the toggle itself, which is always visible at top-left. */
.cw-mobnav[open]::before {
	content: "";
	position: fixed;
	inset: 0;
	background: rgba(37, 19, 12, .45);
	pointer-events: none;
	z-index: 58;
}

.cw-mobnav__panel {
	position: fixed;
	inset-block: 0;
	inset-inline-start: 0;
	width: min(86vw, 340px);
	padding: 4.25rem 1.25rem 2rem;
	overflow-y: auto;
	overscroll-behavior: contain;
	background: var(--cw-color-surface);
	border-inline-end: 1px solid var(--cw-color-line);
	box-shadow: var(--cw-shadow-lift);
	z-index: 60;
}

.cw-mobnav__eyebrow {
	margin: 1.4rem 0 .5rem;
	font-family: var(--cw-font-body);
	font-size: .7rem;
	font-weight: 700;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--cw-color-muted);
}

.cw-mobnav__eyebrow:first-child { margin-top: 0; }

.cw-mobnav__panel a {
	display: block;
	padding: .62rem .5rem;
	margin-inline: -.5rem;
	border-radius: 8px;
	color: var(--cw-color-ink);
	text-decoration: none;
	line-height: 1.35;
}

.cw-mobnav__panel a:active { background: var(--cw-color-ground-alt); }

.cw-mobnav__parent { font-weight: 600; }

.cw-mobnav__children {
	margin: .1rem 0 .5rem;
	padding-inline-start: .85rem;
	border-inline-start: 1px solid var(--cw-color-line);
}

.cw-mobnav__children a {
	font-size: .9rem;
	color: var(--cw-color-ink-soft);
	padding-block: .5rem;
}

@media (max-width: 900px) {
	.cw-mobnav { display: block; }
}

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

/* ---------- header: fit the phone ---------- */

/* Adding the hamburger took 44px the bar did not have: at 390px the actions
   group ended at x=430 and the whole document scrolled sideways. The search
   field is the element that must yield -- it has a placeholder to spare,
   whereas a clipped cart icon is a lost route to checkout. */
.cw-header__actions { min-width: 0; }

.cw-search { min-width: 0; flex: 0 1 auto; }

/* The placeholder is longer than the field on a phone and was butting straight
   into the submit button. An ellipsis makes the truncation deliberate. */
.cw-search input {
	text-overflow: ellipsis;
}

@media (max-width: 900px) {
	.cw-header__inner { gap: .7rem; }
	.cw-search input { width: 100%; }
}

@media (max-width: 620px) {
	.cw-header__inner { padding-inline: 1rem; gap: .5rem; }
	/* The logo is the brand and the icons are the routes out; the field takes
	   whatever is left and no more. */
	.cw-search { flex: 1 1 6rem; }
	.cw-search input { width: 100%; min-width: 0; padding-inline: .85rem 2.4rem; }
	.cw-logo img { max-width: 84px; }
}

/* ---------- reading measure ---------- */

/* The product description ran the full width of the page -- 1,150px lines at
   1440px, roughly 150 characters. Anything past ~75 makes the eye lose the
   line's start on the return sweep. Bagisto's tab panel has no measure of its
   own, so one is imposed here rather than in the vendor view. */
.cw-body main [class*="tab"] p,
.cw-body main [class*="tab"] li,
.cw-body .cw-prose,
.cw-body main .container > div > p {
	max-width: 68ch;
}

/* ---------- empty states ---------- */

/* Bagisto's empty-basket and no-results art is navy and mid-grey, two colours
   that appear nowhere else in this palette, and it is the largest thing on the
   page when a shopper has just filtered themselves into nothing. Desaturating
   and softening it lets the copy carry the moment instead. */
.cw-body main img[src*="empty"],
.cw-body main img[src*="cart"][src*=".svg"],
.cw-body main svg[class*="empty"] {
	filter: grayscale(1) opacity(.42);
	max-width: 128px;
	height: auto;
}
