/*
  MTCaptcha Demo Widget (brand overrides)
  ----------------------------------------------------------------------------
  Loaded AFTER /demo/vendor/mtcaptcha-demo.css (the untouched vendor
  stylesheet). This file only restyles: it never renames or removes a class or
  id the vendor JS depends on (see specs/demo-widget.md for the full list).

  v3 design strategy (rebuilt from scratch, see specs/demo-widget.md revision
  history for the full rationale):

  1. ONE card, not three. The vendor already renders its own themed card
     (.demo-loginbox: a white/off-white/dark box with its own border and
     background, different per theme). Earlier revisions wrapped that in a
     second bordered/shadowed box (.demoscreen) inside a third card supplied
     by the page (the hero's browser-chrome frame), so every theme showed as
     nested boxes-in-boxes. Here .demoscreen and .demo-canvas are made fully
     transparent, so the vendor's own themed card is the only visible surface
     inside the page's frame. As of 2026-08-06 that card carries **no drop
     shadow on a light page**, matching production exactly; the only elevation
     rule left is a 1px ring in dark mode, which production has no answer for
     because it has no dark mode. See the "Elevation" section below.
  2. Columns share one height (`align-items: stretch` on the grid) with the tab
     area top-anchored, so a content-driven height change on one side (e.g.
     Invisible Captcha's fallback challenge growing taller) resizes the row
     without shifting any content. See the note on .mtc-demo-grid below.
  3. Every toggle (Modern Mini, Invisible Captcha, Automated Test Mode) uses
     one shared switch component (.mtc-switchrow / .mtc-switch) instead of two
     different shapes with two different alignment models.
  4. Tab bar icons get a fixed, centered, aspect-ratio-preserving box, and
     fill/stroke color rules are keyed to each icon's own id and combined with
     the *button's* id for hover/active state. This matters because the
     vendor CSS itself already has hover/active icon-color rules keyed to
     `#theme-icon`/`#developers-icon` (see mtcaptcha-demo.css), which are MORE
     specific than a generic ".icon svg path" rule and were winning on hover,
     flashing icons white against a barely-tinted hover background. Beating
     that requires matching specificity with our own id-qualified selectors.

  IMPORTANT sizing note: the vendor's own responsive rules give `.demo-loginbox`
  a real max-width up to 350px (Standard theme) with 40-45px of horizontal
  padding on top (content-box sizing), so the finished card wants roughly
  420-450px to render its captcha challenge without clipping. The right column
  below is sized to guarantee that room; don't shrink it without re-checking
  the captcha renders uncropped at every theme and at Modern Mini.
*/

/* ---------- outer container ---------- */

#mtcaptcha-main-demo {
  display: block;
  background: transparent;
  padding: 0;
  border-radius: 0;
  font-family: 'Poppins', sans-serif;
  color: var(--body);
}

.mtc-demo {
  width: 100%;
}

.mtc-demo-grid {
  display: grid;
  gap: 1.25rem;
  margin-top: 1.5rem;
  /*
    456px, not 420px (changed 2026-08-05).

    The card's natural width is 440px: the vendor gives it 350px of content plus
    40px padding and a 5px border per side, content-box. A 420px column left only
    404px of content box, and because `.demo-canvas` makes the card a flex item
    it quietly shrank to fit rather than overflowing - taking the captcha down to
    314px with it. See the `flex-shrink: 0` note on `.demo-loginbox`.

    456 = 440 + `.demo-canvas`'s 8px inline padding per side. The two changes go
    together: `flex-shrink: 0` without this room converts the squeeze into an
    overflow, which is worse.
  */
  grid-template-columns: 1fr minmax(300px, 456px);
  /*
    Equal column heights (v5). This was `start` in v3 to stop the left panel
    "jumping" when the right side grew, but that fix treated the symptom: the
    jump came from `justify-content: center` on .mtc-demo-tabarea re-centering
    its content inside a changed height, not from stretch itself. The tab area
    is now top-anchored (`flex-start`), so both columns can share a height
    without anything shifting. Do not reintroduce `center` there.
  */
  align-items: stretch;
}

@media (max-width: 860px) {
  .mtc-demo-grid {
    grid-template-columns: 1fr;
    gap: 1rem;
  }
}

/* ---------- tab bar (segmented control) ---------- */

.mtc-demo-tabbar {
  display: flex;
  gap: 0.25rem;
  padding: 0.3rem;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 0.9rem;
}

/*
  setActiveTab() in the vendor JS overwrites these three buttons' className
  wholesale (to "badge-secondary category-badges w-inline-block[ w--current]"),
  so any custom class we put in the markup gets clobbered on the very first
  render. Target the stable ids instead, they're never touched by the JS.
*/
#demo-tabbtn-themes-a,
#demo-tabbtn-accessibility-a,
#demo-tabbtn-developers-a {
  display: flex !important;
  width: auto !important;
  height: auto !important;
  flex: 1 1 0;
  flex-direction: row !important;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  padding: 0.6rem 0.5rem;
  margin-left: 0 !important;
  border-radius: 0.6rem;
  border: none;
  background: transparent;
  cursor: pointer;
  transition: background-color 0.15s ease, box-shadow 0.15s ease, color 0.15s ease;
}

#demo-tabbtn-themes-a:hover,
#demo-tabbtn-accessibility-a:hover,
#demo-tabbtn-developers-a:hover {
  background: color-mix(in oklab, var(--surface) 60%, transparent);
}

