/*
 * tap-system.css — the DIVSA design system layer.
 *
 * WHY THIS FILE EXISTS
 * --------------------
 * The frontend grew section by section, and each section brought its own
 * geometry. Audited live on the homepage at 1425px, 2026-08-28:
 *
 *   card border-radius   7 distinct values   12 / 14 / 16 / 20 / 22 / 24 / 999
 *   card box-shadow      7 distinct values   0 2px 10px … 0 16px 40px
 *   card padding         6 distinct values   18px 20px 10px, 14px 16px, …
 *   button height        4 distinct values   44 / 48 / 50 / 99
 *   button radius        4 distinct values   4 / 12 / 14 / 999
 *   button typography    6 distinct values   14/700, 16/400, 12/800, …
 *   eyebrow tracking     2 distinct values   1.92px / 1.2px
 *   section title        2 distinct values   26px / 24px
 *   icon size            6 distinct values   14 / 20 / 22 / 26 / 30 / 34
 *
 * None of those values is wrong on its own. Having seven of each is the
 * problem: it is what makes a page read as assembled rather than designed.
 *
 * This file is a SCALE, not a patch. It defines one set of tokens and maps
 * the existing component classes onto them. It is registered last so it is
 * the single place geometry is decided; a component stylesheet keeps owning
 * its layout and behaviour, and stops owning its own radius and elevation.
 *
 * It deliberately does NOT touch brand colour. --tap-purple, --tap-marigold
 * and the rest stay exactly as the operator set them.
 *
 * @package DIVSA_OS
 * @since   8.6.29
 */

/* ==========================================================================
   1. TOKENS
   ========================================================================== */
.tap-root,
.tap-home-root,
.tap-chrome-header,
.tap-chrome-footer,
.tap-app-shell{
	/* --- Radius: four steps, not seven ------------------------------------
	   sm  chips, badges, small controls
	   md  buttons, inputs, icon tiles
	   lg  cards, sheets, media
	   pill fully rounded controls                                        */
	--ds-radius-sm: 10px;
	/*
	 * Control corner: also an operator setting (--tap-btn-radius, from Brand
	 * & Theme). This site has it at 4px; hardcoding 14px here would have
	 * quietly overruled that choice on every button while leaving the store's
	 * own buttons at 4px — inconsistency introduced by the layer meant to
	 * remove it. Same principle as --ds-radius-lg: derive, do not decide.
	 */
	--ds-radius-md: var(--tap-btn-radius, 14px);
	/*
	 * The card corner is an OPERATOR setting, not a designer's constant:
	 * TAP_Layout already emits --tap-card-radius from Cards & Layout →
	 * card radius. Deriving from it means the service card and the store
	 * card land on the same number because they read the same control —
	 * consistency by construction rather than by two hardcoded values that
	 * happen to agree until someone edits one of them.
	 */
	--ds-radius-lg: var(--tap-card-radius, 18px);
	--ds-radius-pill: 999px;

	/* --- Elevation: three steps, all restrained ---------------------------
	   The audit found a 0 16px 40px shadow on a 134px card — an elevation
	   deeper than the object casting it. Premium surfaces sit close to the
	   page; they do not hover above it.                                   */
	--ds-shadow-0: none;
	--ds-shadow-1:
		0 1px 2px color-mix(in srgb, var(--tap-ink) 5%, transparent);
	--ds-shadow-2:
		0 1px 2px color-mix(in srgb, var(--tap-ink) 4%, transparent),
		0 4px 14px color-mix(in srgb, var(--tap-ink) 4%, transparent);
	--ds-shadow-3:
		0 2px 4px color-mix(in srgb, var(--tap-ink) 5%, transparent),
		0 10px 26px color-mix(in srgb, var(--tap-ink) 6%, transparent);

	/* --- Space: one 4px-based scale --------------------------------------- */
	--ds-space-1: 4px;
	--ds-space-2: 8px;
	--ds-space-3: 12px;
	--ds-space-4: 16px;
	--ds-space-5: 20px;
	--ds-space-6: 24px;
	--ds-space-8: 32px;

	/* --- Section rhythm ---------------------------------------------------
	   One vertical beat for every band on a page. The audit found four
	   different values stacked on the same property (0 / 24 / 32 / 34), set
	   across five rules in three files — which is why the page read as a
	   stack of unrelated strips rather than one document.

	   The operator still owns the number: TAP_Layout emits this token from
	   Cards & Layout -> section padding, using that value as the FLOOR and
	   letting it open up on wider screens. The value below is only the
	   fallback for sites that never set one.                              */
	--ds-section-y: clamp(28px, 3.4vw, 48px);

	/* --- Controls ---------------------------------------------------------
	   48px on a phone is the comfortable primary height the brief asks for;
	   44px is the floor for secondary and inline controls.                */
	--ds-control-h: 48px;
	--ds-control-h-sm: 44px;
	--ds-control-pad-x: 22px;

	/* --- Icons: three sizes ----------------------------------------------- */
	--ds-icon-sm: 16px;
	--ds-icon-md: 20px;
	--ds-icon-lg: 26px;

	/* --- Focus ------------------------------------------------------------ */
	--ds-focus: 0 0 0 3px color-mix(in srgb, var(--tap-primary) 30%, transparent);
}

