/**
 * JP Cages — Order Tracking
 *
 * Deliberately small. The theme owns the page; this styles only what the plugin
 * adds, and inherits the theme's font and colours everywhere it can.
 *
 * Brand red is #E31E24 (docs/design-system.md). jpcages.com uses #E30613 in
 * places, which is wrong about its own logo — but that is a website-wide fix,
 * not something to litigate on one page, so nothing here depends on either.
 */

.jpc-ot-header {
	/* The reported defect: the title and the user name ran together as
	   "ORDER TRACKINGJPC Admin". Flex with a gap cannot concatenate them. */
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.5rem 1rem;
	margin-bottom: 1.25rem;
}

.jpc-ot-title {
	margin: 0;
}

.jpc-ot-user {
	opacity: 0.7;
	font-size: 0.95rem;
}

/* ---------------------------------------------------------------------------
 * The race-track tracker card (JP's approved v2 design, 1 Oct 2026)
 *
 * A self-contained DARK card: it carries its own colours so it looks the same
 * on any theme, and everything is scoped under `.jpc-ot` so it styles only what
 * the plugin adds. Mobile first — nothing scrolls the page sideways at 390px,
 * and the circuit is decoration the card reads fine without.
 * ------------------------------------------------------------------------ */

.jpc-ot {
	--jpc-red: #DD0D12;
	--jpc-white: #fff;
	--jpc-muted: #a7adb6;
	--jpc-line: rgba( 255, 255, 255, 0.12 );
}