#demo-tabbtn-themes-a.w--current,
#demo-tabbtn-accessibility-a.w--current,
#demo-tabbtn-developers-a.w--current {
  background: var(--surface);
  box-shadow: var(--shadow-card);
}

.mtc-demo-tabbar .demo-tabbtn {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--muted);
  white-space: nowrap;
  line-height: 1;
  transition: color 0.15s ease;
}

#demo-tabbtn-themes-a.w--current .demo-tabbtn,
#demo-tabbtn-accessibility-a.w--current .demo-tabbtn,
#demo-tabbtn-developers-a.w--current .demo-tabbtn {
  color: var(--color-brand-600);
}

/*
  axe, 2026-08-08, dark mode, active tab label ("Themes" is active by
  default so it is the one caught at first paint, but all three share this
  rule and would fail identically once clicked): brand-600 text on the dark
  canvas measured 3.08:1, under 4.5:1. Same root cause and same fix already
  applied to `.mtc-demo-cta` above and to LangSwitcher.astro - brand-600 is
  tuned for light backgrounds, brand-300 is its dark-mode counterpart.
*/
.dark #demo-tabbtn-themes-a.w--current .demo-tabbtn,
.dark #demo-tabbtn-accessibility-a.w--current .demo-tabbtn,
.dark #demo-tabbtn-developers-a.w--current .demo-tabbtn {
  color: var(--color-brand-300);
}

/*
  Fixed, centered, aspect-ratio-preserving icon slot. The vendor injects three
  differently-proportioned SVGs (40x40, 30x40, 36x34) with hardcoded width/
  height attributes straight into these spans via innerHTML on load; forcing
  them to an identical square with `width/height` in CSS would distort the
  narrower accessibility glyph. Constraining with max-width/max-height instead
  keeps every icon's own aspect ratio while giving all three the same visual
  footprint, which is what actually makes the row read as aligned.
*/
.mtc-demo-tabicon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.35rem;
  height: 1.35rem;
  flex-shrink: 0;
}

.mtc-demo-tabicon svg {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
}

/*
  Icon color, keyed per icon id rather than a blanket "svg path" rule, for two
  reasons found by reading the vendor CSS directly:
  1. The developers icon is a stroke-only line glyph (`fill="none"` on its own
     <svg>, drawn entirely with `stroke`). A shared `fill: var(--muted)` rule
     silently fills it solid, turning a thin "</>" bracket into a dark blob.
  2. The vendor CSS itself ships hover/active color rules scoped to
     `#theme-icon`/`#accessibility-icon`/`#developers-icon` (an id selector),
     which outrank a generic class-based rule on specificity and were winning
     on hover, flashing the icon white against our barely-tinted hover
     background. Matching specificity requires our own id-qualified selectors.
*/
#theme-icon-container svg path,
#accessibility-icon-container svg path {
  fill: var(--muted);
  stroke: none;
  transition: fill 0.15s ease;
}

#developers-icon-container svg path {
  fill: none;
  stroke: var(--muted);
  transition: stroke 0.15s ease;
}

#demo-tabbtn-themes-a:hover #theme-icon-container svg path,
#demo-tabbtn-themes-a.w--current #theme-icon-container svg path,
#demo-tabbtn-accessibility-a:hover #accessibility-icon-container svg path,
#demo-tabbtn-accessibility-a.w--current #accessibility-icon-container svg path {
  fill: var(--color-brand-600);
}

#demo-tabbtn-developers-a:hover #developers-icon-container svg path,
#demo-tabbtn-developers-a.w--current #developers-icon-container svg path {
  stroke: var(--color-brand-600);
}

@media (max-width: 480px) {
  .mtc-demo-tabbar {
    flex-direction: column;
  }
  #demo-tabbtn-themes-a,
  #demo-tabbtn-accessibility-a,
  #demo-tabbtn-developers-a {
    justify-content: flex-start !important;
    padding: 0.7rem 0.75rem;
  }
}

#mtcaptcha-main-demo hr {
  display: none;
}

/* ---------- tab pages (left column) ---------- */

.mtc-demo-tabarea {
  display: flex;
  flex-direction: column;
  /* Top-anchored, not centered: content keeps its position when the shared
     column height changes (see the .mtc-demo-grid note above). */
  justify-content: flex-start;
  gap: 1.1rem;
  min-height: 21rem;
  height: 100%;
  border-radius: 1rem;
  border: 1px solid var(--line);
  background: var(--surface);
  box-shadow: var(--shadow-card);
  padding: 1.5rem;
}

.demo-tabpage {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}

.demo-tabpage-invisible {
  display: none !important;
}

/* Icon + heading pairing reused by the Accessibility and Developers panels,
   so both read as one deliberate design system instead of two ad hoc ones. */
.mtc-demo-panel-head {
  display: flex;
  align-items: flex-start;
  gap: 0.85rem;
}

.mtc-demo-panel-title {
  margin: 0 0 0.3rem;
  font-size: 1rem;
  font-weight: 700;
  color: var(--ink);
}

.mtc-demo-panel-intro {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--body);
}

#options-container {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 0;
  min-height: 0;
  font-size: 0.9rem;
  margin: 0;
}

