/* ==========================================================================
   Vision Simulator + focus lens

   Both are the same technique: stack two copies of one image, filter the
   bottom copy, and reveal the untouched top copy through a clip-path (the
   simulator's split) or a radial mask (the hero lens). JS only writes custom
   properties on a rAF tick — no layout work, no style strings in script.
   ========================================================================== */

/* --- Vision Simulator ---------------------------------------------------- */

.vision {
  display: grid;
  gap: var(--space-xl);
  align-items: start;
}

/*
  The source photograph is 699px wide; capping the stage there keeps the
  "corrected" half genuinely sharp, which is the whole point. Two columns only
  once 699px of stage AND a usable controls column both fit — below that the
  stage sits full width with the controls beneath it.
*/
@media (min-width: 79rem) {
  .vision {
    grid-template-columns: minmax(0, 699px) minmax(20rem, 1fr);
    gap: var(--space-2xl);
  }
}

.vision__stage {
  --split: 50;
  position: relative;
  margin: 0;
  aspect-ratio: 699 / 524;
  max-inline-size: 699px;
  border-radius: var(--radius-lg);
  overflow: hidden;
  isolation: isolate;
  border: 1px solid var(--color-line);
  box-shadow: var(--shadow-lift);
  touch-action: pan-y;
}

.vision__layer {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  user-select: none;
  -webkit-user-drag: none;
}

/* The affected copy sits underneath and carries the condition filter. */
.vision__layer--affected {
  z-index: 1;
}

/* The wash paints haze, scotoma or headlight bloom. It sits above the
   affected copy and below the clear one, so the split hides it for free. */
.vision__wash {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: transparent;
  transition: background var(--duration-slow) var(--ease-standard);
}

/* The untouched copy, revealed from the split rightwards. */
.vision__layer--clear {
  z-index: 3;
  clip-path: inset(0 0 0 calc(var(--split) * 1%));
}

.vision__split {
  position: absolute;
  inset: 0;
  z-index: 4;
  inline-size: 100%;
  block-size: 100%;
  margin: 0;
  padding: 0;
  opacity: 0;
  cursor: ew-resize;
  appearance: none;
  background: transparent;
}

.vision__split::-webkit-slider-thumb {
  appearance: none;
  inline-size: 1px;
  block-size: 100%;
}

.vision__divider {
  position: absolute;
  inset-block: 0;
  z-index: 5;
  inset-inline-start: calc(var(--split) * 1%);
  inline-size: 2px;
  translate: -1px 0;
  background: linear-gradient(
    to bottom,
    transparent,
    var(--color-brass-glow) 12%,
    var(--color-brass-glow) 88%,
    transparent
  );
  pointer-events: none;
}

.vision__divider::after {
  content: "";
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  inline-size: 2.75rem;
  aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  border: 1px solid var(--color-brass-glow);
  background: oklch(100% 0 0 / 0.16);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  box-shadow: 0 6px 18px oklch(21% 0.018 258 / 0.4);
}

.vision__split:focus-visible + .vision__divider::after {
  outline: 2px solid var(--color-brass-glow);
  outline-offset: 3px;
}

.vision__edge {
  position: absolute;
  z-index: 6;
  inset-block-end: var(--space-sm);
  padding: 0.3rem 0.7rem;
  border-radius: var(--radius-pill);
  font-size: var(--text-micro);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-night-text);
  background: oklch(17.5% 0.016 258 / 0.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  pointer-events: none;
}

.vision__edge--left {
  inset-inline-start: var(--space-sm);
}

.vision__edge--right {
  inset-inline-end: var(--space-sm);
}

/* --- Conditions ---------------------------------------------------------- */

/*
  Each condition is a filter on the affected layer plus, where the effect is
  not a blur, a wash. Nothing here is driven from JavaScript: the script only
  sets data-condition on the stage.
*/

.vision__stage[data-condition="none"] .vision__layer--affected {
  filter: none;
}

.vision__stage[data-condition="myopia"] .vision__layer--affected {
  filter: blur(6px);
}

.vision__stage[data-condition="astigmatism"] .vision__layer--affected {
  /* Directional blur along one axis — which is what astigmatism actually is. */
  filter: url("#astigmatism-blur");
}

.vision__stage[data-condition="cataract"] .vision__layer--affected {
  filter: blur(2.5px) contrast(0.72) saturate(0.8) brightness(1.12);
}

.vision__stage[data-condition="cataract"] .vision__wash {
  background: radial-gradient(
      120% 90% at 50% 45%,
      oklch(96% 0.07 88 / 0.5),
      oklch(94% 0.05 88 / 0.32) 60%,
      oklch(92% 0.04 88 / 0.4)
    );
}

.vision__stage[data-condition="glaucoma"] .vision__layer--affected {
  filter: blur(1px) contrast(0.94);
}

/* Centred at 32%, not 50%: the wash is only visible left of the split, so a
   stage-centred effect would straddle the divider instead of reading whole. */
.vision__stage[data-condition="glaucoma"] .vision__wash {
  background: radial-gradient(
    circle at 32% 50%,
    transparent 12%,
    oklch(14% 0.01 258 / 0.55) 30%,
    oklch(10% 0.01 258 / 0.96) 52%
  );
}

.vision__stage[data-condition="amd"] .vision__layer--affected {
  filter: contrast(0.96);
}

/* A near-black scotoma disappears against this shopfront, which is itself dark
   navy. A mid grey reads against both the dark building and the bright sky. */
.vision__stage[data-condition="amd"] .vision__wash {
  background: radial-gradient(
    circle at 32% 46%,
    oklch(58% 0.006 258 / 0.99) 0%,
    oklch(58% 0.006 258 / 0.96) 12%,
    oklch(60% 0.006 258 / 0.74) 19%,
    oklch(62% 0.008 258 / 0.34) 26%,
    transparent 35%
  );
}

