/* ==================================================================================================
   tw-case-hero-video — PLAYER TRANSPORT
   ==================================================================================================

   The custom control bar the widget builds on `play` when `controls_style = custom`. A SEPARATE
   stylesheet from `widget-case-hero-video.css` on purpose: the transport is a separable component
   (built by JS, switchable off entirely, and the subject of its own spec), and keeping it in its own
   file is what lets `check_widget_spec.mjs` diff `docs/specs/player-controls.md` byte-for-byte
   against a file containing ONLY the transport.

   ── RULE 1 · GEOMETRY IS FLUSH AND FULL-BLEED, AT EVERY WIDTH ────────────────────────────────────
   `left/right/bottom: 0`, square corners, no side or bottom border — the geometry a browser's own
   control bar has. Hares, 2026-08-20: *"get rid of the X & Y size variation and instead use the full
   length of the video, similar to how the native elementor does it."*
   ⛔ THERE IS NO `bar_width` AND NO `bar_height` CONTROL, AND ADDING ONE BACK REVERSES THAT
   INSTRUCTION. A 0.4.4x-era transport had both; they made the bar a floating pill, which is the
   design his partners rejected. If a size needs tuning it is tuned HERE, in this file, for every
   instance at once.

   ── RULE 2 · THE BAR IS TRANSPARENT BY DEFAULT; THE `::before` SCRIM CARRIES THE LEGIBILITY ──────
   Edge-to-edge, an opaque panel reads as a letterbox band across the film. A bottom-up gradient is
   what every native player uses and what Hares chose. The bar's own `background-color` is
   `transparent` in this file, and nothing in this file may colour it.
   ⛔⛔ THE ABSOLUTE FORM OF THIS RULE DIED IN 0.4.41 AND THE OLD WORDING IS RECORDED HERE SO NOBODY
   RESTORES IT. It read: the background-color "MUST stay that way — colour it and the scrim's whole
   point is lost". Hares asked for the opposite as an option on 2026-08-20 — "I'd like to see how it
   looks like with it having an actual background … Have a Setting where I can change it" — so
   `transport_bar_filled` + `transport_bar_bg` now exist, and a rule standing against shipped code is
   the same failure Rule 5 had earlier in this very release.
   ⚠️ WHAT ACTUALLY SURVIVES, AND IT IS THE PART THAT MATTERED: THE TWO ARE MUTUALLY EXCLUSIVE.
   Transparent is the default and the scrim is why; when the fill is switched on the scrim is
   switched OFF in the same rule block. What must never exist is a bar carrying BOTH — a gradient
   climbing behind an opaque band, doing nothing, costing a paint.
   ⚠️ THIS IS THE SECOND SCRIM IN THE WIDGET AND BOTH ARE CORRECT. `.tw-chv__scrim`
   (`widget-case-hero-video.css`) is a POSTER-seating device and fades to `opacity: 0` the moment
   playback starts (0.4.10 — over moving footage it is only a veil). It is gone exactly when the
   transport appears, so it cannot back it.
   ⛔ THE `z-index: -1` ON THE PSEUDO-ELEMENT IS LOAD-BEARING AND LOOKS REDUNDANT. `.tw-chv__bar` is
   positioned WITH a `z-index`, so it always establishes a stacking context — which is precisely why
   a negative child paints behind the bar's own box and CANNOT fall behind the frame or the film.
   Remove the bar's `z-index` and the scrim disappears under the video.

   ── RULE 3 · EVERY SLIDER IS A REAL `<input type="range">` AT `opacity: 0` ───────────────────────
   Track, fill and head are decoration (`pointer-events: none`); the input above them is the control.
   ⭐ This is why there is not one vendor pseudo-element in this file — no `::-webkit-slider-thumb`,
   no `::-moz-range-track`. A rule that mixes a `-webkit-` and a `-moz-` selector is dropped whole by
   both engines, and that class of bug cannot occur here at all.
   ⛔ `opacity: 0`, NEVER `visibility: hidden` OR `display: none` — an opacity-0 input keeps its tab
   stop, its keyboard handling and its accessible name. The focus ring is drawn on the WRAPPER with
   `:focus-within`, because an invisible element cannot show one itself.
   ⛔ AND `:focus-within` ALONE IS NOT THE WHOLE RULE — IT CANNOT TELL A CLICK FROM A TAB. Left at
   that it lights the ring on a mouse click and NEVER CLEARS IT, because the bar's auto-hide also
   refuses to run while focus is inside the bar (`armHide()` in the JS; spec §6.2 — ⚠️ NOT rule 4
   below, which this sentence cited until the re-audit: rule 4 is about the hidden bar staying
   focusable and has nothing to do with the timer). Two halves, both required: the pointer suppression
   below (`:focus-within:not(:has(:focus-visible))`), and `dropPointerFocus()` in the JS, which
   blurs the slider on `pointerup` so the hide timer can run again. Fixed 0.4.44; the full account
   is on the seek slider's rule and in `docs/specs/player-controls.md` rules 3 and §6.2.

   ── RULE 4 · THE HIDDEN BAR STAYS FOCUSABLE ─────────────────────────────────────────────────────
   At rest the bar is `opacity: 0` + `pointer-events: none`. ⛔ NEVER `visibility: hidden` — it is the
   one mechanism that removes a subtree from the TAB ORDER, and `focusin` is one of the reveal
   triggers, so hiding that way disables the only trigger a keyboard can produce and strands a
   keyboard user with no controls and no way back (the frame is `tabindex="-1"`). Found cold by
   `branch-auditor`; the full rule is `docs/CONVENTIONS.md` §6b.
   ⚠️ `pointer-events: none` is not optional either — an invisible bar with pointer events swallows
   the tap meant to reveal it.

   ── RULE 5 · THIS FILE OWNS THE GEOMETRY, SO THE SIZE CONTROLS SHIP WITH NO `default` ────────────
   `transport_icon_size` and `scrub_thickness` have NO `default` in the PHP. ⛔ THIS INVERTS §6a's
   USUAL CURE AND IS DELIBERATE. A control `default` compiles at (0,4,0) un-mediated and beats every
   rule in this file at every width. Measured, not assumed: on the archived build both skins set a
   56px bar height, a `bar_height` default of 52 existed, and the bar rendered 52 — two dead
   declarations that looked perfectly fine on screen.
   ⛔⛔ THE REASON CHANGED IN 0.4.41, AND THE OLD ONE IS NOW FALSE. It read "the two skins set
   different values, so one default flattens them". THERE IS ONLY ONE LOOK NOW — `dots` was deleted —
   so that conflict does not exist, and a rule whose stated reason has evaporated is worse than no
   rule: the next reader goes looking for the conflict, cannot find it, and "fixes" the absence.
   ⚠️ THE REASON THAT SURVIVES, AND IT IS ENOUGH ON ITS OWN: this file owns the design, and a control
   exists to OVERRIDE it, not to restate it. A `default` copies the value into a second place and the
   two drift — which is precisely how the archived build got its dead 56px declarations. It also
   keeps a desktop value from reaching a phone through responsive inheritance for no benefit.
   ⚠️ DO NOT "RESTORE THE MISSING DEFAULTS". That is the bug, not the fix.

   ── RULE 6 · `transport_glow_layer` IS THE ONLY SOURCE OF `box-shadow` ON A BUTTON ───────────────
   The same standing rule `tw-testimonials` enforces. A second light source under a halo the control
   owns is what got 0.4.17's shimmer deleted whole. `below` is the reference as drawn — the halo
   stops at the stroke and the middle stays a hole; `above` adds the inset wash so the light reads
   as coming OFF the button, the cure for "light with no lamp"
   (`copy/home-153/ARROW-GLOW-SPEC.md`).
   ⚠️ The class lands on the ELEMENTOR WRAPPER (`.elementor-element-<id>`), not on `.tw-chv` — a
   `prefix_class` always does. Reading it off `.tw-chv` produced two false reds last time.
   ⚠️ Since 0.4.41 the control is conditioned on nothing, so one of the two classes is ALWAYS on the
   wrapper. It used to hang off `transport_style = glow`, and Elementor omits a `prefix_class` whose
   control is conditioned out — which is why that condition had to be deleted along with the control
   it named, rather than left pointing at nothing.

   ── ORDER ────────────────────────────────────────────────────────────────────────────────────────
   Base → the ring and its glow → preview → breakpoint → reduced-motion. The last two must STAY last:
   they are overrides and lose at equal specificity if anything is appended after them.
   ================================================================================================== */