/* ---------- unified switch component ---------- */
/*
  Shared by Modern Mini, Invisible Captcha, and the Developers tab's test-mode
  toggle. One track size, one dot size, one alignment model (label on the
  left, switch on the right) everywhere a toggle appears in this widget.
*/
.mtc-switchrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-left: 0 !important;
  margin-bottom: 0;
  font-size: 0.9rem;
  color: var(--ink);
  cursor: pointer;
}

.mtc-switchrow-label {
  font-weight: 600;
  color: var(--ink);
}

/*
  Track and knob.

  Reshaped 2026-08-05 after review ("this switch needs better shape, not looking
  good"). Four changes, each for a reason:

  1. **Bigger.** 44x26 with a 20px knob, up from 38x22/16. The old one was
     under the 24x24 minimum that WCAG 2.5.8 asks of a pointer target, and it
     read as an afterthought beside a full-size label.
  2. **The off state is legible on its own.** It was `--surface-2` inside a
     `--line-strong` border, which on the light theme is a pale box on a pale
     panel: whether it was off or simply disabled was a guess. A filled track a
     clear step darker than the panel reads as "off", not "absent".
  3. **`translateX` rather than animating `left`.** Same movement, but it is
     composited, so the knob does not jitter on a slow frame. Paired with an
     ease-out curve that settles rather than stopping dead.
  4. **A focus ring, which did not exist.** The real checkbox is `opacity: 0`,
     so a keyboard user had no indication of which switch they were on. The ring
     is on `:focus-visible`, so it appears for keyboard use and not on click.
*/
.mtc-switch {
  position: relative;
  flex-shrink: 0;
  width: 44px;
  height: 26px;
  border-radius: 999px;
  border: 1px solid transparent;
  background-color: var(--line-strong);
  /*
    Only the colour transitions. `box-shadow` is deliberately excluded: it draws
    the keyboard focus ring, and fading that in over 180ms means a keyboard user
    tabbing quickly moves on before the indicator has finished appearing. Focus
    indication has to be immediate.
  */
  transition: background-color 0.18s ease;
}

.mtc-switchrow input:checked ~ .mtc-switch {
  background-color: var(--color-brand-600);
  border-color: transparent;
}

.mtc-switchrow:hover input:not(:checked) ~ .mtc-switch {
  background-color: color-mix(in oklab, var(--line-strong) 70%, var(--ink));
}

.mtc-switchrow:hover input:checked ~ .mtc-switch {
  background-color: var(--color-brand-500);
}

/*
  Keyboard focus. `:focus-visible` on the hidden input, drawn on the track, so
  it appears when tabbing and not when clicking - a ring that shows on every
  mouse click reads as a rendering fault.
*/
.mtc-switchrow input:focus-visible ~ .mtc-switch {
  box-shadow:
    0 0 0 2px var(--canvas),
    0 0 0 4px var(--color-brand-500);
}

/*
  The knob. The two-class selector is load-bearing, not decoration.

  This element is `class="demo-checkmark mtc-switch"`, so the vendor styles it
  too - as a *checkmark*:

      .demo-chkcontainer .demo-checkmark:after   (0,2,0)
        left: 6px; top: 2px; width: 5px; height: 10px;
        border: solid #fcfcfc; border-width: 0 3px 3px 0;
        transform: rotate(45deg);

  A bare `.mtc-switch:after` is (0,1,0) and loses to that on every property it
  does not mark `!important`. That is what shipped until 2026-08-05: `content`,
  `border` and `transform` were marked, which stripped the tick's borders and
  rotation but left its **5x10 geometry** intact - so the knob rendered as a thin
  white sliver pinned to the left of the track. Two rounds of "reshaping the
  switch" adjusted the track and never touched the actual fault, because the
  declaration here was correct the whole time and simply lost the cascade.

  Qualifying with `.mtc-switchrow` makes this (0,2,0), equal to the vendor rule,
  and demo-overrides.css loads after mtcaptcha-demo.css (see DemoWidget.astro),
  so equal specificity resolves our way. Geometry therefore needs no `!important`.
  The three that remain are still required: `content` and `border` because the
  vendor sets them from an equally specific rule, and `transform` because the
  checked state has to beat the vendor's `rotate(45deg)`.
*/
.mtc-switchrow .mtc-switch:after {
  content: '' !important;
  position: absolute;
  left: 3px;
  top: 3px;
  width: 18px;
  height: 18px;
  border: none !important;
  border-radius: 50%;
  background: #fff;
  transform: translateX(0) !important;
  transition: transform 0.18s cubic-bezier(0.2, 0.9, 0.3, 1);
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.28),
    0 0 0 1px rgba(0, 0, 0, 0.04);
}

.mtc-switchrow input:checked ~ .mtc-switch:after {
  transform: translateX(18px) !important;
}

/*
  The vendor also re-draws the checkmark's border on the checked state, from
  `.demo-chkcontainer input:checked ~ .demo-checkmark:after` (0,3,0). Matching
  that specificity here keeps the knob a plain dot when the switch is on;
  without it the knob grows two white edges the moment it is toggled.
*/
.mtc-switchrow input:checked ~ .mtc-switch:after {
  border: none !important;
}

/* A small press response, so the control feels answerable rather than inert. */
.mtc-switchrow:active .mtc-switch:after {
  width: 21px;
}

/*
  Respect a reduced-motion preference: the knob still moves, it just arrives
  immediately rather than sliding.
*/
@media (prefers-reduced-motion: reduce) {
  .mtc-switch,
  .mtc-switch:after {
    transition: none;
  }
}


