  .label-radio {
    position: relative;
  }

  input[type='radio'] {
    z-index: 10;
  }
  .cms-thumbnail:has(input[type='radio']:hover) .border {
    border: 0.5px solid var(--_colors---ink-3);
    background: white;
  }
  .cms-thumbnail:has(input[type='radio']:checked) .border {
    background-color: var(--_colors---ink);
    border: 1px solid var(--_colors---ink);
  }

  .f-cms-thumbnail:has(input[type='radio']:checked) .f-border {
    border: 4px solid var(--_colors---ink);
  }

  .f-cms-thumbnail:has(input[type='radio']:checked) {
    background: white;
  }

  .f-cms-thumbnail:has(input[type='radio']:hover) {
    background: white;
  }
  .f-radio-button-field:has(input[type='radio']:checked) ~ .x-icon-white {
    z-index: 100;
  }

  .cms-thumbnail:has(input[type='radio']:checked) .thumbnail-label {
    color: white;
  }

  /* Frame thumbnail */

  /* .frame-thumbnail was renamed to .frame-component in the Designer; this
     selector had stopped matching, so the hover reveal was dead. */
  .frame-embed:hover ~ .frame-component .frame-info {
    opacity: 1;
  }

  .cms-thumbnail:has(input[type='radio']:checked) .frame-info {
    opacity: 1;
  }

  /* Show/hide 'select a ...' text */

  .prod-option-card .select-option {
    opacity: 0;
  }
  .prod-option-card:not(:has(input[type='radio']:checked)) .select-option {
    opacity: 1;
  }

  /* Add-to-cart button: dim until every required option is chosen */

  /* No JS and no class toggle. `:valid` / `:invalid` are native CSS
     pseudo-classes that a <form> carries automatically: a form matches
     :invalid while any control inside it fails constraint validation, and
     flips to :valid the moment they all pass. The browser recomputes this
     itself on every input change — there is nothing to listen to and nothing
     to keep in sync.

     There is no `is-ready` class and nothing here toggles one — an earlier
     draft of this did, and the name may still be floating around. `:valid` is
     a browser-maintained pseudo-class, so the class-toggling step that
     approach needed simply does not exist.

     Why this is the sturdy option: it reads the exact same constraint set the
     browser uses for its own "Please select one of these options" bubble. It
     cannot drift from the required fields, because it *is* the required
     fields — add or remove a `required` option group in the Designer and this
     follows with no code change.

     A wrinkle worth knowing, since it is easy to misread as a bug: `required`
     on radios is evaluated per group *name*, not per element. All 8 finish
     radios share name="finish", so checking one canvas finish satisfies the
     hidden metal and paper ones too. Only a group whose every member is
     hidden can be permanently unsatisfiable — that is why canvas-format gets
     explicitly disabled in ui-visibility.js and nothing else needs to be.

     Deliberately NOT paired with [disabled] on the button. The button stays
     clickable while dim so that clicking it triggers the native validation
     message; a disabled button silently does nothing and tells the customer
     less than the dim one does. */

  .ecom-atc-btn {
    transition: opacity 0.2s ease;
  }

  /* Only the lit state lives here. The dim state is whatever opacity
     .ecom-atc-btn already has in the Designer (0.44 as of writing) — leaving
     it there keeps the value editable in the Webflow UI instead of burying it
     in this file. Change the dim look in the Designer; this rule just says
     "and go full opacity once the form is satisfied".

     Scoped to .product-form because the Webflow cart is a second, separate
     <form> on this page. */
  .product-form:valid .ecom-atc-btn {
    opacity: 1;
  }
