/**
 * FLUXX — components.
 *
 * Buttons, chips, badges, cards, drawers. Reads tokens.css.
 */

/* ---------------------------------------------------------------- buttons */
/*
 * Square, black, uppercase, no shadow. The primary CTA sets the tone for every
 * control on the site, so it is worth getting exactly right: sharp corners here
 * are a decision, not an oversight.
 */

.fx-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	height: var(--fx-control-cta);
	padding-inline: 24px;
	border: 0;
	border-radius: var(--fx-radius-none);
	background: var(--fx-ink);
	color: var(--fx-text-on-dark);
	font-size: 14px;
	font-weight: var(--fx-weight-bold);
	line-height: 1;
	letter-spacing: var(--fx-tracking-cta);
	text-transform: uppercase;
	cursor: pointer;
	transition: background-color var(--fx-dur) var(--fx-ease),
		color var(--fx-dur) var(--fx-ease),
		border-color var(--fx-dur) var(--fx-ease);
}

.fx-btn:hover,
.fx-btn:active {
	background: var(--fx-ink-hover);
	color: var(--fx-text-on-dark);
}

.fx-btn[disabled],
.fx-btn.is-disabled {
	opacity: .4;
	cursor: not-allowed;
	pointer-events: none;
}

.fx-btn--block {
	width: 100%;
}

.fx-btn--secondary {
	background: transparent;
	color: var(--fx-ink);
	border: 1px solid var(--fx-ink);
}

.fx-btn--secondary:hover {
	background: var(--fx-surface);
	color: var(--fx-ink);
}

.fx-btn--sm {
	height: var(--fx-control-sm);
	padding-inline: 16px;
	font-size: 12px;
}

/* A text link that behaves like a button. Underlined, ink, no chrome. */
.fx-btn--link {
	height: auto;
	padding: 0;
	background: none;
	color: var(--fx-ink);
	text-decoration: underline;
	text-underline-offset: 0.25em;
	letter-spacing: var(--fx-tracking-body);
	text-transform: none;
	font-weight: var(--fx-weight-regular);
}

/* -------------------------------------------------------------- size chips */
/*
 * Square. 44px tall, 48px minimum wide, grey hairline that goes black when
 * selected. Adjacent chips collapse their borders into one connected strip.
 *
 * Note this is NOT the rounded pill used for filters and sort below — the two
 * look alike in a screenshot and are different components.
 */

.fx-chips {
	display: flex;
	flex-wrap: wrap;
}

.fx-chip {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	height: var(--fx-control-md);
	min-width: 48px;
	padding-inline: 12px;
	border: 1px solid var(--fx-border-control);
	border-radius: var(--fx-radius-none);
	background: var(--fx-paper);
	font-size: 12px;
	line-height: 1;
	cursor: pointer;
	user-select: none;
	transition: border-color var(--fx-dur) var(--fx-ease),
		background-color var(--fx-dur) var(--fx-ease);
}

/* Collapse shared borders so a size row reads as one strip. */
.fx-chip + .fx-chip {
	margin-inline-start: -1px;
}

.fx-chip:hover {
	background: var(--fx-surface);
}

.fx-chip.is-selected,
.fx-chip[aria-pressed="true"] {
	border-color: var(--fx-ink);
	/* Raise the selected chip so its full border is visible over its siblings. */
	position: relative;
	z-index: 1;
}

/*
 * Sold out reads as struck through and faded, but stays focusable and
 * clickable, because clicking it offers "Notify me". An inert sold-out size is
 * a dead end and one of the clearest complaints about the reference.
 */
.fx-chip.is-unavailable {
	text-decoration: line-through;
	opacity: .25;
}

.fx-chip.is-unavailable:hover {
	opacity: .4;
	background: var(--fx-paper);
}

/* ------------------------------------------------------------ filter pills */
/* The rounded one. Used only for the quick-filter rail and sort. */

.fx-pill {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	height: 34px;
	padding-inline: 14px;
	border: 1px solid var(--fx-border-strong);
	border-radius: var(--fx-radius-pill);
	background: var(--fx-paper);
	font-size: 12px;
	line-height: 1;
	white-space: nowrap;
	cursor: pointer;
	transition: border-color var(--fx-dur) var(--fx-ease),
		background-color var(--fx-dur) var(--fx-ease),
		color var(--fx-dur) var(--fx-ease);
}

.fx-pill.is-active {
	background: var(--fx-ink);
	border-color: var(--fx-ink);
	color: var(--fx-text-on-dark);
}