/*
  Vendor bug we're exposing, not introducing: `.demo-chkcontainer
  .demo-checkmark:after` draws its checkmark border unconditionally
  (border-color #fcfcfc), relying on it being invisible against the vendor's
  own light-gray unchecked background. Our surface color is darker, so that
  "invisible" mark becomes visible. Hide it explicitly when unchecked.
*/
.demo-chkcontainer input:not(:checked) ~ .demo-checkmark:after {
  border-color: transparent;
}

/* ---------- theme swatches + buttons ---------- */

.theme-name {
  font-size: 0.85rem;
  color: var(--body);
  white-space: nowrap;
}

.mtc-demo-themebtns {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.mtc-demo-themebtns .category-badges.theme-btn {
  width: auto;
  height: auto;
  flex-direction: row;
  align-items: center;
  padding: 0.5rem 1rem 0.5rem 0.6rem;
  margin-left: 0 !important;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: var(--canvas);
  color: var(--ink);
  font-size: 0.85rem;
  font-weight: 600;
  gap: 0.55rem;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.mtc-demo-themebtns .category-badges.theme-btn:hover {
  border-color: var(--color-brand-500);
}

.mtc-demo-themebtns .category-badges.theme-btn.w--current {
  background: var(--color-brand-600);
  border-color: var(--color-brand-600);
  color: #fff;
}

/*
  Rounded-square color chips, not circles: a plain filled circle (especially
  Blackmoon's near-black one) reads as an ambiguous bullet or stray dot next
  to a label, not as an intentional color swatch. A chip shape with a visible
  ring reads unambiguously as "this button previews this color."
*/
.mtc-demo-swatch {
  display: inline-block;
  width: 0.95rem;
  height: 0.95rem;
  border-radius: 0.3rem;
  box-shadow: 0 0 0 1px var(--line-strong);
  flex-shrink: 0;
}

.mtc-demo-swatch--standard {
  background: #f5f7fa;
}

.mtc-demo-swatch--neowhite {
  background: #ffffff;
}

.mtc-demo-swatch--blackmoon {
  background: #1a1a1a;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.35);
}

.mtc-demo-themebtns .category-badges.theme-btn.w--current .mtc-demo-swatch {
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.6);
}

/* ---------- fields (select) ---------- */

.mtc-demo-field {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.mtc-demo-fieldlabel {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--muted);
}

/*
  The vendor pins .mtselect to `height: 30px` (mtcaptcha-demo.css). With our
  own vertical padding and Poppins' line box on top of that fixed height, the
  selected option was rendering taller than its own box and getting visually
  cut in half. Height is released to `auto` with a min-height floor so the
  text always has room, whatever the font or zoom level.
*/
.mtselect {
  height: auto;
  min-height: 2.5rem;
  line-height: 1.5;
  border-radius: 0.6rem;
  border: 1px solid var(--line-strong);
  background-color: var(--canvas);
  color: var(--ink);
  /*
    Symmetric 1rem sides, matching the contact form's `px-4` on every field.
    2026-08-06.

    Was `0.5rem 1.9rem 0.5rem 0.7rem` - 11.2px on the left against 30.4px on the
    right, so the label sat close to the border while a wide empty band ran down
    the right. Next to the Purpose select on /contact, which is an even 16px on
    both sides, the two read as different components rather than one control
    used twice.

    Both use the browser's native arrow, so nothing here has to reserve room for
    a custom icon - that asymmetric 1.9rem was never buying anything.

    Vertical padding stays 0.5rem rather than the form's 0.75rem: this select
    lives in a compact widget panel, and the horizontal alignment is what was
    inconsistent.
  */
  /*
    Every gap is 0.75rem (12px), matching the contact form's select:

        12px  gap from the right edge      (background-position)
        12px  the arrow itself             (background-size)
        12px  gap between text and arrow
        ----
        36px  = 2.25rem padding-right

    `appearance: none` is the load-bearing line. A native <select> paints its
    own arrow at an inset the browser chooses, which `padding-right` cannot
    move and which differs across Chrome, Safari and Firefox - so this select
    and the contact form's could never be made to match while both used it.

    These properties duplicate `.form-select` in global.css deliberately. This
    file is loaded by <link>, so it is unlayered and outranks Tailwind's utility
    layer; applying that class here would lose to the padding above. The icon is
    shared through `--select-chevron`, so the two cannot drift apart.
  */
  padding: 0.5rem 2.25rem 0.5rem 0.75rem;
  appearance: none;
  background-image: var(--select-chevron);
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  background-size: 0.75rem 0.75rem;
  font-family: inherit;
  font-size: 0.85rem;
}

.mtselect:focus {
  outline: 2px solid color-mix(in oklab, var(--color-brand-500) 50%, transparent);
  outline-offset: 1px;
}

/* ---------- help / comment text + CTA buttons ---------- */

.demo-comment {
  color: var(--muted);
  background: var(--subtle);
  border: 1px solid var(--line);
  border-radius: 0.85rem;
  padding: 1rem 1.1rem;
  line-height: 1.6;
  font-size: 0.9rem;
}

.demo-comment p {
  margin: 0 0 0.6rem;
}

.demo-comment p:last-child {
  margin-bottom: 0;
}

.mtc-demo-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: none;
  border-radius: 999px;
  padding: 0.5rem 0.9rem;
  background: color-mix(in oklab, var(--color-brand-500) 14%, transparent);
  color: var(--color-brand-600);
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s ease, transform 0.15s ease;
}