/* ── The bar ──────────────────────────────────────────────────────────────────────────────────── */
.tw-chv__bar {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 3;
	display: flex;
	align-items: center;
	gap: 10px;
	box-sizing: border-box;
	height: 56px;
	padding: 0 16px;
	background-color: transparent;
	opacity: 0;
	pointer-events: none;
	transition-property: opacity;
	transition-duration: .3s;
	transition-timing-function: ease;
}

/* Rule 2 — the legibility layer. Taller than the bar so the fade has room to resolve. */
.tw-chv__bar::before {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	top: -64px;
	z-index: -1;
	pointer-events: none;
	background-image: linear-gradient(0deg, rgba(8, 8, 10, .88) 0%, rgba(8, 8, 10, .55) 42%, rgba(8, 8, 10, 0) 100%);
}

.tw-chv__bar.is-shown {
	opacity: 1;
	pointer-events: auto;
}

/* ── The filled bar ───────────────────────────────────────────────────────────────────────────── */
/* `transport_bar_filled` — Hares, 2026-08-20: "While a Transparent background looks cool, I'd like
   to see how it looks like with it having an actual background … Have a Setting where I can change
   it from transparent to the filled Background please." Off by default, so Rule 2's scrim remains
   what the bar does unless someone asks otherwise.
   ⚠️ THE COLOUR IS NOT SET HERE. `transport_bar_bg` owns it and compiles into the page's own CSS at
   a specificity this file cannot and should not fight. This rule exists for the two things the
   control CANNOT express — killing the scrim, and the hairline.
   ⛔ SPECIFICITY, CHECKED BEFORE IT WAS WRITTEN, BECAUSE THIS EXACT COLLISION SHIPPED ONCE ALREADY.
   `.tw-chv-barfill-yes .tw-chv__bar` is (0,2,0) — the SAME weight as `.tw-chv__bar.is-shown`, which
   is what beat `.tw-chv__bar--preview` at (0,1,0) and left the "inert" editor bar clickable. They do
   not actually fight (`is-shown` sets no background), but this block sits AFTER it so that order
   decides if either ever grows a shared property. The gate asserts a filled bar is still filled
   while `is-shown` is on rather than trusting the reasoning.
   ⚠️ The class lands on the ELEMENTOR WRAPPER, not on `.tw-chv` — a `prefix_class` always does.
   ⛔ NO `backdrop-filter`. The reference is a flat render of a black page, which cannot show blur;
   adding one would be inference dressed as a match. */