/* ==========================================================================
   2. BUTTONS — one system, three roles

   Primary    booking, payment, the one conversion action on a screen
   Secondary  view details, support, explore — soft/outline
   Tertiary   see all, learn more — a text link with a target area

   Existing component classes are mapped onto these rather than renamed, so
   no template changes and no second button vocabulary.
   ========================================================================== */

/*
 * .tap-vfilter__go is deliberately NOT in the lists below.
 *
 * It is the Search control seated inside the pill-shaped filter field, and
 * the field owns its geometry: a 999px corner and the field's inner height.
 * Handing it the generic control shape gave it --ds-radius-md (this site's
 * 4px) at 48px tall inside a 58px pill with 4px of padding — a square orange
 * block sticking out of a rounded input, which is exactly how it shipped.
 *
 * A control inside a shaped container inherits that container's shape. The
 * component sheet already had this right; the system layer's job here is to
 * stay out of the way.
 */
/* -- shared shape -------------------------------------------------------- */
.tap-app-shell.tap-app-shell .tap-btn,
.tap-app-shell.tap-app-shell .tap-cta,
.tap-app-shell.tap-app-shell .tap-fcard-cta,
.tap-chrome-header.tap-chrome-header .tap-chrome-cta,
.tap-home-root.tap-home-root .tap-vertical-empty__link{
	display:inline-flex; align-items:center; justify-content:center;
	gap:var(--ds-space-2);
	min-block-size:var(--ds-control-h);
	padding-inline:var(--ds-control-pad-x);
	border-radius:var(--ds-radius-md);
	border:1px solid transparent;
	font-family:var(--tap-font-body);
	font-size:15px;
	font-weight:700;
	line-height:1.1;
	letter-spacing:.005em;
	text-decoration:none;
	cursor:pointer;
	/* A control must never be the thing that makes a card taller. */
	max-inline-size:100%;
	transition:
		background-color var(--tap-motion-quick, 160ms) var(--tap-ease-standard, ease),
		border-color var(--tap-motion-quick, 160ms) var(--tap-ease-standard, ease),
		color var(--tap-motion-quick, 160ms) var(--tap-ease-standard, ease),
		transform 90ms var(--tap-ease-standard, ease),
		box-shadow var(--tap-motion-quick, 160ms) var(--tap-ease-standard, ease);
}

/* Icons inside a button share one size and never shrink. */
.tap-app-shell.tap-app-shell .tap-btn svg,
.tap-app-shell.tap-app-shell .tap-cta svg,
.tap-app-shell.tap-app-shell .tap-fcard-cta svg,
.tap-chrome-header.tap-chrome-header .tap-chrome-cta svg{
	inline-size:var(--ds-icon-md); block-size:var(--ds-icon-md);
	flex:0 0 auto;
}