.mtc-demo-cta:hover {
  background: color-mix(in oklab, var(--color-brand-500) 22%, transparent);
  transform: translateX(1px);
}

/*
  brand-600 text on this pill's tinted background measures fine in light mode
  (the 14% brand-500-over-white mix is light), but the same mix over dark
  mode's near-black canvas is a dark purple, and brand-600 text on it drops to
  2.8:1 (found via axe-core, 2026-08-06). brand-300 is the site's established
  swap for exactly this: LangSwitcher.astro and the footer already use
  dark:text-brand-300 for 14px text needing the AAA 7:1 this site publishes.
*/
.dark .mtc-demo-cta {
  color: var(--color-brand-300);
}

.mtc-demo-cta--filled {
  background: var(--color-brand-600);
  color: #fff;
  align-self: flex-start;
}

.mtc-demo-cta--filled:hover {
  background: var(--color-brand-700, var(--color-brand-600));
}

.mtc-demo-cta-icon {
  width: 0.9em;
  height: 0.9em;
  flex-shrink: 0;
}

/* ---------- accessibility tab ---------- */

.mtc-demo-a11y {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  color: var(--body);
}

.mtc-demo-a11y-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 0.75rem;
  background: color-mix(in oklab, var(--color-brand-500) 14%, transparent);
  color: var(--color-brand-600);
  flex-shrink: 0;
}

.mtc-demo-a11y-icon svg {
  width: 1.3rem;
  height: 1.3rem;
}

/* Keyboard shortcuts as a short, scannable list instead of one run-on
   sentence stitched together from several translation strings, that read as
   machine-generated filler rather than crafted UI copy. */
.mtc-demo-shortcuts {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.mtc-demo-shortcuts li {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  font-size: 0.88rem;
  color: var(--body);
}

.mt-keybox {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.7rem;
  height: 1.7rem;
  padding: 0 0.4rem;
  border-radius: 0.45rem;
  border: 1px solid var(--line-strong);
  background: var(--canvas);
  box-shadow: 0 1px 0 var(--line-strong);
  /*
    Poppins, like everything else. 2026-08-06, by instruction: one typeface
    across the whole site, no exceptions.

    These are keycaps showing a literal keyboard key, and they were previously
    monospace on purpose - a keycap reads as a key rather than as prose, and the
    stack was spelled out so every platform rendered the same glyphs. That
    reasoning was sound but is now overridden by the single-typeface rule. The
    border, padding and background still carry the "this is a key" signal, so
    the cue survives the font change.
  */
  font-family: inherit;
  font-size: 0.85rem;
  flex-shrink: 0;
}

.mtc-demo-invisible-status {
  margin-top: 0.75rem;
}

.mtc-demo-spinner {
  display: inline-block;
  width: 0.9em;
  height: 0.9em;
  margin-right: 0.4em;
  border: 2px solid color-mix(in oklab, var(--color-brand-500) 35%, transparent);
  border-top-color: var(--color-brand-600);
  border-radius: 50%;
  vertical-align: -0.15em;
}

.mtc-demo-check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.1em;
  height: 1.1em;
  margin-right: 0.4em;
  border-radius: 50%;
  background: var(--color-brand-600);
  color: #fff;
  font-size: 0.75em;
  vertical-align: -0.1em;
}

/* ---------- developer tab ---------- */

#demo-tabpage-developers {
  gap: 1.1rem !important;
}

.demo-devmodecomments {
  color: var(--body);
}

.demo-devmodecomments > p:first-child {
  margin: 0 0 0.85rem;
  font-size: 0.9rem;
}

.demo-devmodecomments code,
.demo-devmodecomments p code {
  background: var(--surface-2);
  border-radius: 0.35rem;
  padding: 0.1em 0.4em;
  font-size: 0.9em;
}

/* ---------- live demo screen (right column) ---------- */

/* The right column is a flex chain down to .demo-canvas so it fills the shared
   row height. The login card itself is never stretched, it stays its natural
   vendor size and centers in whatever height the row ends up being. */
/*
  The right column gets the same frame as the left (.mtc-demo-tabarea), added
  2026-08-06 by instruction: border, radius and surface so the two halves of the
  demo read as a matched pair instead of one card floating beside loose content.

  Border and background only - **no box-shadow**. The left panel carries
  `--shadow-card`, but the vendor's own login card (.demo-loginbox) already has
  its own elevation one level down; adding a second shadow here is what produced
  the "three layers of background" this file warns about below. One border, one
  surface, and the inner card keeps its own depth.
*/
.mtc-demo-screen-container {
  width: 100%;
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  border-radius: 1rem;
  border: 1px solid var(--line);
  background: var(--surface);
  padding: 1.5rem;
}

/*
  No border, background, or shadow on .demoscreen or .demo-canvas: the vendor
  already renders its own themed card one level down (.demo-loginbox), and
  stacking our own card around it produced the "three layers of background"
  effect, most visible on Blackmoon where a dark card sat inside a light
  vendor canvas inside our own bordered/shadowed frame. Depth now comes from a
  single box-shadow applied directly to .demo-loginbox further down, so there
  is exactly one visible surface per state.
*/
.demoscreen,
.demo-theme-standard .demo-canvas,
.demo-theme-neowhite .demo-canvas,
.demo-theme-blackmoon .demo-canvas {
  background: transparent;
}