.vision__stage[data-condition="glare"] .vision__layer--affected {
  filter: brightness(0.5) contrast(1.2) saturate(0.7) blur(0.6px);
}

.vision__stage[data-condition="glare"] .vision__wash {
  background: radial-gradient(
      circle at 26% 62%,
      oklch(99% 0.04 92 / 0.85),
      oklch(96% 0.06 92 / 0.28) 26%,
      transparent 46%
    ),
    radial-gradient(
      circle at 40% 60%,
      oklch(99% 0.04 92 / 0.7),
      oklch(96% 0.06 92 / 0.2) 22%,
      transparent 40%
    ),
    radial-gradient(
      circle at 78% 30%,
      oklch(97% 0.05 92 / 0.42),
      transparent 34%
    );
}

/* --- Controls ------------------------------------------------------------ */

.vision__controls {
  display: grid;
  gap: var(--space-md);
  align-content: start;
}

.vision__options {
  display: grid;
  gap: var(--space-2xs);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 9.5rem), 1fr));
}

.vision__option {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-sm);
  background: oklch(100% 0 0 / 0.42);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: var(--color-ink-soft);
  font: inherit;
  font-size: var(--text-sm);
  text-align: start;
  cursor: pointer;
  transition: border-color var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard),
    background-color var(--duration-fast) var(--ease-standard);
}

.vision__option::before {
  content: "";
  inline-size: 0.5rem;
  block-size: 0.5rem;
  border-radius: 50%;
  border: 1px solid currentColor;
  flex: none;
  translate: 0 -0.05rem;
  transition: background-color var(--duration-fast) var(--ease-standard);
}

.vision__option:hover {
  color: var(--color-ink);
  border-color: color-mix(in oklab, var(--color-brass) 60%, transparent);
}

.vision__option[aria-pressed="true"] {
  color: var(--color-ink);
  border-color: var(--color-brass);
  background: color-mix(in oklab, var(--color-brass) 14%, oklch(100% 0 0 / 0.5));
}

.vision__option[aria-pressed="true"]::before {
  background: var(--color-brass-deep);
}

.vision__note {
  min-block-size: 4.5lh;
  margin: 0;
  color: var(--color-ink-soft);
  font-size: var(--text-base);
}

.vision__disclaimer {
  margin: 0;
  padding-inline-start: var(--space-sm);
  border-inline-start: 2px solid var(--color-brass);
  color: var(--color-ink-mute);
  font-size: var(--text-sm);
}

.vision__actions {
  margin-top: var(--space-2xs);
}

/* Without JS the slider and buttons cannot do anything, so don't invite a drag
   that will not work. The stage still shows the 50/50 comparison and the
   condition list still reads as text. */
html:not(.js) .vision__split {
  display: none;
}

html:not(.js) .vision__option {
  cursor: default;
}

.vision__defs {
  position: absolute;
  inline-size: 0;
  block-size: 0;
  pointer-events: none;
}

@media (max-width: 47.99rem) {
  .vision__note {
    min-block-size: 0;
  }
}

/* --- Hero focus lens ----------------------------------------------------- */

/*
  The panel only goes soft once the script has taken over (data-lens-active),
  so with JavaScript blocked the hero simply renders sharp.
*/

.hero__lensbox {
  position: absolute;
  inset: 0;
  z-index: 2;
}

.hero__panel {
  background: #fff;
}

.hero__panel .hero__img {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
  mix-blend-mode: normal;
  user-select: none;
  -webkit-user-drag: none;
}

.hero__panel .hero__img--soft {
  transition: filter var(--duration-normal) var(--ease-standard);
}

.hero__visual[data-lens-active] .hero__img--soft {
  filter: blur(3.6px) saturate(0.92);
}

.hero__visual[data-lens-active] .hero__img--sharp {
  --lens-x: 50%;
  --lens-y: 50%;
  --lens-r: 8.5rem;
  mask-image: radial-gradient(
    circle var(--lens-r) at var(--lens-x) var(--lens-y),
    #000 52%,
    transparent 74%
  );
  -webkit-mask-image: radial-gradient(
    circle var(--lens-r) at var(--lens-x) var(--lens-y),
    #000 52%,
    transparent 74%
  );
}

.hero__lens-rim {
  position: absolute;
  z-index: 3;
  inline-size: calc(var(--lens-r, 8.5rem) * 2 * 0.63);
  aspect-ratio: 1;
  inset-block-start: var(--lens-y, 50%);
  inset-inline-start: var(--lens-x, 50%);
  translate: -50% -50%;
  border-radius: 50%;
  border: 1px solid color-mix(in oklab, var(--color-brass) 70%, transparent);
  box-shadow: 0 0 0 1px oklch(100% 0 0 / 0.55),
    0 12px 30px -12px oklch(21% 0.018 258 / 0.3);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--duration-normal) var(--ease-standard);
}

.hero__visual[data-lens-active] .hero__lens-rim {
  opacity: 1;
}

/* Touch and reduced-motion users get the plain sharp panel. */
@media (hover: none) {
  .hero__visual[data-lens-active] .hero__img--soft,
  .hero__visual[data-lens-active] .hero__lens-rim {
    display: none;
  }

  .hero__visual[data-lens-active] .hero__img--sharp {
    mask-image: none;
    -webkit-mask-image: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero__visual[data-lens-active] .hero__img--soft,
  .hero__visual[data-lens-active] .hero__lens-rim {
    display: none;
  }

  .hero__visual[data-lens-active] .hero__img--sharp {
    mask-image: none;
    -webkit-mask-image: none;
  }

  .vision__wash,
  .vision__layer--affected {
    transition: none;
  }
}
