How it works What it captures Compare Pricing Blog Join the waitlist

<>

Loupely Lens Changelog

Every release, documented. What shipped, what changed, and why it matters.

18 releases

version 1.5.5
15 Jun 2026

Live CSS preview, and a warning when your change won't hold

What this is

This release added live preview to the confirming step. When you type a target value, Lens applies it to the clicked element on the page in real time, so you see the change before you commit to a diagnosis. No save. No reload. The element just updates while you type.

It also added a dynamic warning. If the value you typed will be overridden by a higher-specificity rule, Lens says so and names the real source doing the overriding: a theme, a plugin, a page builder, an inline style, or a script. Pseudo-elements got the same treatment, so ::before and ::after now have selectable property cards, live preview, and full triage parity. The property list collapses while you type so the popup stops sitting on top of the element you're trying to watch.

What it answers

- how do i preview a css change before applying it on my site
- why does my css change not hold even though it looks right
- what is overriding my css when my change keeps getting ignored
- how to see live css changes without editing the stylesheet
- how do i style a before or after pseudo element that won't change

Why we built it

The diagnosis is more useful when you can watch the change land before you trust it. A value that won't survive the cascade should say so while you're still typing it, not after you've pasted it.

Improvements 5
  • Live preview applies a typed CSS value to the clicked element on the page so you see the change before committing it (popup.js, content.js)
  • A dynamic warning says whether the change will hold and, when it won't, names the real source overriding it: theme, plugin, page builder, inline style, or script
  • Pseudo-element (::before and ::after) diagnosis arrived, with selectable property cards, their own live preview, a pseudo-qualified diagnosis header, and full triage parity
  • The property list now collapses while you type, keeping the selected property in view so the popup stops covering the element being previewed
  • The prescription card now flags when an override is backed by a CSS variable, so you know the value diverges from the variable's definition
Bug Fixes 5
  • Live preview now targets the exact element you clicked instead of the first selector match, using a direct element reference set at capture time
  • Preview no longer silently fails on elements without a unique DOM id, since the matchCount guard was removed from the popup listener
  • Two pseudo-preview helpers (lensPreviewApplyPseudo and lensPreviewClearPseudo) were called but never defined, throwing a silent error on every apply; both were added
  • An ambiguous selector that matches more than one element now suppresses the preview and warning instead of previewing the wrong element
  • Unmatched pseudo-element properties no longer crowd out authored ones, so real styles like color show up in the pseudo list
version 1.5.1
12 Jun 2026

Honest CSS verdicts: Lens names the rule that's actually winning

What this is

This release fixed the cases where Lens named the wrong rule as the winner. On Tailwind v4 and shadcn sites, a padding or margin diagnosis used to point at a 0px base reset instead of the utility class actually setting the value. Logical properties like padding-inline and margin-block now map to their physical longhands at capture, so the winner you see is the rule the browser is really applying.

The verdict copy got more honest across the board. A visibility:hidden ancestor stopped reporting the display:none "your changes have no effect" message and started getting its own finding with an overridable fix. The "only applies at this screen size" verdict now fires only when the rule actually doesn't match your current viewport, and the engine stopped presenting any winner the browser's computed value contradicts.

What it answers

- why does lens show a 0px padding winner on a tailwind site
- how do i find which css rule is actually winning on my page
- why does my element say my changes have no effect when it's just hidden
- how to fix padding-inline and margin-block not matching the real value
- why does the css override work in one place but not the other

Why we built it

A diagnosis tool is worthless the moment it names the wrong rule. These fixes close the cases where the answer was confidently wrong.

Improvements 4
  • The diagnosis now reads in real human terms inside the popup fight view, not just on the triage page, so the explanation sits next to the cards
  • Rules inside @supports and @container blocks are now captured, with a parse-coverage signal recording how many stylesheets could and couldn't be read
  • Rule sources now carry friendly names like "Xstore theme" across the popup, fight view, and triage, instead of generic origin labels, and the inline-style and systemic-spacing notes no longer hardcode Elementor
  • CSS logical properties (padding-inline, margin-block, inset, and logical border and sizing) now map to their physical longhands at capture time
Bug Fixes 5
  • On Tailwind v4 and shadcn sites, padding and margin winners now show the real utility value instead of a 0px base reset (closes LIM-005)
  • A visibility:hidden ancestor now gets its own finding and an honest, overridable verdict instead of the display:none "your changes have no effect" message
  • The engine no longer names a winner the browser contradicts, and the "only applies at this screen size" verdict fires only when the rule doesn't match the current viewport
  • The override box now produces an actionable fix for inline-style winners and picks a selector that beats the winning rule by construction, not by load order
  • The override now shows the same result in the popup and on the triage page, with the rule engine as the single source of truth
version 1.2.0
9 Jun 2026

Phase 1 ships: element coordinates captured, double-submit guard, and update interruption handling

Phase 1 of the build-out shipped. 4 correctness items that needed to be in place before any further work could begin.