.demoscreen {
  width: 100% !important;
  flex: 1;
  display: flex;
  flex-direction: column;
}

.demo-canvas {
  min-height: 300px;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 0.5rem;
  overflow: visible;
  transition: min-height 0.2s ease;
}

/* Modern Mini's form is much shorter; without this the canvas keeps its full
   min-height and the compact form looks lost in a mostly-empty box. Reading
   the mini state straight off the DOM (:has()) instead of adding a JS hook
   keeps every vendor className assignment untouched. */
.demo-canvas:has(.demo-captchabox-mini) {
  min-height: 190px;
}

/*
  Deliberately NOT adding overflow-x:auto/hidden anywhere in this ancestor
  chain (.demo-loginbox, .demo-captchabox, .demoscreen, .demo-canvas): any of
  them would clip or force-scroll Modern Mini's intentionally-overflowing
  compact layout. Verified via direct measurement that the captcha iframe
  (real width) stays within .demo-loginbox at both mobile (375px) and desktop
  widths; keep re-verifying this after any width change.
*/

.demo-loginbox {
  /*
    `flex-shrink: 0` is the load-bearing line here, added 2026-08-05.

    `.demo-canvas` above is `display: flex`, which is ours - production's is a
    plain block. That one difference makes this card a **flex item**, and a flex
    item's default `flex-shrink: 1` lets the layout compress it below its
    declared size. It was being compressed by exactly 36px: the vendor sizes the
    card `width: 100%; max-width: 350px` (content-box) in its
    `@media (min-width: 371px)` bucket, so it wants 350 + 40px padding + 5px
    border per side = 440px, and the available content box was 404px. The card
    landed at 314px of content, and **the captcha inside it rendered at 314px
    instead of 350px** - about 10% narrower than the vendor designs for, on every
    desktop view. Nothing clipped, so nothing looked broken.

    On production the card is a block box: it takes its 350px and simply
    overflows its 384px parent, which is why it keeps its full size there.

    Note the vendor's `min-width: 350px !important` (line ~785) is NOT what
    protects this - the vendor cancels it itself for the Standard theme with
    `min-width: unset !important` (~line 239). There is no floor to fall back on,
    which is why the shrink has to be disabled at the flex level.

    Pairs with the 456px column in `.mtc-demo-grid`: without the room, refusing
    to shrink just turns the squeeze into an overflow.
  */
  flex-shrink: 0;
  /* Let the vendor's own responsive max/min-width rules govern the size itself;
     they're already tuned to fit the captcha challenge without clipping. We only
     guarantee the surrounding boxes (above) never squeeze it smaller. */
  margin-inline: auto;
  transition: box-shadow 0.2s ease;
}

/*
  Real mobile clipping, found after a screenshot showed the captcha's audio
  icon, text input, and footer cut off on the right at 375px, even though the
  outer page had zero horizontal scroll (document.scrollWidth === clientWidth).
  That measurement was the wrong check: the captcha itself renders inside a
  cross-origin iframe, so if its own content needs more width than we give
  its container, the overflow happens *inside the iframe's own browsing
  context* and never touches the parent page's scrollWidth at all, while the
  hero section's own `overflow-hidden` (needed for its decorative background
  blobs) visibly clips it. The actual bug was a width *budget* problem: by the
  time you subtract the page gutter (container-page, 24px/side), the hero
  card's own padding, and this canvas's padding, `.demo-loginbox` was only
  reaching vendor's >=371px breakpoint (40px padding + 5px border/side) with
  as little as ~179px left for the captcha itself, well under what the vendor
  designed for. Reclaim width specifically at narrow viewports: the vendor's
  own breakpoints already assume a generous parent, so this overrides its
  padding down near its own <350px bucket instead of the >=371px one a 375px
  screen would otherwise land in.
*/
@media (max-width: 600px) {
  .demo-canvas {
    padding-inline: 0;
  }

  .demo-loginbox,
  .demo-theme-standard .demo-loginbox,
  .demo-theme-neowhite .demo-loginbox,
  .demo-theme-blackmoon .demo-loginbox {
    padding: 14px !important;
    border-width: 2px !important;
    /*
      Added 2026-08-17 after QE saw the Neowhite card clipped on the right at
      375px while Standard was fine.

      The vendor sizes this card `width: 100%; max-width: <n>px` with
      `box-sizing: content-box` (line ~232). Under content-box, `width: 100%`
      means the *content* alone equals the parent's full width, and padding and
      border are then added *outside* it - so the card is always wider than its
      parent by exactly padding + border, whatever the padding is reduced to.
      Combined with the `flex-shrink: 0` above (load-bearing for a different
      bug, see its note) nothing can pull it back, so it just overflows.

      Neowhite shows it first because it is the widest-padded theme in the
      vendor sheet (45px against Standard's 40px), but the geometry is wrong
      for every theme; Standard was simply close enough to fit.

      `border-box` folds padding and border back inside the declared width, and
      `max-width: 100%` caps the card at its parent regardless of the vendor's
      per-theme max-width. Scoped to <=600px so desktop keeps the vendor's own
      intended content-box sizing untouched.
    */
    box-sizing: border-box !important;
    max-width: 100% !important;

    /*
      `flex-shrink: 0` (see its own note above) is what stops this card being
      squeezed below the size the vendor designs for. That is right on desktop,
      where there is spare room; on a phone there is none, so refusing to shrink
      just pushes the overflow up to the parent instead of fixing it. Now that
      `border-box` above makes the card's declared width honest, letting it
      shrink is safe: it tracks the container rather than a fixed 314px.
    */
    flex-shrink: 1 !important;
  }

  /*
    The actual "right side is cut off" bug, measured 2026-08-17 at 375px:

      .mtc-demo-screen-container   l=31  r=395  w=364   <- 51px wider
      .mtc-demo-grid (its parent)  l=31  r=344  w=313

    The container was 51px wider than its own parent and spilled to the right,
    where an ancestor's `overflow: hidden` (the hero's decorative-blob clip)
    cut it off. Everything inside it was correctly centered *within the
    container*, which is why the card looked internally fine while the whole
    assembly sat too far right.

    Two causes, both needed: the container is a flex parent, so it defaults to
    `min-width: auto` and cannot shrink below its content, and its own 1.5rem
    padding sits outside that content. Below `sm` the page gutter already
    provides the breathing room this padding was for.
  */
  .mtc-demo-screen-container {
    min-width: 0;
    max-width: 100%;
    padding: 0.75rem;
  }

  /*
    Make the card track its container instead of sizing itself. The vendor
    gives it `width: 93%` (<=350px bucket) or `width: 100%` (>=371px) against a
    flex parent whose own width depends on this card - circular enough that it
    settled on its 350px max-width rather than the space actually available.
    `width: 100%` against a container that is now definitively sized removes
    the circularity.
  */
  .demo-loginbox,
  .demo-theme-standard .demo-loginbox,
  .demo-theme-neowhite .demo-loginbox,
  .demo-theme-blackmoon .demo-loginbox {
    width: 100% !important;
    min-width: 0 !important;
  }
}