/* -- primary ------------------------------------------------------------- */
.tap-app-shell.tap-app-shell .tap-btn-primary,
.tap-app-shell.tap-app-shell .tap-fcard-cta,
.tap-chrome-header.tap-chrome-header .tap-chrome-cta,
.tap-home-root.tap-home-root .tap-vertical-empty__link.is-primary{
	background:var(--tap-cta, var(--tap-primary));
	color:var(--tap-cta-text, #fff);
	box-shadow:var(--ds-shadow-1);
}
.tap-app-shell.tap-app-shell .tap-btn-primary:hover,
.tap-app-shell.tap-app-shell .tap-fcard-cta:hover,
.tap-chrome-header.tap-chrome-header .tap-chrome-cta:hover{
	background:color-mix(in srgb, var(--tap-cta, var(--tap-primary)) 88%, var(--tap-ink));
	box-shadow:var(--ds-shadow-2);
}

/* -- secondary ----------------------------------------------------------- */
.tap-app-shell.tap-app-shell .tap-btn-ghost,
.tap-app-shell.tap-app-shell .tap-btn-secondary,
.tap-home-root.tap-home-root .tap-vertical-empty__link{
	background:var(--tap-card, #fff);
	color:var(--tap-ink);
	border-color:var(--tap-line);
	box-shadow:none;
}
.tap-app-shell.tap-app-shell .tap-btn-ghost:hover,
.tap-app-shell.tap-app-shell .tap-btn-secondary:hover,
.tap-home-root.tap-home-root .tap-vertical-empty__link:hover{
	border-color:var(--tap-primary);
	color:var(--tap-primary);
	background:color-mix(in srgb, var(--tap-primary) 5%, var(--tap-card, #fff));
}

/* -- tertiary — the "See all ›" links ------------------------------------ */
.tap-app-shell.tap-app-shell .tap-sec-action,
.tap-home-root.tap-home-root .tap-sec-action{
	display:inline-flex; align-items:center; gap:6px;
	min-block-size:var(--ds-control-h-sm);
	padding-inline:var(--ds-space-2);
	border-radius:var(--ds-radius-sm);
	font-family:var(--tap-font-body);
	font-size:14px; font-weight:700;
	color:var(--tap-primary);
	text-decoration:none;
	background:none; border:0;
}
.tap-app-shell.tap-app-shell .tap-sec-action:hover{
	color:color-mix(in srgb, var(--tap-primary) 84%, var(--tap-ink));
	background:color-mix(in srgb, var(--tap-primary) 6%, transparent);
}

/* -- states -------------------------------------------------------------- */
.tap-app-shell.tap-app-shell .tap-btn:active,
.tap-app-shell.tap-app-shell .tap-cta:active,
.tap-app-shell.tap-app-shell .tap-fcard-cta:active,
.tap-chrome-header.tap-chrome-header .tap-chrome-cta:active{
	/* A press should be felt, not watched. */
	transform:translateY(1px);
	box-shadow:var(--ds-shadow-1);
}
.tap-app-shell.tap-app-shell .tap-btn:focus-visible,
.tap-app-shell.tap-app-shell .tap-cta:focus-visible,
.tap-app-shell.tap-app-shell .tap-fcard-cta:focus-visible,
.tap-app-shell.tap-app-shell .tap-sec-action:focus-visible,
.tap-chrome-header.tap-chrome-header .tap-chrome-cta:focus-visible,
.tap-home-root.tap-home-root .tap-vertical-empty__link:focus-visible{
	outline:2px solid var(--tap-primary);
	outline-offset:2px;
	box-shadow:var(--ds-focus);
}
.tap-app-shell.tap-app-shell .tap-btn[disabled],
.tap-app-shell.tap-app-shell .tap-btn[aria-disabled="true"],
.tap-app-shell.tap-app-shell .tap-cta[disabled],
.tap-root button[disabled]{
	opacity:.5;
	cursor:not-allowed;
	transform:none;
	box-shadow:none;
	/* Nothing should react to a pointer it cannot serve. */
	pointer-events:none;
}
/* A button mid-request must look busy and must not accept a second press —
   the cheapest guard there is against a double booking or double payment. */
.tap-app-shell.tap-app-shell .is-loading,
.tap-root [data-loading="1"]{
	pointer-events:none;
	position:relative;
	color:transparent!important;
}
.tap-app-shell.tap-app-shell .is-loading::after,
.tap-root [data-loading="1"]::after{
	content:"";
	position:absolute; inset-block-start:50%; inset-inline-start:50%;
	inline-size:18px; block-size:18px; margin:-9px 0 0 -9px;
	border-radius:50%;
	border:2px solid color-mix(in srgb, currentColor 30%, transparent);
	border-block-start-color:var(--tap-cta-text, #fff);
	animation:ds-spin .7s linear infinite;
}
@keyframes ds-spin{to{transform:rotate(360deg)}}

/* Phone: the primary action gets the comfortable height the brief asks for. */
@media (max-width:767.98px){
	.tap-app-shell.tap-app-shell .tap-btn-primary,
	.tap-app-shell.tap-app-shell .tap-fcard-cta,
	.tap-app-shell.tap-app-shell .tap-cta{min-block-size:50px; font-size:15px}
}

/* ==========================================================================
   3. THE BOTTOM STACK — the booking action is never covered

   Audited on a 375×812 phone, puja detail page, 2026-08-28:

     .tap-sticky   (Book CTA)   y732–802   z 40   bottom:10px
     .tap-bottomnav             y739–812   z 70   bottom:0, 73px tall
     .tap-wa-fab   (WhatsApp)   y750–796   z 80   bottom:16px

   document.elementFromPoint() at the CTA's own centre returned the WhatsApp
   icon. On a phone, tapping the middle of "Book" opened WhatsApp.

   The plugin's design was already right: tap-shell.css lifts the CTA above
   the nav for `body.tap-has-active-nav`, and hides the FAB for
   `body.tap-has-transaction-sticky`. Both classes — and
   --tap-bottom-nav-h — are written by measure() in tap-chrome.js, which on
   this page reports 0 for a nav that is really 73px and a CTA that is
   really 70px. The SPA builds the CTA after that measurement runs, and it
   does not run again.

   So the rules below do not ask JavaScript anything. They key off classes
   the SERVER renders (tap-has-bottomnav, tap-nav-mobile, tap-puja-canvas)
   and use max(), so a correct measurement still wins and a missing one
   cannot put the primary action underneath the navigation.
   ========================================================================== */
.tap-app-shell.tap-app-shell,
.tap-app-shell{
	/* Floor for the bottom navigation: 72px of bar plus the home indicator.
	   Only used when the measured value is missing or smaller. */
	--ds-nav-h: 72px;
}

@media (max-width:1023.98px){
	body.tap-has-bottomnav.tap-nav-mobile .tap-root .tap-sticky,
	body.tap-has-bottomnav.tap-nav-mobile .tap-sam-sticky-buy{
		inset-block-end:max(
			calc(var(--tap-bottom-nav-h, 0px) + var(--tap-fixed-gap, 10px)),
			calc(var(--ds-nav-h) + var(--tap-safe-bottom, 0px) + var(--tap-fixed-gap, 10px))
		)!important;
	}
}

/*
 * A floating chat button must not compete with — let alone sit on top of —
 * the one action the screen exists for. tap-shell.css already says this for
 * .tap-has-transaction-sticky; tap-puja-canvas is the server-rendered class
 * that means the same thing and is always present on a booking page.
 */
body.tap-puja-canvas :is(.tap-wa-fab, #tap-wa-float){display:none!important}

/* ==========================================================================
   4. SURFACES — one radius and one elevation ladder for every card
   ========================================================================== */
/*
 * `!important` is deliberate and is confined to this block.
 *
 * Radius and elevation are the two properties this layer exists to own, and
 * several component sheets set them from selectors deeper than any sane
 * scoping here could out-specify — after one round of raising specificity,
 * nine of seventeen service cards still kept a 22px corner and a
 * 0 12px 32px shadow while the other eight took the token. The alternative
 * is a specificity arms race that the next component to be written wins
 * again. One documented override in the system layer is the smaller cost.
 *
 * It applies to geometry ONLY. Colour, layout and behaviour stay with the
 * components.
 */
.tap-app-shell.tap-app-shell .tap-fcard,
.tap-app-shell.tap-app-shell .tap-pcard,
.tap-app-shell.tap-app-shell .tap-sam-card,
.tap-home-root.tap-home-root .tap-home-trust-card,
.tap-home-root.tap-home-root .tap-home-step,
.tap-app-shell.tap-app-shell .tap-addon-card,
.tap-app-shell.tap-app-shell .tap-plan-card{
	border-radius:var(--ds-radius-lg)!important;
	box-shadow:var(--ds-shadow-2)!important;
	border:1px solid color-mix(in srgb, var(--tap-line) 72%, transparent);
	background:var(--tap-card, #fff);
}
/*
 * A button label is a label: it stays on its line and the type steps down
 * before the box grows.
 *
 * .tap-sam-card-add is the store card's footer WRAPPER, not a control, and
 * it is deliberately absent from every rule above. It was briefly included,
 * which painted the primary background across the whole strip and left the
 * store's own button sitting inside an orange band. The control is
 * .tap-sam-cta; the store owns its colour, this layer only sizes the label.
 */
.tap-app-shell.tap-app-shell .tap-sam-cta{
	white-space:nowrap;
	font-size:clamp(13px, 2.6vw, 15px);
}
/* Desktop hover: a small, single, consistent lift. */
@media (hover:hover) and (min-width:768px){
	.tap-app-shell.tap-app-shell .tap-fcard:hover,
	.tap-app-shell.tap-app-shell .tap-pcard:hover,
	.tap-app-shell.tap-app-shell .tap-sam-card:hover,
	.tap-home-root.tap-home-root .tap-home-trust-card:hover{
		box-shadow:var(--ds-shadow-3);
		border-color:color-mix(in srgb, var(--tap-line) 100%, transparent);
	}
}
/*
 * Fitted media must fill its aspect-ratio box.
 *
 * tap-layout.css carries a global responsive guard,
 *   .tap-responsive-smart .tap-app-shell img { height: auto }
 * at (0,2,1). The store asks for height:100% at (0,2,0), so the guard wins:
 * measured on a phone, .tap-sam-art is a 177×133 box holding a 177×177 image
 * (one product 177×204). overflow:hidden then crops 33–53% off the bottom of
 * every product photo, by a different amount per product — which is what made
 * the store grid look ragged. object-fit:contain never got a chance to run,
 * because the element it was meant to fit was never sized.
 *
 * NOTE ON SCOPE: the store card is NOT inside .tap-root — its chain is
 * .tap-app-shell › .tap-shell-container › .tap-sam › .tap-sam-card. Rules in
 * this file scoped to .tap-root therefore never reached it (the tokens did,
 * because custom properties inherit). .tap-app-shell is the real common
 * ancestor of both trees, so fitted media is scoped there.
 *
 * contain, not cover, for products: a yantra or a mala must be shown whole,
 * not cropped to fill a box.
 */
.tap-app-shell.tap-app-shell .tap-sam-art img{
	inline-size:100%;
	block-size:100%;
	object-fit:contain;
	object-position:center;
	display:block;
}

/* Media inside a card follows the card's corner, one step tighter. */
.tap-app-shell.tap-app-shell .tap-fcard-art,
.tap-app-shell.tap-app-shell .tap-sam-card-media{
	border-radius:calc(var(--ds-radius-lg) - 4px);
	overflow:hidden;
}
.tap-app-shell.tap-app-shell .tap-fcard-media,
.tap-app-shell.tap-app-shell .tap-sam-card img{
	inline-size:100%; block-size:100%;
	object-fit:cover;
	/* Faces and deities sit high in devotional artwork. */
	object-position:center 32%;
	display:block;
}

/* ==========================================================================
   4. TYPE — one scale for the shared roles
   ========================================================================== */
.tap-app-shell.tap-app-shell .tap-sec-eyebrow,
.tap-home-root.tap-home-root .tap-sec-eyebrow{
	font-family:var(--tap-font-body);
	font-size:12px;
	font-weight:800;
	/* Was 1.92px in one place and 1.2px in another. */
	letter-spacing:.14em;
	text-transform:uppercase;
	line-height:1.2;
}
.tap-app-shell.tap-app-shell .tap-sec-title,
.tap-home-root.tap-home-root .tap-sec-title{
	font-family:var(--tap-font-display, var(--tap-font-heading));
	font-size:clamp(24px, 3.2vw, 40px);
	font-weight:600;
	line-height:1.1;
	letter-spacing:-.025em;
	margin-block-start:6px;
}
/* Card titles are titles, not paragraphs: two lines, then an ellipsis. */
.tap-app-shell.tap-app-shell .tap-fcard-name,
.tap-app-shell.tap-app-shell .tap-sam-card-title,
.tap-home-root.tap-home-root .tap-home-trust-card h3,
.tap-home-root.tap-home-root .tap-home-why-card h3{
	font-family:var(--tap-font-body);
	font-size:15.5px;
	font-weight:700;
	line-height:1.3;
	letter-spacing:-.005em;
	/*
	 * Two lines, cut cleanly.
	 *
	 * The existing rule asked for -webkit-line-clamp:2 with
	 * -webkit-box-orient:vertical, which needs display:-webkit-box. Measured
	 * live: setting display:-webkit-box !important on this element still
	 * computes to `flow-root` in current Chrome, whether or not the parent is
	 * a flex container. So the clamp never engaged and the bare
	 * overflow:hidden sliced the third line THROUGH the middle of it — a
	 * 43px box over 64px of text, with no ellipsis:
	 *
	 *   "Shri Krishna Janmashtami Special Janmotsav Mahapoo"
	 *
	 * A line-height-relative height cap does not depend on -webkit-box, so it
	 * works everywhere: the box ends exactly on a line boundary. `lh` is the
	 * precise unit for this; the em calc above it covers engines without it.
	 * The clamp properties stay so the ellipsis appears wherever the legacy
	 * path IS honoured.
	 */
	display:-webkit-box;
	-webkit-line-clamp:2;
	-webkit-box-orient:vertical;
	line-clamp:2;
	overflow:hidden;
	max-block-size:calc(2 * 1.3em);
	max-block-size:2lh;
	text-wrap:balance;
}
.tap-app-shell.tap-app-shell .tap-fcard-summary,
.tap-home-root.tap-home-root .tap-home-trust-card p,
.tap-home-root.tap-home-root .tap-home-why-card p{
	font-size:13.5px;
	line-height:1.55;
	color:var(--tap-muted);
	/* Readability measure — long lines are the other way text stops working. */
	max-inline-size:62ch;
}

/* ==========================================================================
   5. ICONS — the audit found six sizes at one stroke weight. Keep the stroke,
   settle the sizes. Explicit width/height attributes on the SVG still win
   where a component genuinely needs a bespoke size.
   ========================================================================== */
.tap-app-shell.tap-app-shell .tap-sec-action svg,
.tap-app-shell.tap-app-shell .tap-vchip svg{
	inline-size:var(--ds-icon-sm); block-size:var(--ds-icon-sm);
	flex:0 0 auto;
}

/* ==========================================================================
   6. RAILS — one strong card, a deliberate peek at the next
   ========================================================================== */
@media (max-width:767.98px){
	.tap-app-shell.tap-app-shell .tap-rail,
	.tap-root [class*="-rail"]:not(.tap-review-rail){
		scroll-snap-type:x mandatory;
		scroll-padding-inline:var(--ds-space-4);
		-webkit-overflow-scrolling:touch;
		/* Vertical gestures belong to the page, not the rail. */
		touch-action:pan-x pan-y;
		overscroll-behavior-x:contain;
	}
	.tap-app-shell.tap-app-shell .tap-rail > *,
	.tap-root [class*="-rail"]:not(.tap-review-rail) > *{
		scroll-snap-align:start;
	}
}

/* ==========================================================================
   7. SKELETONS — the loading state uses the same geometry as the thing it
   stands in for, so nothing moves when the real content lands.
   ========================================================================== */
.tap-app-shell.tap-app-shell .tap-skeleton{
	border-radius:var(--ds-radius-lg);
	background:linear-gradient(100deg,
		color-mix(in srgb, var(--tap-ink) 5%, var(--tap-card)) 30%,
		color-mix(in srgb, var(--tap-ink) 9%, var(--tap-card)) 50%,
		color-mix(in srgb, var(--tap-ink) 5%, var(--tap-card)) 70%);
	background-size:220% 100%;
	animation:ds-shimmer 1.4s ease-in-out infinite;
}
@keyframes ds-shimmer{from{background-position:180% 0}to{background-position:-40% 0}}

/* ==========================================================================
   8. MOTION — every animation in this file is optional.
   ========================================================================== */
@media (prefers-reduced-motion: reduce){
	.tap-app-shell.tap-app-shell .tap-btn,
	.tap-app-shell.tap-app-shell .tap-cta,
	.tap-app-shell.tap-app-shell .tap-fcard-cta,
	.tap-app-shell.tap-app-shell .tap-fcard,
	.tap-app-shell.tap-app-shell .tap-sam-card,
	.tap-chrome-header.tap-chrome-header .tap-chrome-cta{transition:none}
	.tap-app-shell.tap-app-shell .tap-btn:active,
	.tap-app-shell.tap-app-shell .tap-cta:active,
	.tap-app-shell.tap-app-shell .tap-fcard-cta:active{transform:none}
	.tap-app-shell.tap-app-shell .is-loading::after,
	.tap-root [data-loading="1"]::after,
	.tap-app-shell.tap-app-shell .tap-skeleton{animation:none}
}

/* ==========================================================================
   9. POLISH — the pass that decides whether this reads as designed

   Measured live on the homepage, 2026-08-28, after the layer above landed:

     type variants     34   size/weight/line-height combinations on one page
     heading sizes      7   H2 at 19 / 24 / 30 / 40, H3 at 15.5 / 17 / 18
     corner radii       9   999 / 50% / 22 / 16 / 14 / 13 / 12 / 10 / 4
     badge type         5   10px/800, 11px/700, 11px/800, 11.625px/600 …
     rail control      40   px wide, below the 44px floor it sits next to

   Everything here is calibration, not new structure: no element moves, no
   section changes, no component is replaced. It settles the values that were
   each individually defensible and collectively looked unplanned.

   Nothing below invents a number the operator already owns. Sizes derive
   from --tap-fs, corners from --tap-card-radius, colour from the brand
   tokens; this file only decides how many distinct values there may be.
   ========================================================================== */

/* --- 9.1 One corner for icon tiles ---------------------------------------
   Three tiles doing the same job carried three corners: 16px on the service
   junction, 13px on Why, 12px on Trust. A tile is a smaller surface than the
   card it sits in, so it derives from the card corner rather than competing
   with it — change the operator's card radius and every tile follows.       */
.tap-app-shell.tap-app-shell,
.tap-home-root.tap-home-root{
	--ds-radius-tile: max(8px, calc(var(--ds-radius-lg) - 2px));
}
.tap-home-root.tap-home-root .tap-service-junction__icon,
.tap-home-root.tap-home-root .tap-home-why-icon,
.tap-home-root.tap-home-root .tap-home-trust-icon,
.tap-home-root.tap-home-root .tap-home-step-num{
	border-radius:var(--ds-radius-tile);
}

/* --- 9.2 One corner for large surfaces -----------------------------------
   22px on the service-junction card and the closing occasion card against
   14px on every puja card. The operator sets one card radius; these read it
   too now. The store card is deliberately not listed: section 4 already
   owns it, and repeating a selector is how the duplication started.        */
.tap-home-root.tap-home-root .tap-service-junction__card,
.tap-home-root.tap-home-root .tap-occasion-card{
	border-radius:var(--ds-radius-lg);
	/* 0 14px 36px on a 150px card is elevation borrowed from a modal. */
	box-shadow:var(--ds-shadow-2);
}

/* --- 9.3 One badge -------------------------------------------------------
   Five badge treatments, the smallest at 10px/800. Small-and-heavy is the
   most reliable tell of an interface that was assembled rather than set:
   under about 12px the weight stops reading as emphasis and starts reading
   as noise. One size, one weight, one tracking — and a floor that still
   scales if the operator raises the base font.                             */
/*
 * Sentence-case pills — a price cut, a stock note.
 *
 * Two things had to be right here, and the first attempt got both wrong.
 *
 * A bare floor — max(12px, .75 * --tap-fs) — has no ceiling, so it is only
 * as sensible as the base font it reads. And --tap-fs is not defined on the
 * store card at all: an undefined custom property makes the whole calc()
 * invalid at computed-value time, which for font-size means the declaration
 * is dropped and the value INHERITS. Measured live, that turned a 10px badge
 * into a 16px one — inheriting the body size — while the CSS read as though
 * it asked for 12.
 *
 * So: a band, not a floor, and a fallback on the variable so the expression
 * stays valid wherever the token has not been emitted.
 */
.tap-app-shell.tap-app-shell .tap-sam-badge,
.tap-app-shell.tap-app-shell .tap-sam-off,
.tap-home-root.tap-home-root .tap-service-junction__soon{
	font-size:clamp(12px, calc(.75 * var(--tap-fs, 16px)), 13px);
	font-weight:700;
	letter-spacing:.01em;
	line-height:1.35;
	border-radius:var(--ds-radius-pill);
}
/* Uppercase micro-labels are a different role: set in caps, they keep their
   open tracking. Only the size band is shared. (.tap-sec-eyebrow is not
   listed — section 4 already sets it, and naming it twice is the habit this
   file exists to break.) */
.tap-home-root.tap-home-root .tap-occasion-badge{
	font-size:clamp(12px, calc(.75 * var(--tap-fs, 16px)), 13px);
	line-height:1.2;
}
/* The deity label is a name, not a caption: 11.6px was below the floor. */
.tap-home-root.tap-home-root .tap-deity-name{
	font-size:clamp(12.5px, calc(.78 * var(--tap-fs, 16px)), 14px);
	line-height:1.3;
}

/* --- 9.4 Two heading levels, not four ------------------------------------
   .tap-sec-title is the section voice and already sits on one step. The
   bands that are NOT sections — the promo rail, the service junction head,
   the closing occasion card — each picked their own: 24 / 30 / 19. They are
   one role (a band title, quieter than a section) and now share one step.  */
.tap-home-root.tap-home-root .tap-promo__body h2,
.tap-home-root.tap-home-root .tap-service-junction__head h2,
.tap-home-root.tap-home-root .tap-occasion-card h2{
	font-family:var(--tap-font-display, var(--tap-font-heading));
	font-size:clamp(20px, 2.4vw, 30px);
	font-weight:600;
	line-height:1.15;
	letter-spacing:-.02em;
	text-wrap:balance;
}

/* --- 9.5 The 44px floor, kept ---------------------------------------------
   The rail arrows measured 40x44 sitting beside 44x44 controls. A control
   that is one size in one direction is a control that was never checked.   */
.tap-app-shell.tap-app-shell .tap-rail-btn{
	min-inline-size:var(--ds-control-h-sm);
	min-block-size:var(--ds-control-h-sm);
}

/* --- 9.6 One focus ring --------------------------------------------------
   Keyboard focus was drawn four ways: a 3px brand outline here, the browser
   default there, nothing at all on the rails. One ring, on the brand, with
   an offset so it never sits on the element's own edge.                    */
.tap-app-shell.tap-app-shell :is(a, button, [role="button"], input, select, textarea):focus-visible,
.tap-chrome-header.tap-chrome-header :is(a, button):focus-visible,
.tap-chrome-footer :is(a, button):focus-visible{
	outline:2px solid var(--tap-cta, var(--tap-primary));
	outline-offset:2px;
	border-radius:var(--ds-radius-sm);
}

/* --- 9.7 One motion contract ---------------------------------------------
   Hover and press were timed independently per component — 120ms here,
   160ms there, 300ms on a card. Interfaces read as expensive when every
   surface answers at the same speed. Press is faster than hover on purpose:
   a press should feel like contact, a hover like attention.                */
.tap-app-shell.tap-app-shell :is(.tap-fcard, .tap-pcard, .tap-sam-card,
	.tap-service-junction__card, .tap-home-trust-card, .tap-deity-item){
	transition:
		box-shadow var(--tap-motion-quick, 160ms) var(--tap-ease-standard, ease),
		border-color var(--tap-motion-quick, 160ms) var(--tap-ease-standard, ease),
		transform 90ms var(--tap-ease-standard, ease);
}
.tap-app-shell.tap-app-shell :is(.tap-fcard, .tap-sam-card, .tap-service-junction__card):active{
	transform:scale(.995);
}
@media (prefers-reduced-motion: reduce){
	.tap-app-shell.tap-app-shell *{
		transition-duration:1ms!important;
		animation-duration:1ms!important;
		animation-iteration-count:1!important;
		scroll-behavior:auto!important;
	}
}