/*
 * The sticky quick-filter rail, with a shadow that fades in only once it has
 * stuck. A nice touch from the reference, worth reproducing exactly.
 */
.fx-chiprail {
	position: sticky;
	top: var(--fx-header-h);
	z-index: var(--fx-z-sticky);
	display: flex;
	gap: 8px;
	padding: 8px var(--fx-gutter);
	background: var(--fx-paper);
	overflow-x: auto;
	/*
	 * The rail lives inside a gutter'd container but has to scroll edge to
	 * edge, so it pulls out to the viewport and re-adds the gutter as its own
	 * padding. Without this the first chip sits at twice the gutter and looks
	 * indented against the heading above it.
	 */
	margin-inline: calc(var(--fx-gutter) * -1);
}

@media (min-width: 768px) {
	.fx-chiprail {
		top: var(--fx-header-h-md);
		padding-inline: var(--fx-gutter-md);
		margin-inline: calc(var(--fx-gutter-md) * -1);
	}
}

.fx-chiprail::after {
	content: "";
	position: absolute;
	bottom: -4px;
	inset-inline: 0;
	height: 4px;
	background: linear-gradient(180deg, rgba(0, 0, 0, .05), transparent);
	opacity: 0;
	transition: opacity var(--fx-dur-exit) var(--fx-ease);
	pointer-events: none;
}

.fx-chiprail.is-stuck::after {
	opacity: 1;
}

/* ----------------------------------------------------------------- badges */

.fx-badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 4px 6px;
	border-radius: var(--fx-radius-badge);
	font-size: 10px;
	font-weight: var(--fx-weight-bold);
	line-height: 1;
	letter-spacing: var(--fx-tracking-badge);
	text-transform: uppercase;
}

.fx-badge--sale {
	background: var(--fx-sale-bg);
	color: var(--fx-sale-fg);
}

.fx-badge--promo {
	background: var(--fx-promo-bg);
	color: var(--fx-ink);
}

.fx-badge--neutral {
	background: var(--fx-sand);
	color: var(--fx-ink);
}

.fx-badge--soldout {
	background: var(--fx-ink);
	color: var(--fx-text-on-dark);
}

/* ------------------------------------------------------------ colour swatch */

.fx-swatch {
	display: inline-block;
	width: 18px;
	height: 18px;
	border-radius: var(--fx-radius-round);
	border: 1px solid var(--fx-border-strong);
	background-color: var(--fx-swatch-colour, var(--fx-surface-muted));
}

.fx-swatch.is-selected {
	box-shadow: 0 0 0 1px var(--fx-paper), 0 0 0 2px var(--fx-ink);
}

/* ------------------------------------------------------------------ prices */

.fx-price {
	display: inline-flex;
	align-items: baseline;
	gap: 8px;
	flex-wrap: wrap;
}

/*
 * MRP sits BEFORE the selling price, struck through — the order the reference
 * uses, and the order Indian shoppers read.
 */
.fx-price__mrp {
	text-decoration: line-through;
	color: var(--fx-text);
	font-weight: var(--fx-weight-light);
}

.fx-price__now {
	font-weight: var(--fx-weight-bold);
}

.fx-price__now.is-discounted {
	color: var(--fx-sale-bg);
}

.fx-price__off {
	color: var(--fx-sale-bg);
	font-weight: var(--fx-weight-bold);
}

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

.fx-card {
	position: relative;
	display: flex;
	flex-direction: column;
}

.fx-card__media {
	position: relative;
	display: block;
	aspect-ratio: var(--fx-product-ratio);
	background: var(--fx-media-ground);
	overflow: hidden;
}

.fx-card__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/*
 * The hover swap. The reference has no second image on hover; we add it because
 * seeing the back of a shirt without a click is worth more than the fidelity.
 */
.fx-card__img--alt {
	position: absolute;
	inset: 0;
	opacity: 0;
	transition: opacity var(--fx-dur-exit) var(--fx-ease);
}

@media (hover: hover) {
	.fx-card:hover .fx-card__img--alt {
		opacity: 1;
	}
}

.fx-card__badges {
	position: absolute;
	top: 8px;
	inset-inline-start: 8px;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 4px;
	pointer-events: none;
}

.fx-card__wishlist {
	position: absolute;
	top: 8px;
	inset-inline-end: 8px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	color: var(--fx-ink);
	transition: color var(--fx-dur) var(--fx-ease);
}