/*
  Smallest phones (<=380px covers 320 and 360 wide devices).

  The vendor floors the card at `min-width: 270px` in its <=350px bucket, and
  unlike the >=371px bucket it never unsets that per theme. At 320px the page
  gutter (24px each side) plus this container's own padding left roughly 258px,
  so the card could not reach its floor and overflowed by ~46px per side -
  centered, so it was clipped symmetrically rather than looking obviously
  broken.

  Dropping this container's padding to zero returns 24px, which puts the
  available width back above the vendor's floor. The page gutter outside it
  still provides visible breathing room, so nothing looks edge-to-edge.
*/
@media (max-width: 380px) {
  .mtc-demo-screen-container {
    padding: 0;
  }
}

/*
  Elevation: none on a light page, matching production.

  Removed 2026-08-06. This block previously carried one box-shadow per
  (widget theme x site mode) pairing - six rules. Measured against the real card
  on www.mtcaptcha.com:

      production   radius 24px   border 5px solid #fff   bg rgba(255,255,255,.9)
                   padding 25px 40px 20px   box-shadow: NONE

  Every one of those already matches what the vendor CSS produces here. The
  shadow was the only thing we had added to the card, and therefore the only
  thing making it look unlike production's.

  The dark-mode 1px ring that used to live here is gone too, 2026-08-06.

  It existed for a real reason: the Standard theme adopts the site's dark
  surface, so on a dark page the card was a dark box on a dark background with a
  5px border of nearly the same colour - no visible edge at all. The ring
  restored that boundary.

  `.mtc-demo-screen-container` now carries a border of its own, matching the
  left panel, and that supplies the edge instead. Keeping both drew **two
  concentric lines** around the login card, which is what it looked like: a
  frame inside a frame. One boundary per card.
*/

/* ---------- Standard theme follows the site's own light/dark mode ---------- */
/*
  Standard is the demo's default theme and the only one that tracks the host
  page: white card on a light page (the vendor's own look, untouched), and the
  site's dark surface on a dark page, so it doesn't sit there as a white slab.
  Neowhite and Blackmoon are deliberately left exactly as the vendor ships
  them, since those two exist to show the product's own fixed themes.

  The vendor's own rules are `.demo-theme-standard .demo-*` (specificity 0,2,0)
  and some sit inside media queries; adding `.dark` in front (0,3,0) beats them
  everywhere without !important.

  Known limit: the captcha challenge itself renders in a cross-origin iframe
  whose styling comes from `mtcaptchaConfig.theme`, which the vendor's setTheme()
  sets to null (its default light look) for Standard. CSS in this file cannot
  reach inside that iframe, so the challenge block stays light within the
  darkened card. Changing it would mean overriding the vendor's captcha config
  for Standard, which would misrepresent what the product's Standard theme
  actually looks like to a customer evaluating it.
*/
/* The vendor gives this card `border: 5px solid #ffffff`, which is invisible
   on a white page and a glaring white frame on a dark one. It is really just
   inset spacing, so it takes the card's own color rather than being removed
   (removing it would shrink the card and squeeze the captcha). */
.dark .demo-theme-standard .demo-loginbox {
  background-color: var(--surface);
  border-color: var(--surface);
}

.dark .demo-theme-standard .demo-welcomesm {
  color: var(--ink);
}

/*
  Vendor's own Standard-theme label color (#777777 on white) measures 4.47:1,
  just under the 4.5:1 AA threshold for normal text (found via axe-core,
  2026-08-06). #707070 is visually indistinguishable from the vendor's
  original at this size and clears 4.95:1. Not gated on .dark, since the
  vendor's own light-mode color was the one failing; the .dark override
  below still wins in dark mode on selector specificity.
*/
.demo-theme-standard .demo-label {
  color: #707070;
}

