/**
 * {CODICTS} Buyback Deduction Engine - frontend widget styles.
 *
 * These render on the SITE's surface, which is normally light. Nothing here
 * borrows the dark admin tokens (Bible 7.8): colours are neutral, low contrast
 * against white, and every one of them is a CSS custom property so an Elementor
 * style control (or a theme) overrides it without a specificity fight.
 *
 * Specificity is kept to one class on purpose so `{{WRAPPER}} .cbde-option`
 * from the widget controls always wins.
 */

.cbde-selector,
.cbde-price,
.cbde-summary,
.cbde-submit {
	--cbde-text: #1f2937;
	--cbde-text-muted: #6b7280;
	--cbde-border: #d1d5db;
	--cbde-border-strong: #111827;
	--cbde-surface: #ffffff;
	--cbde-surface-hover: #f9fafb;
	--cbde-accent: #111827;
	--cbde-radius: 8px;
	--cbde-gap: 10px;

	color: var(--cbde-text);
	box-sizing: border-box;
}

.cbde-selector *,
.cbde-price *,
.cbde-summary *,
.cbde-submit * {
	box-sizing: inherit;
}

/* Hidden by the engine. Wins over an inline display, deliberately. */
.cbde-hidden {
	display: none !important;
}

/*
 * A selector that rendered no options at all, left on the page only to carry a
 * parking instruction. It has nothing inside it and nothing to show.
 */
.cbde-selector--empty {
	display: none;
}

/* ------------------------------------------------------------- selector */

.cbde-options {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--cbde-gap);
}

.cbde-option {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 12px 14px;
	border: 1px solid var(--cbde-border);
	border-radius: var(--cbde-radius);
	background: var(--cbde-surface);
	cursor: pointer;
	transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease;
	min-width: 0;
}

.cbde-option:hover {
	background: var(--cbde-surface-hover);
}

/*
 * A SELECTED OPTION IS OUTLINED BY ITS BORDER, AND ONLY BY ITS BORDER.
 *
 * This used to draw the outline twice: the border-color below, plus an inset
 * 1px box-shadow to make it read as thicker without reflowing the row. The
 * shadow is a fake border, and Elementor's Border control only ever writes
 * border-style, border-width and border-color - so setting Border Type to None
 * on the Selected tab removed the real border and left the fake one sitting
 * there, with nothing in the panel able to touch it.
 *
 * Anyone who wants the heavier ring back has the Box Shadow control on that
 * same tab, which is where a shadow belongs.
 */
.cbde-option.is-selected {
	border-color: var(--cbde-border-strong);
}

.cbde-option.is-unavailable {
	opacity: .45;
	cursor: not-allowed;
}

/* The native control drives state; the visible indicator is the span. */
.cbde-option-input {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	border: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
}

.cbde-option-indicator {
	flex: 0 0 auto;
	width: 18px;
	height: 18px;
	border: 2px solid var(--cbde-border);
	border-radius: 50%;
	background: transparent;
	position: relative;
	transition: border-color .15s ease, background-color .15s ease;
}

.cbde-option.is-selected .cbde-option-indicator {
	border-color: var(--cbde-accent);
	background: var(--cbde-accent);
	box-shadow: inset 0 0 0 3px var(--cbde-surface);
}

.cbde-selector--checkbox .cbde-option-indicator {
	border-radius: 4px;
}

.cbde-selector--no-indicator .cbde-option-indicator {
	display: none;
}

.cbde-option-body {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
}

.cbde-option-label {
	font-weight: 600;
	line-height: 1.3;
}

.cbde-option-desc {
	font-size: .85em;
	color: var(--cbde-text-muted);
	line-height: 1.35;
}

/* Buttons variant: same markup, centred and pill shaped. */
.cbde-selector--buttons .cbde-option {
	justify-content: center;
	text-align: center;
	border-radius: 999px;
}

.cbde-selector--buttons .cbde-option-indicator {
	display: none;
}

.cbde-selector--buttons .cbde-option.is-selected {
	background: var(--cbde-accent);
	color: var(--cbde-surface);
}

.cbde-selector--buttons .cbde-option.is-selected .cbde-option-label {
	color: inherit;
}

.cbde-select {
	width: 100%;
	padding: 10px 12px;
	border: 1px solid var(--cbde-border);
	border-radius: var(--cbde-radius);
	background: var(--cbde-surface);
	color: inherit;
	font: inherit;
	line-height: 1.3;
}

.cbde-select option.is-unavailable {
	color: var(--cbde-text-muted);
}