.tw-chv-barfill-yes .tw-chv__bar {
	border-top: 1px solid var(--tw-line2, rgba(255, 255, 255, .14));
}

/* A gradient rising behind an opaque band is a second background doing nothing. */
.tw-chv-barfill-yes .tw-chv__bar::before {
	display: none;
}

/* ── Buttons ──────────────────────────────────────────────────────────────────────────────────── */
/* 44px is the hit area, not the mark — the icon inside is `transport_icon_size`. The gate asserts
   the 44 at every width; shrinking it to fit a phone is the wrong fix. */
.tw-chv__btn {
	flex: none;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background-color: transparent;
	color: var(--tw-ink, #f6f4f0);
	cursor: pointer;
}

/* A tan ring: these buttons are ghosts on a dark scrim, so the house accent reads. (The POSTER's
   play button is the opposite case — it is itself tan, and takes an ink ring instead.) */
.tw-chv__btn:focus-visible {
	outline: 2px solid var(--tw-tan-hi, #c9a074);
	outline-offset: 2px;
}

.tw-chv__ico {
	display: block;
	width: 18px;                           /* transport_icon_size overrides */
	height: 18px;                          /* transport_icon_size overrides */
	fill: currentColor;
	pointer-events: none;
}

/* ── Seek ─────────────────────────────────────────────────────────────────────────────────────── */
/* `flex: 1 1 auto` with `min-width: 0` — the track is the only element that may absorb the leftover
   width, and `min-width: 0` is what lets it shrink below its content on a phone. */
/* ⛔ `clip` + `overflow-clip-margin`, AND NEITHER HALF IS INTERCHANGEABLE WITH `overflow: hidden`.
   The falloff (`.tw-chv__scrub-fill::after`) is a FIXED length hung off the playhead, so near the
   end of the film it runs past the track and paints over the timecode — this element is positioned
   and `.tw-chv__time` is not, so the falloff wins the paint order. It has to be clipped.
   ⚠️ BUT `overflow: hidden` ALSO CUTS THE PLAYHEAD IN HALF. The head is centred with
   `translate(-50%, -50%)`, so half of it sits outside this box at 0% and again at 100% — a half-dot
   at the exact moment playback starts. `overflow-clip-margin` is what lets the head's 5px overhang
   paint while still cutting the falloff dead. 8px covers a head up to 16px wide.
   ⛔ AND THE OBVIOUS ALTERNATIVE — INSET THE TRACK TO MAKE ROOM — CANNOT WORK HERE. `draw()` writes
   `fill.style.width` and `head.style.left` as the SAME percentage of this box; inset the track and
   the head stops landing on it. Correcting that in JS means hard-coding half the head's width,
   which is the trap the head's own comment warns against below. */
.tw-chv__scrub {
	position: relative;
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	align-items: center;
	height: 44px;
	overflow: clip;
	overflow-clip-margin: 8px;
	container-type: inline-size;
}

/* Rule 3 — the ring belongs to the wrapper because the input itself is invisible. */
.tw-chv__scrub:focus-within {
	outline: 2px solid var(--tw-tan-hi, #c9a074);
	outline-offset: -2px;
	border-radius: 4px;
}

/* ── AND NOT FOR A MOUSE ─────────────────────────────────────────────────────────────────────────
   `:focus-within` cannot tell a click from a Tab, so a plain click on the timeline lit this ring —
   and it stayed lit, because nothing takes focus off a slider (`dropPointerFocus()` in the JS is
   the other half of this fix, and the one that also unsticks the bar's auto-hide).
   ⭐ `:not(:has(:focus-visible))` IS THE WHOLE MECHANISM, and it degrades correctly by itself: an
   engine that does not know `:has()` treats the selector as invalid and drops THIS rule only, so
   the ring above survives and a keyboard user is never left without one. That is why there is no
   `@supports` around it — adding one would gain nothing and could only get the fallback wrong.
   ⛔ DO NOT "SIMPLIFY" THIS INTO `:has(:focus-visible)` ON THE RULE ABOVE. That inverts the
   degradation: the same old engine would then drop the ring ENTIRELY.
   ⚠️ HOW THAT LAST PARAGRAPH WAS CHECKED, because it reads like a measurement and half of it is a
   proxy. Every engine we can run supports `:has()`, so it cannot be tested directly. What WAS run:
   the same two shapes with an invented `:tw-not-a-real-pseudo()` standing in for `:has()`. Chrome
   kept `.a:focus-within` and dropped both rules containing the unknown pseudo — so the shape below
   keeps its ring and the "simplified" shape loses it. That proves the CSS mechanism (an unknown
   pseudo-class invalidates ITS OWN rule and no other); it assumes, rather than proves, that a real
   `:has()`-less engine treats `:has()` the same way. (`branch-auditor`, 2026-08-24.)
   Measured in Chrome: after a mouse click `:has(:focus-visible)` is false; after Tab or an arrow
   key it is true. ⚠️ Hares REPORTED the bug on 2026-08-24; the measurement is the manager's, in a
   throwaway page. Naming the reporter as the measurer is how an inference gets a source it never
   had — the file's other measurement credits `branch-auditor` for exactly that reason. */
.tw-chv__scrub:focus-within:not(:has(:focus-visible)) {
	outline: none;
}

/* A HAIRLINE, and it is the design rather than a starting point — the reference's seek line is a
   thread, not a slab. `scrub_thickness` overrides it. */
.tw-chv__scrub-track,
.tw-chv__scrub-fill {
	position: absolute;
	left: 0;
	top: 50%;
	height: 2px;                           /* scrub_thickness overrides */
	border-radius: 999px;
	transform: translateY(-50%);
	pointer-events: none;
}

/* ⛔ FAINT, AND IT IS THE FALLOFF THAT MADE IT SO. This was `.26` — the same grey the volume track
   still uses — and at that weight a solid line resumes the instant the gold has finished fading,
   so the fade reads as a rendering fault rather than a design. Hares, 2026-08-20: "you have it
   orange until the current timecode and after that it is grey … in the reference there is a
   fade-off of the orange colour."
   ⚠️ DO NOT "RESTORE" IT TO MATCH `.tw-chv__vol-track`. The two are deliberately different now: the
   volume has no falloff, so its remainder is the only thing drawing the rest of its run. */
.tw-chv__scrub-track {
	right: 0;
	background-color: rgba(255, 255, 255, .07);
}

/* The width is written by `draw()` as a percentage — the played proportion, and nothing else.
   ⚠️ The glow is cast by a SOLID TAN BAR, which is what keeps it inside the house rule: light is
   emitted by a surface that is already tan, never by a halo with no source
   (`design-reference/DESIGN-GUIDELINES.md` §2, "light with no lamp"). */
.tw-chv__scrub-fill {
	width: 0;
	background-color: var(--tw-tan, #B18051);
	box-shadow: 0 0 10px rgba(177, 128, 81, .9);
}

/* ⭐ THE FALLOFF, AND IT COSTS NO JS AT ALL. `left: 100%` is the fill's right edge, and the fill's
   right edge IS the playhead — so this tracks the position for free, off a width `draw()` is
   already writing. No custom property, no second element, nothing for the tick to keep in sync.
   ⚠️ THERE IS NO "JS WRITES AN INLINE CSS VAR" PATTERN IN THIS BUILD and this is not the place to
   start one: a single `setProperty` call exists in the whole plugin (`widget-work-grid.js`).
   ⛔⛔ `cqw` — A SHARE OF THE TRACK'S OWN WIDTH — AND THE FIRST ATTEMPT GOT THIS WRONG TWICE OVER.
   It shipped a fixed 160px with a comment arguing that a proportional length was the mistake, since
   it "would cover a third of the track on a desktop and a third of a much shorter track on a phone".
   That is not a fault, it is the reference: the board's fade is a SHARE of its track, and screenshots
   at 1400 showed 160px reading as a stub next to it.
   ⚠️ A PERCENTAGE WOULD NOT WORK, WHICH IS WHY THE FIXED VALUE WAS REACHED FOR. This pseudo-element's
   containing block is the FILL, so `width: 34%` would be 34% of the played portion and would grow as
   the film ran. `cqw` resolves against `.tw-chv__scrub` instead — the whole track — via the
   `container-type` above, which is the measurement actually wanted. It also removes the breakpoint
   override the fixed value needed, so there is one number here instead of two that can drift.
   ⛔⛔ IT STARTS DIMMED — AT .42, NOT AT THE FILL'S OWN COLOUR — AND THAT IS THE WHOLE POINT OF IT.
   The first version began at full `var(--tw-tan)`, so the played line and the fade met with no step
   and the fade read as more played track rather than as decoration. Hares, 2026-08-20: *"It is not
   obvious enough that this is just for style … the colour already starts way darker compared to the
   colour of the timeline which has been already played."*
   ⚠️ SO THE STEP AT THE PLAYHEAD IS THE FEATURE. Anything that closes it — raising the first stop,
   or "tidying" it back to the token for consistency with the fill — puts the original bug back.
   ⚠️ THREE STOPS, NOT TWO. A straight .42 → 0 ramp decays too evenly and the tail stays legible far
   too long; dropping to .16 by a third of the way gives the quick fall and long faint tail the
   reference draws.
   ⚠️ Literal `rgba()` rather than the token, matching every glow in this file — the token cannot
   carry an alpha, and half-tokenising it would hide that all four of these values move together.
   ⚠️ Rule 6 holds: this is the lit fill continuing past its own edge, not a second light source. The
   fill's own 10px glow bleeds across the step, so the dimming reads as falloff and not as a seam. */
.tw-chv__scrub-fill::after {
	content: '';
	position: absolute;
	left: 100%;
	top: 0;
	bottom: 0;
	width: 34cqw;
	pointer-events: none;
	background-image: linear-gradient(90deg, rgba(177, 128, 81, .42) 0%, rgba(177, 128, 81, .16) 34%, rgba(177, 128, 81, 0) 100%);
}

/* Centred on its own middle by the transform, so a bigger head stays honest about the time it
   reports. ⚠️ Do NOT re-centre by subtracting half the width in JS — that hard-codes one size, and
   the archived build did exactly that with a `- 1px` for a 2px head. */
.tw-chv__scrub-head {
	position: absolute;
	left: 0;
	top: 50%;
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background-color: #f0dcc2;
	box-shadow: 0 0 12px 2px rgba(226, 192, 147, .85);
	transform: translate(-50%, -50%);
	pointer-events: none;
}

.tw-chv__scrub-input {
	position: absolute;
	left: 0;
	top: 0;
	width: 100%;
	height: 100%;
	margin: 0;
	opacity: 0;
	cursor: pointer;
}

/* ── Timecode ─────────────────────────────────────────────────────────────────────────────────── */
/* ⛔ `aria-hidden` in the markup, and that is not an oversight: the seek input's `aria-valuetext`
   already announces the position, so an exposed sibling makes a screen reader say it twice.
   `tabular-nums` is what stops the bar twitching as the digits change. */
.tw-chv__time {
	flex: none;
	font-family: var(--tw-font-body, 'Inter', sans-serif);
	font-size: 11px;
	font-weight: 400;
	letter-spacing: .14em;
	font-variant-numeric: tabular-nums;
	color: var(--tw-body, #c4c1ba);
	white-space: nowrap;
	-webkit-user-select: none;
	user-select: none;
}

/* ── Volume ───────────────────────────────────────────────────────────────────────────────────── */
/* ⛔ INLINE, NEVER A HOVER FLYOUT. The archived build used a panel that opened on `pointerenter`
   behind a coarse-pointer gate, while the mute button blurs itself on a pointer click — so the
   volume slider was unreachable on EVERY touch device the widget shipped to. An always-present
   slider cannot reproduce that shape. It is dropped outright below 767 (see the breakpoint block),
   where the speaker button remains as a mute toggle. */
.tw-chv__vol {
	position: relative;
	flex: none;
	display: flex;
	align-items: center;
	width: 72px;
	height: 44px;
}

.tw-chv__vol:focus-within {
	outline: 2px solid var(--tw-tan-hi, #c9a074);
	outline-offset: -2px;
	border-radius: 4px;
}

/* Pointer focus draws no ring — the reasoning, and why there is no `@supports`, is on the seek
   slider's copy of this rule above. */
.tw-chv__vol:focus-within:not(:has(:focus-visible)) {
	outline: none;
}

.tw-chv__vol-track,
.tw-chv__vol-fill {
	position: absolute;
	left: 0;
	top: 50%;
	height: 3px;
	border-radius: 999px;
	transform: translateY(-50%);
	pointer-events: none;
}

.tw-chv__vol-track {
	right: 0;
	background-color: rgba(255, 255, 255, .26);
}

/* ⛔ THE SAME TAN AS THE SEEK FILL, AND THE REMAINDER STAYS GREY. Hares, 2026-08-20: "The Audio
   Slider should be bronze coloured, look at the reference." It shipped grey (`--tw-body`) beside a
   tan seek fill in the same bar, which is the disagreement he saw.
   ⚠️ ONLY THE FILL TURNS. The reference draws the volume as a gold run with a short dark tail — run
   the whole 72px gold and the slider reads as permanently full, losing the only cue that it HAS a
   value. The `.tw-chv__vol-track` above stays at .26 on purpose.
   ⚠️ The glow is half the seek fill's alpha, not the same: this line is 3px in a 72px run and takes
   the same halo as a full-width track otherwise, which puts a lamp on the quietest control in the
   bar. Rule 6 is unaffected — it governs `box-shadow` on a BUTTON, and this is a lit surface. */
.tw-chv__vol-fill {
	width: 100%;
	background-color: var(--tw-tan, #B18051);
	box-shadow: 0 0 8px rgba(177, 128, 81, .45);
}

.tw-chv__vol-input {
	position: absolute;
	left: 0;
	top: 0;
	width: 100%;
	height: 100%;
	margin: 0;
	opacity: 0;
	cursor: pointer;
}

/* ── A seek that cannot land anywhere ─────────────────────────────────────────────────────────── */
/* A stream with no known duration: the track stays as an inert rail rather than pretending. */
.tw-chv__bar.is-noscrub .tw-chv__scrub-input {
	display: none;
}

.tw-chv__bar.is-noscrub .tw-chv__scrub-head {
	display: none;
}

/* ══ THE PLAY BUTTON'S RING AND ITS GLOW ═════════════════════════════════════════════════════════
   ⛔ THERE ARE NO SKIN MODIFIER CLASSES IN THIS FILE, AND THERE USED TO BE TWO. 0.4.40 shipped
   `tw-chv__bar--glow` and `tw-chv__bar--dots` for Hares to choose between on the live site; he chose
   on 2026-08-20 — "I would like to get rid of the dotted version and just stick to the glow one" —
   so the dots skin is DELETED and the glow one is simply what the bar is. Its declarations were
   folded up into the base rules above: the 2px hairline track, the fill's glow, and the 10px cream
   head are all up there now.
   ⚠️ DO NOT REINTRODUCE A MODIFIER FOR ONE LOOK. A class that never varies is a hook nothing reads,
   and it invites a second look to be added beside it rather than considered on its merits.
   ⚠️ The deleted skin is recoverable from this branch's own history and from the tag
   `archive/chv-transport-0.4.42` — it is not lost, it is decided.
   ⚠️ THAT TAG'S NUMBER IS HIGHER THAN THIS BUILD'S AND IT IS NOT A TYPO. The archived transport
   really did carry 0.4.42; the rebuild started again from `main`, which was on 0.4.39, so the
   shipping line runs 0.4.39 → 0.4.40 → 0.4.41 and is monotonic on main. A tag numbered above the
   code is the only trace of a branch that was deleted rather than merged.
   ⛔ CONSEQUENCE NOBODY HAD WRITTEN DOWN (`branch-auditor`, 2026-08-21): THE NEXT RELEASE IS 0.4.42
   AND WILL COLLIDE WITH THAT TAG BY NAME. Ship it anyway — a tag and a version are different
   namespaces and git will not stop you. ⚠️ DO NOT "RESOLVE" THE COLLISION BY SKIPPING TO 0.4.43:
   a gap in the version line is a permanent puzzle, while a tag naming a deleted branch is a
   footnote. Rename the tag if it genuinely gets in the way. */

/* A ring, not a disc — the reference's button is an outline with the film showing through. */
.tw-chv__btn--play {
	border-width: 1px;
	border-style: solid;
	border-color: rgba(201, 160, 116, .55);
}

/* ⛔ RULE 6 — THE ONLY TWO `box-shadow` DECLARATIONS ON A BUTTON IN THIS FILE, and both belong to
   `transport_glow_layer`. A second light source under a halo the control owns is what got 0.4.17's
   shimmer deleted whole in `tw-testimonials`.
   ⚠️ The class lands on the ELEMENTOR WRAPPER (`.elementor-element-<id>`), never on `.tw-chv` — a
   `prefix_class` always does, and reading it off the widget root has produced false gate reds twice.
   ⚠️ Since 0.4.41 the control is no longer conditioned on anything, so one of these two always
   matches. Previously it hung off `transport_style = glow`, and Elementor omits a `prefix_class`
   whose control is conditioned out. */
.tw-chv-glow-below .tw-chv__btn--play {
	box-shadow: 0 0 18px 2px rgba(177, 128, 81, .55);
}

.tw-chv-glow-above .tw-chv__btn--play {
	box-shadow: 0 0 18px 2px rgba(177, 128, 81, .55), inset 0 0 16px rgba(177, 128, 81, .5);
}

/* ── The editor canvas ────────────────────────────────────────────────────────────────────────── */
/* `editor_preview_bar` draws a frozen bar at 50% so the panel's controls move something visible.
   ⛔ It is INERT: nothing binds, nothing ticks, and it must never accept a click — a control that
   looks live and does nothing is worse than no preview. The attribute that reaches it is gated on
   `is_edit_mode()` in PHP, so this class is unreachable on the frontend.
   ⚠️ THIS RULE IS THE SECOND LINE OF DEFENCE NOW, AND UNTIL 0.4.41 IT WAS THE ONLY ONE. The JS
   claimed to bind nothing while `previewBar()` in fact built a fully bound bar, so real handlers sat
   behind this one declaration — and `pointer-events` does not stop a KEYBOARD reaching a button.
   `buildBar( entry, true )` now attaches no listeners, which is what makes the paragraph above true
   rather than aspirational.

   ⛔⛔ DOUBLED SELECTOR, AND IT IS NOT A TYPO. The preview bar also carries `is-shown` — it has to,
   or it would be invisible — and `.tw-chv__bar.is-shown` sets `pointer-events: auto` at (0,2,0).
   A single-class `.tw-chv__bar--preview` is (0,1,0) and LOSES, so the inert preview was fully
   clickable in the canvas. Measured in the real Elementor editor on templates 971 and 877, where it
   computed `auto`; nothing on the frontend could ever have shown it, because this class never ships
   there. Doubling the class matches (0,2,0) and wins on order.
   ⚠️ Do not "simplify" this back to one class. */
.tw-chv__bar.tw-chv__bar--preview {
	pointer-events: none;
}

/* ── ≤767 ─────────────────────────────────────────────────────────────────────────────────────── */
/* The slider goes, the timecode stays — Hares, 2026-08-19. At 390 both would leave under 90px of
   track, and iOS refuses to let a page set `.volume` at all, so the slider is already inert on his
   review device. The speaker button stays and still toggles mute. */
@media (max-width: 767px) {

	.tw-chv__bar {
		gap: 6px;
		height: 52px;
		padding: 0 10px;
	}

	.tw-chv__vol {
		display: none;
	}
}

/* ── Reduced motion ───────────────────────────────────────────────────────────────────────────── */
/* ⛔ `transition-duration` ALONE, never the `transition` shorthand — the shorthand resets
   `transition-property` too and would re-enable everything it is meant to stop. */
@media (prefers-reduced-motion: reduce) {

	.tw-chv .tw-chv__bar {
		transition-duration: 0s !important;
	}
}