/*
  Vendor's own Standard-theme submit button (#666BFF background, white text)
  measures 4.1:1, also under 4.5:1 (same audit). var(--color-brand-600) is
  the same blue every other primary button on the site already uses and
  clears 6.2:1; using it here instead of a one-off hex keeps this button
  consistent with the rest of the page's palette, not just compliant.
*/
.demo-theme-standard .demo-submitbtn {
  background-color: var(--color-brand-600);
}

.demo-theme-standard .demo-submitbtn:active {
  background-color: var(--color-brand-700, var(--color-brand-600));
}

.dark .demo-theme-standard .demo-label {
  color: var(--muted);
}

.dark .demo-theme-standard .demo-inputtxt {
  background-color: var(--canvas);
  border-color: var(--line-strong);
  color: var(--ink);
}

/*
  Vendor forces the invisible-mode captcha box to a fixed 23px (tall enough
  for just a "verifying..." line). In this demo, invisible mode can still fall
  back to a visible challenge (no real behavioral signal to judge), which then
  overflowed into the Sign In button below. Let it grow instead of overlap.
*/
.demo-captchabox-invisible {
  height: auto !important;
  min-height: 23px;
  margin-bottom: 0.5rem;
}

/* ---------- video modal ---------- */

.mtc-demo-videomodal {
  position: fixed;
  inset: 0;
  z-index: 100;
}

.mtc-demo-videomodal-backdrop {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: rgba(4, 9, 26, 0.72);
  backdrop-filter: blur(2px);
}

.mtc-demo-videomodal .video-mod-box {
  width: 100%;
  max-width: 48rem;
  border-radius: 1rem;
  overflow: hidden;
  background: #000;
  box-shadow: var(--shadow-lift);
  aspect-ratio: 16 / 9;
  display: flex;
  flex-direction: column;
}

.mtc-demo-videomodal-bar {
  display: flex;
  justify-content: flex-end;
  padding: 0.5rem 0.75rem;
  background: #000;
}

.mt-videoclosebtn {
  border: none;
  background: transparent;
  color: #fff;
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
  opacity: 0.8;
  cursor: pointer;
}

.mt-videoclosebtn:hover {
  opacity: 1;
}

.mtc-demo-videomodal iframe {
  flex: 1;
  width: 100%;
  border: 0;
}

/* ---------- dark mode (general text colors) ---------- */

.dark .demo-comment,
.dark .demo-chkcontainer,
.dark .theme-name,
.dark .mtc-demo-a11y,
.dark .demo-devmodecomments {
  color: var(--body);
}

/* ---------- email field: icon and text on one line ---------- */

/*
  The vendor gives the username input `width: 100%` in both Neowhite and
  Blackmoon, while the password input right below it gets `width: auto`. Both
  sit next to a 35px inline-block icon label, so the 100% one cannot fit
  beside its icon and wraps to the next line: the mail icon ends up alone on
  row one with the address underneath, while the key icon stays inline with
  the password. Two fields, two different layouts, from one property.

  Fixed by giving the box a flex row and letting the input take the leftover
  space (`min-width: 0` so a long address shrinks instead of forcing the
  overflow back). `width: auto` alone would match the password rule but sizes
  the field to its `size` attribute, which is narrower than the demo address.

  The password box gets the same treatment so both rows share one alignment
  model rather than agreeing by coincidence. Vendor ids/classes are only
  restyled here, never renamed - see the file header.
*/
/*
  CORRECTION 2026-08-17, same day: this originally covered Blackmoon too, which
  was wrong. The two themes position their icons by completely different means:

    Neowhite    #demo-label-*  display: inline-block   -> in normal flow
    Blackmoon   #demo-label-*  position: absolute; right: 5px -> out of flow

  Only Neowhite's icon is laid out beside the input, so only Neowhite can have
  the wrapping bug. Blackmoon's icon floats over the field's right edge by
  design, and making its box a flex container did nothing for the icon while
  letting the input run its text underneath it - the reported overlap. Blackmoon
  is handled separately below.
*/
.demo-theme-neowhite .demo-usernamebox,
.demo-theme-neowhite .demo-passwordbox {
  display: flex;
  align-items: center;
  /* Flex containers default to min-width:auto, which lets a long value push
     the whole login card wider than its parent. */
  min-width: 0;
}

.demo-theme-neowhite #demo-inputusername,
.demo-theme-neowhite #demo-password {
  flex: 1;
  width: auto;
  min-width: 0;
}

/* The icon labels must not stretch or shrink out of their fixed 35px box. */
.demo-theme-neowhite #demo-label-username1,
.demo-theme-neowhite #demo-label-password1 {
  flex: none;
}

/*
  Blackmoon: the icon sits *over* the field's right edge (position:absolute,
  right:5px, 35px wide). Nothing reserves space for it, so a long value like
  `super.mountain@example.com` runs straight under the glyph - visible at 375px
  where the field is narrow enough for the text to reach that far. Reserve the
  icon's width plus its offset as padding instead of changing the layout model,
  which is what the vendor design intends and what the wider desktop field was
  accidentally providing.
*/
.demo-theme-blackmoon #demo-inputusername,
.demo-theme-blackmoon #demo-password {
  padding-right: 45px;
  box-sizing: border-box;
}