/*
 * Saved is a filled heart in the accent, not just a darker outline. An outline
 * that changes weight is a state nobody notices, and the whole value of the
 * control is knowing at a glance which of twelve cards you already saved.
 */
.fx-card__wishlist.is-on {
	color: var(--fx-accent);
}

.fx-card__wishlist.is-on .fx-icon {
	fill: currentColor;
}

/* ------------------------------------------------------------- quick add */

/*
 * Sits over the foot of the image. On a pointer device it appears on hover, so
 * the grid stays a wall of photography; on touch there is no hover to wait for,
 * so it is simply always there.
 */
.fx-card__quickadd {
	position: absolute;
	inset-inline: 8px;
	bottom: 8px;
	/* The media anchor covers the whole image, so this has to sit over it. */
	z-index: 2;
	display: block;
	padding: 11px 0;
	background: var(--fx-paper);
	color: var(--fx-ink);
	font-size: 11px;
	font-weight: var(--fx-weight-bold);
	letter-spacing: var(--fx-tracking-cta);
	text-align: center;
	text-transform: uppercase;
	text-decoration: none;
}

@media (hover: hover) {
	.fx-card__quickadd {
		opacity: 0;
		transform: translateY(6px);
		transition:
			opacity var(--fx-dur) var(--fx-ease),
			transform var(--fx-dur) var(--fx-ease);
	}

	li.product:hover .fx-card__quickadd,
	.fx-card__quickadd:focus-visible {
		opacity: 1;
		transform: none;
	}
}

.fx-quickadd__head {
	display: flex;
	gap: 14px;
	align-items: center;
	margin-bottom: 20px;
}

.fx-quickadd__img {
	width: 64px;
	height: 85px;
	object-fit: cover;
	background: var(--fx-media-ground);
}

.fx-quickadd__name {
	margin: 0 0 4px;
	font-weight: var(--fx-weight-bold);
}