/* ---------------------------------------------------------------- price */

.cbde-price {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: 6px;
}

.cbde-price-value {
	display: inline-flex;
	align-items: baseline;
	font-weight: 700;
	font-size: 1.6em;
	line-height: 1.1;
}

.cbde-price-value .currency {
	font-size: .7em;
	margin-right: 2px;
}

/* Only while the number is counting. See count() in engine.js. */
.cbde-price-value.is-counting .amount {
	font-variant-numeric: tabular-nums;
	font-feature-settings: "tnum";
}

.cbde-price-prefix,
.cbde-price-suffix {
	color: var(--cbde-text-muted);
	font-size: .9em;
}

.cbde-price-fallback {
	color: var(--cbde-text-muted);
	font-size: .95em;
}

/* Kept from 1.x: existing templates hook this class name. */
.codicts-price-animate,
.cbde-price.codicts-price-animate {
	animation: cbde-pop var(--cbde-price-anim, .35s) ease;
}

/*
 * The settled quote, for screen readers only.
 *
 * The counting / fading / sliding styles take the visible number out of the
 * accessibility tree while it moves and put the finished value in here instead,
 * so the quote is announced once per change rather than once per frame.
 */
.cbde-price-sr {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	border: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
}

@keyframes cbde-pop {
	0%   { transform: scale(.96); opacity: .6; }
	60%  { transform: scale(1.02); opacity: 1; }
	100% { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
	.codicts-price-animate,
	.cbde-price.codicts-price-animate {
		animation: none;
	}
}

/* -------------------------------------------------------------- summary */

.cbde-summary-body {
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.cbde-summary-row {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 16px;
}

.cbde-summary-label {
	min-width: 0;
}

.cbde-summary-value {
	flex: 0 0 auto;
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}

.cbde-summary-row--deduction {
	color: var(--cbde-text-muted);
}

/*
 * A line that gives money back rather than taking it: the cap refusing to
 * deduct any more, or the floor refusing to let the quote fall further. It reads
 * as part of the same subtraction, so it is styled like a deduction rather than
 * shouting - the plus sign in front of it is the whole difference.
 */
.cbde-summary-row--adjustment {
	color: var(--cbde-text-muted);
}

.cbde-summary-row--total {
	margin-top: 6px;
	padding-top: 8px;
	border-top: 1px solid var(--cbde-border);
	font-weight: 700;
}

.cbde-summary-note,
.cbde-summary-empty {
	font-size: .85em;
	color: var(--cbde-text-muted);
}

/* --------------------------------------------------------------- submit */

/*
 * Why the button is off. Sits under it, appears on hover or press, and is
 * deliberately quiet: the visitor has not done anything wrong, they have just
 * not finished. Styled as guidance rather than as an error for that reason.
 */
.cbde-submit-hint {
	margin-top: 8px;
	font-size: .85em;
	line-height: 1.45;
	color: var(--cbde-text-muted);
}

/*
 * A question that is still waiting, once somebody has PRESSED a button that is
 * not ready. Nothing before that: until they try, they have not skipped
 * anything, and marking every unanswered question on arrival reads as a page
 * full of mistakes.
 *
 * IT IS A COLOUR, NOT A BOX. An outline round a question that is already a
 * bordered control reads as a form error and redraws the page under somebody
 * who has only pressed a button. What gets marked is the HEADING - the words
 * naming the question, where the reader's eye already is.
 *
 * The colour is set per element by the Submit widget, because what it paints
 * belongs to OTHER widgets and Elementor can only scope CSS to its own. Red is
 * the fallback, not the decision.
 *
 * `!important` for the same reason: the heading is nearly always somebody
 * else's widget, and Elementor writes its colour as
 * `.elementor-widget-heading .elementor-heading-title` - two classes, which
 * beats an element selector. Without it the words stayed exactly as dark as
 * before, which is the one thing this is for.
 */
.cbde-required-pending,
/*
 * THE LABEL COUNTS AS A HEADING HERE. On a tick box the label IS the
 * question - there is no heading above it to turn - so an unticked agreement
 * was marked in a way that showed nothing at all.
 */
.cbde-required-pending .cbde-option-label,
.cbde-required-pending .cbde-rule-title,
.cbde-required-pending .elementor-heading-title,
.cbde-required-pending h1,
.cbde-required-pending h2,
.cbde-required-pending h3,
.cbde-required-pending h4,
.cbde-required-pending h5,
.cbde-required-pending h6 {
	color: var(--cbde-required-color, #dc2626) !important;
}

/*
 * And the box, so an unticked agreement is visibly the thing being asked for
 * rather than a red sentence beside a control that looks exactly as it did.
 * Only while it is EMPTY: once ticked it is answered, whatever else is not.
 */
.cbde-required-pending .cbde-option:not(.is-selected) .cbde-option-indicator {
	border-color: var(--cbde-required-color, #dc2626) !important;
}

.cbde-submit {
	display: flex;
	flex-direction: column;
}

.cbde-submit-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 12px 22px;
	border: 1px solid var(--cbde-accent);
	border-radius: var(--cbde-radius);
	background: var(--cbde-accent);
	color: #ffffff;
	font: inherit;
	font-weight: 600;
	text-decoration: none;
	cursor: pointer;
	transition: opacity .15s ease, background-color .15s ease;
}

.cbde-submit-btn:hover {
	color: #ffffff;
}

/*
 * Icon and label are siblings HERE, not inside the button - the button has this
 * one child. The Icon spacing control writes its gap onto this element, so it
 * has to be a flex container or the control silently does nothing.
 */
.cbde-submit-btn-inner {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
}

.cbde-submit-btn-icon {
	display: inline-flex;
	align-items: center;
	line-height: 0;
}

.cbde-submit-btn-icon svg {
	width: 1em;
	height: 1em;
	fill: currentColor;
}

.cbde-submit-btn.cbde-is-disabled,
.cbde-submit-btn[disabled] {
	opacity: .55;
	cursor: not-allowed;
	pointer-events: none;
}

/* ---------------------------------------------------------- editor note */

.cbde-editor-note {
	padding: 8px 12px;
	font: 13px/1.4 system-ui, -apple-system, "Segoe UI", sans-serif;
	border: 1px dashed #d1d5db;
	border-radius: 6px;
	color: #6b7280;
	background: #ffffff;
}

.cbde-editor-note--warning {
	color: #b45309;
	border-color: #fcd34d;
}

.cbde-editor-note--ok {
	color: #047857;
	border-color: #6ee7b7;
}

/*
 * Two pricing rows carrying the same storage term: the option cannot resolve to
 * one row, so the lowest row id wins and the other price is unreachable. The
 * markup has always tagged that option, but nothing styled the class, so the
 * warning rendered invisibly. The Data Provider widget used to report it in the
 * editor; it was removed in 3.0.0, leaving this as the only signal.
 *
 * Editor only, deliberately. This is a data problem for whoever builds the page,
 * and a buyer should never see the calculator commenting on its own wiring.
 */
body.elementor-editor-active .cbde-option--shared-variant {
	outline: 2px dashed #f6ad3d;
	outline-offset: 2px;
	position: relative;
}

body.elementor-editor-active .cbde-option--shared-variant::after {
	content: "shares a pricing row";
	position: absolute;
	top: -0.65rem;
	right: 0.4rem;
	padding: 0 0.35rem;
	font-size: 10px;
	line-height: 1.4;
	white-space: nowrap;
	color: #7c4a03;
	background: #fcd34d;
	border-radius: 3px;
	pointer-events: none;
}

/* Text field source ------------------------------------------------------- */

/*
 * Deliberately almost nothing. Every visual choice here is an Elementor control,
 * and a default that looked "designed" would fight the theme on sites that style
 * their own inputs. Only the two things a bare input gets wrong inside a widget:
 * it does not fill its container, and its padding is added to its width.
 */
.cbde-selector--text {
	display: block;
}

input.cbde-text-input {
	box-sizing: border-box;
	width: 100%;
	max-width: 100%;
}

/*
 * A box whose entry breaks its rules. Shown only once the visitor has left it or
 * pressed Sell, so the defaults have to be visible without any styling: the same
 * red the Sell button uses to mark what is still needed, which a site sets once.
 */
.cbde-text-error {
	margin-top: 6px;
	font-size: .875em;
	color: var(--cbde-required-color, #dc2626);
}

.cbde-text-invalid input.cbde-text-input {
	border-color: var(--cbde-required-color, #dc2626);
}

/* Rules widget ------------------------------------------------------------ */

/*
 * Same restraint as everything above: the stack is a flex column so the "Gap
 * between rules" control has something to act on, and the title and description
 * only get their browser margins cleared so the spacing controls start from
 * zero rather than from a heading default that differs per theme. Every colour,
 * size and weight is an Elementor control.
 */
.cbde-rules {
	display: flex;
	flex-direction: column;
}

.cbde-rule-title,
.cbde-rule-desc {
	margin-top: 0;
}