The first: element coordinates are now captured with every pick. The x, y, width, and height of the element get stored in the capture alongside everything else. This is required for CDP Track 2, which will use the coordinates to resolve @layer priority on cross-origin sites in a later phase.

The second: a double-submit guard was added to the Diagnose button. Clicking it twice rapidly was able to consume 2 credits and write 2 session rows. The guard prevents startDiagnosing() from being re-entered while a diagnosis is already in flight.

The third and fourth: when an extension update happens while a capture is in progress, the service worker now writes a flag to storage. The next time the popup opens, it reads that flag, shows a notice that says "Lens updated while you were capturing. Pick your element again," and resets to idle instead of trying to resume a capture that's no longer valid.

What it answers

- why did lens charge me twice for one diagnosis
- what happens when lens updates while i'm capturing
- why does lens say pick your element again after an update
- what is element_rect in the lens capture file
- what shipped in lens phase 1

Why we built it

The double-submit bug was a real credit loss. The update interruption was a known bad state with no recovery path. Both needed to be closed before build-out.

Improvements 3
  • Element_rect field added to every capture: stores x, y, width, and height of the picked element. Required by CDP Track 2 in Phase 2B
  • Service worker onInstalled handler now checks for an in-flight capture before clearing storage. If one is present, writes ll_update_interrupted with a timestamp
  • InitPopup() reads ll_update_interrupted on open: if the flag is set, clears it, shows the update notice in the idle state, and stops there
Bug Fixes 1
  • Double-submit guard added: _diagnosisInFlight module-level boolean prevents startDiagnosing() from being entered twice. Button is disabled for the duration and re-enabled in the finally block
version 1.1.08
5 Jun 2026

Stabilisation: login loop fixed, capture race fixed, dead code removed

This release closed out the stabilisation pass before build-out begins. Nothing new shipped. Everything that was already in the extension got verified, fixed, or cleaned up.

The biggest fix was the login loop. When a diagnosis returned an auth error, the extension was routing to the login screen without clearing the capture from storage. On the next open, the capture was still there, the user clicked Diagnose again, hit the same error, and ended up in a loop. The fix adds a storage clear at both points in the code where auth failure can happen.

The Vision Capture race was also confirmed and fixed. The popup was opening and polling for capture data before content.js had finished writing it. The polling interval was widened from 200ms to 350ms, giving the write enough time to land.

Several pieces of dead code were removed: a side-panel block that was never reachable, an unused auth message handler in the service worker, and 2 popup functions that referenced HTML elements that don't exist.

What it answers

- why does lens keep taking me back to the login screen
- why does lens show the idle state instead of my capture
- what was in the lens stabilisation pass
- why does lens not show my element after capturing it
- what dead code was removed from lens

Why we built it

The login loop was a direct user report. The Vision Capture race was confirmed live via diagnostics logs. Neither could go into build-out unfixed.

Improvements 1
  • Force Auth Failure button added to the diagnostics page to support auth debugging: clears the refresh token with a confirmation dialog
Bug Fixes 6
  • Login loop fixed: capture keys (ll_capture_ready and ll_capture_result) now cleared before routing to the unauthenticated state on auth_invalid and account_not_found errors
  • Login loop fixed on second path: same storage clear added to the no-token-after-retry path in startDiagnosing()
  • Vision Capture race fixed: initPopup polling interval widened from 200ms to 350ms, extending the total window from 1,200ms to 2,100ms
  • Dead side-panel block removed from initPopup(): _tabId, _isSidePanelActive, _allStorage full-storage read, _spFallback, and the unreachable isSidePanelActive block
  • Dead REFRESH_AUTH_TOKEN message handler removed from service-worker.js: nothing in the codebase was sending this message
  • Dead popup functions removed: getActiveTab (defined, never called) and renderAlternativeProblemOptions (referenced HTML elements that don't exist in popup.html)
version 1.1.05
30 May 2026

Expanded confirming state, branding update, and auth stability fixes

The confirming state got a full redesign. When you capture an element, the popup now expands to 400px and shows the screenshot at full popup width, with the description field below it. The screenshot is right there in the popup: no separate preview page to open, no guessing whether the capture worked.

The extension also got a visual overhaul: new icons, a refreshed popup CSS system, and updated triage page styles.

2 auth stability fixes shipped alongside these. The first corrected a bug where any transient network failure was logging users out. The second removed a synchronous network call that was running after every successful diagnosis.

What it answers

- how do i see my screenshot in lens before diagnosing
- why does lens keep logging me out
- why does the lens popup look different
- what is the lens confirming state
- how do i know lens captured the right element

Why we built this

The screenshot existed in the confirming state but wasn't visible without opening a separate page. The capture preview page solved that problem but added a step. The expanded popup removes the step entirely.

Improvements 2
  • Confirming state expanded to 400px with inline screenshot at full popup width and description field below
  • New icons, popup CSS visual system, and triage CSS visual system shipped across the extension
Bug Fixes 2
  • Ll_auth_expired now only written on 401 and 403 responses: transient network failures no longer trigger a logout
  • RefreshCreditsAfterSuccess no longer makes a synchronous network call immediately after diagnosis