.jpc-ot-card {
	position: relative;
	overflow: hidden;
	border: 1px solid var( --jpc-line );
	border-radius: 18px;
	margin: 0 0 1.25rem;
	padding: 20px;
	color: var( --jpc-white );
	background:
		linear-gradient( 135deg, rgba( 255, 255, 255, 0.035 ), transparent 20% ),
		linear-gradient( 180deg, #12151a 0, #0c0e12 100% );
	box-shadow: 0 24px 60px rgba( 0, 0, 0, 0.42 );
	font-family: Oswald, Montserrat, system-ui, -apple-system, "Segoe UI", sans-serif;
}

.jpc-ot-card::before {
	content: "";
	position: absolute;
	inset: 0 0 auto;
	height: 3px;
	background: linear-gradient( 90deg, var( --jpc-red ), #ff6064 32%, rgba( 221, 13, 18, 0.04 ) 76% );
}

.jpc-ot-card-head {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	align-items: baseline;
	gap: 0.25rem 1rem;
	margin-bottom: 0.5rem;
}

.jpc-ot-number {
	font-size: 1.4rem;
	font-weight: 700;
	letter-spacing: 0.03em;
	text-transform: uppercase;
}

.jpc-ot-date {
	color: var( --jpc-muted );
	font-size: 0.8rem;
	font-weight: 600;
}

.jpc-ot-items {
	color: var( --jpc-muted );
	font-size: 0.85rem;
	margin-bottom: 0.5rem;
}

/* The store's own status — always present, the half that needs no network. */
.jpc-ot-status {
	display: inline-block;
	font-size: 0.95rem;
	font-weight: 600;
	color: var( --jpc-white );
	opacity: 0.92;
}

/* The status shell: the app's approved headline and the "Stage n / N" box. */
.jpc-ot-status-shell {
	display: grid;
	grid-template-columns: minmax( 0, 1fr ) auto;
	gap: 14px;
	align-items: center;
	margin: 1rem 0 0.9rem;
	padding: 14px 15px;
	border: 1px solid rgba( 255, 255, 255, 0.09 );
	border-radius: 14px;
	background: linear-gradient( 180deg, rgba( 255, 255, 255, 0.035 ), rgba( 255, 255, 255, 0.012 ) );
}

.jpc-ot-status-kicker {
	margin: 0 0 4px;
	color: #ff6b6f;
	font-size: 0.7rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.jpc-ot-status-copy {
	margin: 0;
	font-size: clamp( 1.15rem, 3vw, 1.7rem );
	font-weight: 600;
	line-height: 1.1;
	text-transform: uppercase;
}

.jpc-ot-status-copy[hidden] {
	display: none;
}

.jpc-ot-stage-count {
	white-space: nowrap;
	text-align: center;
	border: 1px solid rgba( 255, 255, 255, 0.1 );
	border-radius: 12px;
	background: #0b0d10;
	padding: 9px 12px;
}

.jpc-ot-stage-count[hidden] {
	display: none;
}

.jpc-ot-stage-count span {
	display: block;
	color: #8f959e;
	font-size: 0.62rem;
	font-weight: 700;
	letter-spacing: 0.12em;
	text-transform: uppercase;
}

.jpc-ot-stage-count strong {
	display: block;
	margin-top: 2px;
	font-size: 1.15rem;
	letter-spacing: 0.04em;
}

/* ---------------------------------------------------------------------------
 * The circuit, v2 (JP's approved design, 1 Oct 2026)
 *
 * Decoration only — width-capped, never a source of page scroll. The layers run
 * outside-in: grass, shadow, verge, run-off, kerb, edge line, tarmac, racing
 * line, sheen. Each is the SAME path at a narrower stroke-width, which is why
 * the circuit stays consistent when the browser swaps in the phone path.
 * ------------------------------------------------------------------------ */

.jpc-ot-track-card {
	position: relative;
	overflow: hidden;
	border: 1px solid rgba( 255, 255, 255, 0.08 );
	border-radius: 16px;
	background: #0b120d;
	padding: 0;
}

.jpc-ot-track-svg {
	display: block;
	width: 100%;
	height: auto;
	/* Matches the wide viewBox ratio exactly, so `meet` letterboxes nothing.
	   The JS rewrites this inline when it swaps in the phone circuit (420/292);
	   this declaration is the no-JS default and the pre-swap value. */
	aspect-ratio: 1030 / 292;
}

/* fill:none for every track path, belt-and-braces with the SVG attributes. The
   child combinator hits only the geometry paths — the car, the finish shapes
   and the markers are nested in <g>, so their fills are untouched. */
.jpc-ot-track-svg > path { fill: none !important; }

/* The geometry path the car follows is invisible — measured, never drawn. */
.jpc-ot-track-path { fill: none; stroke: none; }

/* --- the ground ------------------------------------------------------- */

/* A soft drop of the whole circuit onto the grass, so the track sits in the
   field rather than floating on it. */
.jpc-ot-track-shadow { stroke: rgba( 0, 0, 0, 0.45 ); stroke-width: 128; stroke-linejoin: round; fill: none; }
.jpc-ot-verge { stroke: #16231a; stroke-width: 124; stroke-linecap: round; stroke-linejoin: round; fill: none; }
.jpc-ot-runoff { stroke: #2a2f35; stroke-width: 96; stroke-linecap: round; stroke-linejoin: round; fill: none; }

/* --- kerbs -------------------------------------------------------------
 * Drawn on the WHOLE path, then dashed down to the bends by the JS
 * (`paintKerbs`), which measures where the path actually turns. The red is a
 * second dash pattern on top of the white, so the stripes alternate. The shade
 * is the same geometry a little narrower, which reads as the inner lip.
 * -------------------------------------------------------------------- */
.jpc-ot-curb-white { stroke: #f4f4f4; stroke-width: 78; stroke-linejoin: round; fill: none; }
.jpc-ot-curb-red { stroke: #E31E24; stroke-width: 78; stroke-linejoin: round; fill: none; }
.jpc-ot-curb-shade { stroke: rgba( 0, 0, 0, 0.35 ); stroke-width: 70; stroke-linejoin: round; fill: none; }

/* --- the road ---------------------------------------------------------- */

.jpc-ot-edge { stroke: #eef0f2; stroke-width: 66; stroke-linecap: butt; stroke-linejoin: round; fill: none; }
.jpc-ot-road { stroke: #2c3138; stroke-width: 60; stroke-linecap: butt; stroke-linejoin: round; fill: none; }
.jpc-ot-rubber { stroke: #15181c; stroke-width: 24; stroke-linecap: round; stroke-linejoin: round; fill: none; opacity: 0.55; }
.jpc-ot-road-hi { stroke-width: 60; stroke-linejoin: round; fill: none; opacity: 0.28; mix-blend-mode: screen; }

/* --- the line the car has driven, and the line still to drive ---------- */

.jpc-ot-ahead { stroke: rgba( 255, 255, 255, 0.34 ); stroke-width: 2.2; stroke-dasharray: 2 11; stroke-linecap: round; fill: none; }
.jpc-ot-driven-glow { stroke: #ff1c22; stroke-width: 14; stroke-linecap: round; fill: none; opacity: 0.42; }
.jpc-ot-driven { stroke: #ff2a2f; stroke-width: 4.5; stroke-linecap: round; fill: none; }
.jpc-ot-driven-core { stroke: #ffd0d1; stroke-width: 1.2; stroke-linecap: round; fill: none; opacity: 0.8; }

/* The reveal that grows these three together is set by the JS, per draw — see
   `drawCircuit`. It is deliberately NOT a rule here: a stylesheet transition
   also animates the first paint, which starts at a full lap and then retracts. */

/* --- the start grid ---------------------------------------------------- */

.jpc-ot-grid path { stroke: #fff; stroke-opacity: 0.7; stroke-width: 1.6; fill: none; }

/* --- markers ----------------------------------------------------------- */

.jpc-ot-marker circle.outer { stroke: #5b626c; stroke-width: 2.5; }
.jpc-ot-marker circle.inner { fill: #2e333b; }
.jpc-ot-marker.done circle.outer,
.jpc-ot-marker.current circle.outer { stroke: #fff; }
.jpc-ot-marker.current circle.outer { stroke-width: 3.5; }
.jpc-ot-marker.future { opacity: 0.6; }
.jpc-ot-marker-num { font-size: 11px; font-weight: 700; fill: #fff; text-anchor: middle; dominant-baseline: middle; pointer-events: none; }

/* The ring that expands off the CURRENT marker — the one "you are here" cue. */
.jpc-ot-pulse {
	fill: none;
	stroke: #ff2a2f;
	stroke-width: 2.5;
	transform-box: fill-box;
	transform-origin: center;
	animation: jpc-ot-pulse 1.6s ease-out infinite;
}

@keyframes jpc-ot-pulse {
	from { transform: scale( 1 ); opacity: 0.9; }
	to { transform: scale( 2.4 ); opacity: 0; }
}

/* --- the pit board naming the current stage ----------------------------
 * The label is the APP'S stage label, set by the JS. Nothing here supplies
 * wording; this styles a board whose text arrives from the app.
 * -------------------------------------------------------------------- */
.jpc-ot-board rect { fill: #fff; }
.jpc-ot-board .tip { fill: #fff; }
.jpc-ot-board .stripe { fill: #E31E24; }
.jpc-ot-board text {
	font-size: 12px;
	font-weight: 700;
	fill: #0b0d10;
	text-anchor: middle;
	dominant-baseline: middle;
	letter-spacing: 0.07em;
	/* The look, not the wording: the DOM text stays the app's label verbatim. */
	text-transform: uppercase;
}

/* --- the finish --------------------------------------------------------- */

.jpc-ot-flagpole { stroke: #c6cbd2; stroke-width: 3; fill: none; }
.jpc-ot-gantry-text { font-size: 9px; font-weight: 700; fill: #fff; letter-spacing: 0.26em; text-anchor: middle; dominant-baseline: middle; text-transform: uppercase; }
.jpc-ot-flag { transform-box: fill-box; transform-origin: 0 50%; }
.jpc-ot-card[data-complete="true"] .jpc-ot-flag { animation: jpc-ot-flag 1s ease-in-out infinite alternate; }
@keyframes jpc-ot-flag { from { transform: skewY( -6deg ) scaleX( 0.93 ); } to { transform: skewY( 6deg ) scaleX( 1.04 ); } }

/* Fired once, on arrival at the finish. The JS removes the rects afterwards. */
.jpc-ot-confetti rect { animation: jpc-ot-confetti 1.4s cubic-bezier( 0.2, 0.7, 0.3, 1 ) forwards; }
@keyframes jpc-ot-confetti {
	from { transform: translate( 0, 0 ) rotate( 0 ); opacity: 1; }
	to { transform: translate( var( --dx ), var( --dy ) ) rotate( var( --r ) ); opacity: 0; }
}

/* --- the car ------------------------------------------------------------
 * A 400x190 WebP with a transparent background, nose pointing +x so the JS can
 * rotate it to the path's tangent with no extra offset. Brake lights glow as it
 * pulls up at a stage; the headlights flash once on delivery.
 * -------------------------------------------------------------------- */
.jpc-ot-brake { opacity: 0; transition: opacity 0.15s; }
.jpc-ot-car.braking .jpc-ot-brake { opacity: 1; }
.jpc-ot-headglow { opacity: 0; }
.jpc-ot-car.flash .jpc-ot-headglow { animation: jpc-ot-flash 0.32s steps( 2 ) 4; }
@keyframes jpc-ot-flash { 50% { opacity: 1; } }

/* --- phone, and the texture budget --------------------------------------
 * Below 600px the browser swaps in the switchback circuit (the JS rewrites the
 * path and the viewBox). THERE IS DELIBERATELY NO RULE HERE TURNING THE
 * feTurbulence TEXTURES OFF at that width, which is the obvious thing to reach
 * for and was measured rather than assumed.
 *
 * Measured 1 Oct 2026, headless Chrome 154 at a 390px viewport, two cards on
 * the page, CPU throttled 6x: frame times while the car drove were 16.7ms mean
 * and 16.7ms at the 95th percentile with the textures on, and the same with
 * them off, no dropped frames either way. A forced full redraw painted inside
 * one frame in both. The textures are not what costs anything here.
 *
 * What DID matter was the filter REGION, and that is fixed in the JS rather
 * than here: the region follows the viewBox, so the phone rasterises a smaller
 * noise field than the desktop does instead of a much larger one.
 *
 * Caveat worth keeping: a CPU-throttled desktop is not a phone GPU. If a real
 * low-end device ever does struggle, the one-rule fix is to put back
 * `@media (max-width:600px){ .jpc-ot-grass,.jpc-ot-runoff,.jpc-ot-road{filter:none!important} }`
 * — the flat colours underneath are the same colours, so the circuit reads
 * identically and only loses its grain.
 * -------------------------------------------------------------------- */

@media ( prefers-reduced-motion: reduce ) {
	.jpc-ot-card[data-complete="true"] .jpc-ot-flag,
	.jpc-ot-pulse,
	.jpc-ot-confetti rect,
	.jpc-ot-car.flash .jpc-ot-headglow { animation: none !important; }
	.jpc-ot-brake { transition: none; }
}

/* The stage list — the readable-without-JS half. Grid on desktop, rows on phone. */
.jpc-ot-stage-list {
	list-style: none;
	margin: 1rem 0 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( 96px, 1fr ) );
	gap: 8px;
}

.jpc-ot-stage-item {
	position: relative;
	min-width: 0;
	border: 1px solid rgba( 255, 255, 255, 0.08 );
	border-radius: 12px;
	background: #101318;
	padding: 10px 9px 11px 14px;
}

.jpc-ot-stage-item::before {
	content: "";
	position: absolute;
	left: 0;
	top: 10px;
	bottom: 10px;
	width: 3px;
	border-radius: 0 3px 3px 0;
	background: #343941;
}

.jpc-ot-stage-item.done { background: #15181d; }
.jpc-ot-stage-item.done::before { background: var( --jpc-red ); }
.jpc-ot-stage-item.current {
	border-color: rgba( 221, 13, 18, 0.72 );
	background: linear-gradient( 180deg, rgba( 221, 13, 18, 0.16 ), rgba( 221, 13, 18, 0.05 ) );
}
.jpc-ot-stage-item.current::before { background: #fff; }
.jpc-ot-stage-item.future { opacity: 0.58; }

.jpc-ot-stage-name {
	display: block;
	font-size: 0.9rem;
	font-weight: 600;
	line-height: 1.1;
	text-transform: uppercase;
	overflow-wrap: anywhere;
}

.jpc-ot-stage-state {
	display: block;
	margin-top: 5px;
	color: #8e949c;
	font-size: 0.58rem;
	font-weight: 700;
	letter-spacing: 0.11em;
	text-transform: uppercase;
}

.jpc-ot-stage-item.done .jpc-ot-stage-state { color: #d8dce1; }
.jpc-ot-stage-item.current .jpc-ot-stage-state { color: #ff686d; }

/* Production lines below the circuit: complete, lead time, empty, error. */
.jpc-ot-production {
	margin-top: 0.9rem;
}

.jpc-ot-production[data-state="loading"] { color: var( --jpc-muted ); }
.jpc-ot-loading { font-size: 0.9rem; }

.jpc-ot-stage { font-weight: 600; }
.jpc-ot-stage--complete { color: #ff686d; text-transform: uppercase; letter-spacing: 0.02em; }

.jpc-ot-lead {
	margin-top: 0.35rem;
	font-size: 0.92rem;
	color: #d6dae0;
}

.jpc-ot-unavailable,
.jpc-ot-empty,
.jpc-ot-unavailable-line,
.jpc-ot-empty-line {
	display: block;
	color: var( --jpc-muted );
	font-size: 0.92rem;
	line-height: 1.5;
}

/* The finish banner — shown only in the complete state. Its headline is the
   app's final-stage label ("Dispatched", or "Ready to collect" on collection).
   It read "Delivered" until 2 Oct 2026, which the app could never actually
   know; see jpc_ot_finish_banner_html(). */
.jpc-ot-finish {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 6px 14px;
	margin-top: 0.9rem;
	padding: 12px 14px;
	border: 1px solid rgba( 255, 255, 255, 0.12 );
	border-radius: 13px;
	background: linear-gradient( 90deg, rgba( 221, 13, 18, 0.17 ), rgba( 255, 255, 255, 0.03 ) );
}

.jpc-ot-finish[hidden] { display: none; }
.jpc-ot-finish strong { font-size: 1.15rem; text-transform: uppercase; letter-spacing: 0.03em; }
.jpc-ot-finish span { color: #bec3ca; font-size: 0.72rem; }

@media ( max-width: 600px ) {
	.jpc-ot-card { padding: 14px; border-radius: 15px; }
	.jpc-ot-status-shell { padding: 12px; }
	.jpc-ot-stage-list { grid-template-columns: 1fr; gap: 6px; }
	.jpc-ot-stage-item {
		display: grid;
		grid-template-columns: minmax( 0, 1fr ) auto;
		align-items: center;
	}
	.jpc-ot-stage-state { margin: 0 0 0 10px; text-align: right; }
}

@media ( max-width: 410px ) {
	.jpc-ot-status-copy { font-size: 1.1rem; }
}


/* ---------------------------------------------------------------------------
 * Checkout SMS notice
 *
 * Quiet by design. It is a courtesy telling the customer what to expect, not a
 * sales message, so it should read like small print rather than a banner.
 * ------------------------------------------------------------------------ */

.jpc-ot-sms-notice {
	margin: 0.75rem 0 0;
	padding: 0.6rem 0.75rem;
	border-left: 3px solid var( --jpc-ot-brand, #E31E24 );
	background: rgba( 0, 0, 0, 0.03 );
	font-size: 0.9rem;
	line-height: 1.45;
}

.jpc-ot-sms-notice[hidden] {
	display: none;
}

/* ---------------------------------------------------------------------------
 * The public tracking page
 *
 * Two fields and a button. The theme owns the page's type and colour; this only
 * makes the form legible on a phone and keeps the touch targets big enough to
 * hit. Nothing here is decoration for its own sake.
 * ------------------------------------------------------------------------ */

.jpc-ot-public-form {
	max-width: 28rem;
	margin: 1.25rem 0 0;
}

.jpc-ot-field {
	display: flex;
	flex-direction: column;
	gap: 0.3rem;
	margin: 0 0 1rem;
}

.jpc-ot-field label {
	font-weight: 600;
}

.jpc-ot-field input {
	/* 16px stops iOS Safari zooming the page in on focus. */
	font-size: 16px;
	padding: 0.65rem 0.75rem;
	border: 1px solid rgba( 0, 0, 0, 0.3 );
	border-radius: 4px;
	width: 100%;
	box-sizing: border-box;
}

.jpc-ot-hint {
	font-size: 0.85rem;
	opacity: 0.7;
}

/* Explicit colours for every interaction state, so the theme's global
   `button:hover` cannot override them. On 1.2.0 JP found the button turning the
   theme's hover colour — white text on a near-white background — and vanishing.
   Stating default, hover, active and focus here (with the same specificity the
   theme's rule has, but as the plugin's own longhand) keeps it visible whatever
   the theme does. Once shipped, JP removes the temporary Additional CSS. */
.jpc-ot-submit button,
.jpc-ot-submit button:link,
.jpc-ot-submit button:visited {
	min-height: 44px;
	padding: 0.6rem 1.4rem;
	border: 0;
	border-radius: 6px;
	background-color: #16181b; /* near-black default */
	color: #ffffff;            /* white text, always */
	font-weight: 700;
	cursor: pointer;
	transition: background-color 0.15s ease;
}

.jpc-ot-submit button:hover,
.jpc-ot-submit button:focus,
.jpc-ot-submit button:focus-visible,
.jpc-ot-submit button:active {
	background-color: #DD0D12; /* JP red on hover/focus/active */
	color: #ffffff;            /* text stays white — never inherits a theme hover colour */
}

/* A focus ring that survives whatever the theme sets, for keyboard users. */
.jpc-ot-submit button:focus-visible {
	outline: 3px solid #ffffff;
	outline-offset: 2px;
	box-shadow: 0 0 0 5px #DD0D12;
}

@media ( prefers-reduced-motion: reduce ) {
	.jpc-ot-submit button { transition: none; }
}

/* The one failure message the page ever prints. Loud enough to be read,
   because a customer who mistyped needs to notice they mistyped. */
.jpc-ot-public-error {
	margin: 0 0 1rem;
	padding: 0.75rem 0.9rem;
	border-left: 3px solid var( --jpc-ot-brand, #E31E24 );
	background: rgba( 0, 0, 0, 0.04 );
	line-height: 1.5;
}

.jpc-ot-public-again {
	margin: 1.5rem 0 0;
	font-weight: 600;
}

.jpc-ot-empty-line,
.jpc-ot-unavailable-line {
	display: block;
	opacity: 0.75;
	font-size: 0.95rem;
	line-height: 1.5;
}

/* The link offered to guests under the My Account login form. */
.jpc-ot-guest-link {
	margin: 1rem 0 0;
	line-height: 1.5;
}

/* Courier details — shown only when the app has them, so this block is
   either populated or absent. There is deliberately no empty state: an
   order whose courier is not booked yet shows nothing at all rather than
   a blank "Tracking:" label. */
.jpc-ot-tracking {
	margin: 0.85rem 0 0;
	padding: 0.7rem 0.85rem;
	border: 1px solid rgba(0, 0, 0, 0.08);
	border-radius: 6px;
	background: rgba(0, 0, 0, 0.02);
}

.jpc-ot-tracking-row {
	line-height: 1.6;
	font-size: 0.95rem;
}

.jpc-ot-tracking-row + .jpc-ot-tracking-row {
	margin-top: 0.2rem;
}

/* Long references must not push the card wide on a phone. */
.jpc-ot-tracking-number {
	font-variant-numeric: tabular-nums;
	letter-spacing: 0.02em;
	word-break: break-all;
}

.jpc-ot-tracking-link {
	display: inline-block;
	margin-top: 0.15rem;
	font-weight: 600;
}