.fx-quickadd__row {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.fx-quickadd__note:empty {
	display: none;
}

.fx-quickadd__note {
	margin: 16px 0 0;
	color: var(--fx-text-muted);
	font-size: 13px;
}

/*
 * The size chips. Same control as the product page, restated here rather than
 * shared, because product.css is not loaded on the catalogue and loading a
 * whole product stylesheet to draw five chips is the wrong trade.
 */
.fx-sizechip {
	min-width: 48px;
	height: var(--fx-control-sm);
	padding-inline: 12px;
	border: 1px solid var(--fx-border-control);
	border-radius: 8px;
	background: var(--fx-paper);
	color: var(--fx-ink);
	font-size: 13px;
	cursor: pointer;
	transition: border-color var(--fx-dur) var(--fx-ease);
}

.fx-sizechip:hover:not(:disabled) {
	border-color: var(--fx-ink);
}

/*
 * Sold out is struck through and dimmed, but never removed and never disabled
 * in a way that hides it: knowing the M is gone is information, and a chip that
 * silently vanishes reads as a size the brand does not make.
 */
.fx-sizechip.is-out {
	color: var(--fx-text-disabled);
	border-color: var(--fx-border);
	text-decoration: line-through;
	cursor: not-allowed;
}

.fx-card__body {
	display: flex;
	flex-direction: column;
	gap: 4px;
	padding: 8px 8px 16px;
}

.fx-card__title {
	display: -webkit-box;
	-webkit-line-clamp: 1;
	line-clamp: 1;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.fx-card__colours {
	display: flex;
	align-items: center;
	gap: 4px;
}

/* The entrance animation: a 60px rise and fade as cards enter the viewport. */
.fx-card--enter {
	animation: fx-card-up .5s var(--fx-ease-out) both;
}

@keyframes fx-card-up {
	from { opacity: 0; transform: translateY(60px); }
	to   { opacity: 1; transform: translateY(0); }
}

/* ----------------------------------------------------- drawers and sheets */
/*
 * Entry and exit are deliberately asymmetric: in is a full slide at .3s, out
 * travels only 24px while fading at .25s, so it recedes rather than shoots off.
 * Copied exactly from the reference, and a large part of why it feels finished.
 */

.fx-scrim {
	position: fixed;
	inset: 0;
	z-index: var(--fx-z-scrim);
	background: var(--fx-scrim);
	backdrop-filter: blur(var(--fx-scrim-blur));
	animation: fx-fade-in var(--fx-dur-exit) var(--fx-ease-out) both;
}

.fx-scrim.is-closing {
	animation: fx-fade-out var(--fx-dur-exit) var(--fx-ease-in) both;
}

.fx-drawer {
	position: fixed;
	top: 0;
	inset-inline-end: 0;
	z-index: var(--fx-z-drawer);
	display: flex;
	flex-direction: column;
	width: min(420px, 100vw);
	height: 100%;
	background: var(--fx-paper);
	animation: fx-slide-in var(--fx-dur-enter) var(--fx-ease-out) both;
}

.fx-drawer.is-closing {
	animation: fx-panel-out var(--fx-dur-exit) var(--fx-ease-in) both;
}

/* On mobile a drawer becomes a bottom sheet, as it does in a native app. */
@media (max-width: 767px) {
	.fx-drawer--sheet {
		top: auto;
		bottom: 0;
		inset-inline: 0;
		width: 100%;
		height: auto;
		max-height: 85vh;
		border-radius: var(--fx-radius-panel) var(--fx-radius-panel) 0 0;
		animation-name: fx-slide-up;
	}

	.fx-drawer--sheet.is-closing {
		animation-name: fx-sheet-out;
	}
}

.fx-drawer__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 16px var(--fx-gutter);
	border-bottom: 1px solid var(--fx-border);
	flex-shrink: 0;
}

.fx-drawer__body {
	flex: 1 1 auto;
	overflow-y: auto;
	overscroll-behavior: contain;
	padding: 16px var(--fx-gutter);
}

.fx-drawer__foot {
	flex-shrink: 0;
	padding: 16px var(--fx-gutter);
	border-top: 1px solid var(--fx-border);
	padding-bottom: calc(16px + env(safe-area-inset-bottom));
}

@keyframes fx-fade-in  { from { opacity: 0; } to { opacity: 1; } }
@keyframes fx-fade-out { from { opacity: 1; } to { opacity: 0; } }
@keyframes fx-slide-in { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
@keyframes fx-slide-up { from { transform: translateY(100%); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
@keyframes fx-panel-out { from { transform: translateX(0); opacity: 1; } to { transform: translateX(24px); opacity: 0; } }
@keyframes fx-sheet-out { from { transform: translateY(0); opacity: 1; } to { transform: translateY(24px); opacity: 0; } }

/* Lock the page behind an open overlay without losing scroll position. */
body.fx-locked {
	overflow: hidden;
}

/* ------------------------------------------------------- sticky action bar */

.fx-sticky-cta {
	position: fixed;
	bottom: 58px;
	inset-inline: 0;
	z-index: var(--fx-z-sticky);
	max-width: var(--fx-shell-mobile);
	margin-inline: auto;
	padding: 12px var(--fx-gutter);
	background: var(--fx-paper);
	box-shadow: var(--fx-shadow-sticky);
}

@media (min-width: 768px) {
	.fx-sticky-cta {
		display: none;
	}
}

/* ------------------------------------------------------------- skeletons */

.fx-skeleton {
	position: relative;
	overflow: hidden;
	background: var(--fx-surface-muted);
}

.fx-skeleton::after {
	content: "";
	position: absolute;
	inset: 0;
	transform: translateX(-100%);
	background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .6), transparent);
	animation: fx-shimmer 1.4s infinite;
}

@keyframes fx-shimmer {
	to { transform: translateX(100%); }
}

/* ------------------------------------------------------------ nudge hint */
/*
 * One shot, a second after load: shows that a rail scrolls sideways.
 *
 * It must NOT be a transform on the scroll container itself. Translating the
 * whole rail slides its first card out past the left gutter and clips the
 * badge, which looks like a layout bug rather than a hint — and a full-page
 * screenshot taken mid-animation captures it permanently.
 *
 * Applied to the last child instead: the far end of the rail twitches, which
 * points in the direction there is more to see, and nothing leaves the frame.
 */
.fx-nudge > *:last-child {
	animation: fx-nudge 1.5s var(--fx-ease) 1s 1;
}

@keyframes fx-nudge {
	0%, 100% { transform: translateX(0); }
	50%      { transform: translateX(-14px); }
}

/* ----------------------------------------------------------------- notice */

.fx-notice {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	padding: 12px 14px;
	background: var(--fx-sand);
	color: var(--fx-ink);
	font-size: 12px;
	line-height: 1.5;
}

.fx-notice--error {
	background: #FBECEC;
}

.fx-notice--success {
	background: #E8F3EC;
}
