/* Pekan Designs OS conversion modal, dock action and contextual nudge. */

#pk-dock-cta {
  display: flex;
  align-items: center;
  gap: 7px;
  width: auto;
  min-width: 0;
  height: 40px;
  margin: 0 3px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 12px;
  padding: 0 14px;
  background: linear-gradient(120deg, #838aff, #5856e9);
  box-shadow: 0 8px 24px rgba(88, 86, 233, 0.34);
  color: #fff;
  cursor: pointer;
  font-size: 12px;
  font-weight: 800;
  white-space: nowrap;
  transition:
    transform 150ms ease,
    filter 150ms ease;
}

#pk-dock-cta:hover {
  transform: translateY(-1px);
  filter: brightness(1.08);
}

/* Round 5, plan 2.1: the conversion modal was deleted. What stood here was a
   sheet with a business field, an email field and a trust row, which is a
   website contact form with a title bar drawn on it. Every capture is now a
   system surface: the lock takes the number, Software Update takes the email
   inside its own toast, and PEKAN.open() routes rather than builds.
   The Update toast geometry lives further down, under the notifications. */

/* This is the primary conversion action, so it keeps its label on phones.
   Room is made by dropping the dock pins, which are redundant there because
   every app icon is already on screen. A bare lightning bolt converts nobody. */
@media (max-width: 620px) {
  #pk-dock-cta {
    height: 38px;
    padding: 0 14px;
    font-size: 13px;
  }
}

/* Only on the narrowest handsets does the label finally give way. */
@media (max-width: 360px) {
  #pk-dock-cta span {
    display: none;
  }

  #pk-dock-cta {
    padding: 0 12px;
  }
}

/* =====
   System notifications. Bottom right, stacked, sliding in from the edge the
   way an OS toast does. This is where the desktop asks for things now: there
   is no dock button and no panel pinned to the wallpaper.
   ===== */
#pk-toasts {
  position: fixed;
  right: 16px;
  bottom: 74px;
  z-index: 999998;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-end;
  pointer-events: none;
}

/* Keep notifications queued in the DOM while the visitor uses Start.
   They return when the menu closes, without covering its launch targets. */
body:has(#start-menu.show) #pk-toasts {
  visibility: hidden;
}

.pk-toast {
  width: min(360px, calc(100vw - 32px));
  border: 1px solid var(--pk-glass-border, rgba(255, 255, 255, 0.25));
  border-radius: var(--pk-radius-panel, 16px);
  padding: 14px 15px 15px;
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.085), rgba(131, 138, 255, 0.045)),
    var(--pk-glass-surface, rgba(18, 18, 22, 0.66));
  box-shadow: var(--pk-glass-shadow, 0 22px 60px rgba(0, 0, 0, 0.5));
  color: var(--pk-text, #fff);
  font-family: var(--pk-font, var(--pd-font));
  opacity: 0;
  pointer-events: auto;
  transform: translateX(24px);
  transition:
    opacity var(--pk-duration, 240ms) var(--pk-ease, ease),
    transform var(--pk-duration, 240ms) var(--pk-ease, cubic-bezier(0.16, 1, 0.3, 1));
  backdrop-filter: var(--pk-glass-blur, blur(32px) saturate(125%));
  -webkit-backdrop-filter: var(--pk-glass-blur, blur(32px) saturate(125%));
}

.pk-toast.show {
  opacity: 1;
  transform: none;
}

/* Header carries the sending app, the way a real notification identifies
   itself before it says anything. */
.pk-toast-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 9px;
}

.pk-toast-icon {
  width: 17px;
  height: 17px;
  border-radius: 4px;
  object-fit: cover;
}

.pk-toast-app {
  flex: 1 1 auto;
  overflow: hidden;
  color: #b3aacd;
  font-size: 11px;
  letter-spacing: 0.02em;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pk-toast-x {
  display: grid;
  flex: 0 0 20px;
  place-items: center;
  width: 20px;
  height: 20px;
  border: 0;
  border-radius: 5px;
  background: transparent;
  color: #b3aacd;
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
}

.pk-toast-x:hover {
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
}

.pk-toast h4 {
  margin: 0 0 4px;
  font-size: 14px;
  font-weight: 700;
}

.pk-toast p {
  margin: 0;
  color: #cdc6e0;
  font-size: 12.5px;
  line-height: 1.45;
}

.pk-toast-form {
  display: flex;
  gap: 7px;
  margin-top: 11px;
}

.pk-toast-form input {
  flex: 1 1 auto;
  min-width: 0;
  border: 1px solid var(--pk-glass-border, rgba(255, 255, 255, 0.25));
  border-radius: var(--pk-radius-control, 10px);
  padding: 0 10px;
  height: 34px;
  background: var(--pk-glass-panel, rgba(255, 255, 255, 0.065));
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.22);
  color: var(--pk-text, #fff);
  font-size: 12.5px;
}

.pk-toast-form input:focus {
  border-color: var(--pk-accent-light, #838aff);
  outline: none;
}

.pk-toast-form button {
  flex: 0 0 auto;
  height: 34px;
  border: 0;
  border-radius: var(--pk-radius-control, 10px);
  padding: 0 14px;
  background: var(--pk-accent, #5956e9);
  color: #fff;
  cursor: pointer;
  font-size: 12.5px;
  font-weight: 700;
}

.pk-toast-form button:disabled {
  cursor: default;
  opacity: 0.65;
}

.pk-toast-actions {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

.pk-toast-actions button {
  height: 32px;
  border: 1px solid var(--pk-glass-border, rgba(255, 255, 255, 0.25));
  border-radius: var(--pk-radius-control, 10px);
  padding: 0 13px;
  background: var(--pk-glass-panel, rgba(255, 255, 255, 0.065));
  color: var(--pk-text, #fff);
  cursor: pointer;
  font-size: 12.5px;
  font-weight: 600;
}

.pk-toast-actions .yes {
  border-color: transparent;
  background: var(--pk-accent, #5956e9);
  color: #fff;
}

/* the notification's email permission row, same contract as the update card:
   a real unchecked control, a 44 px target, and the sentence that gets stored */
.pk-toast-consent {
  display: flex;
  gap: 10px;
  align-items: center;
  min-height: 44px;
  margin-top: 9px;
  border: 1px solid var(--pk-glass-hairline, rgba(255, 255, 255, 0.12));
  border-radius: var(--pk-radius-control, 10px);
  padding: 8px 10px;
  background: var(--pk-glass-panel, rgba(255, 255, 255, 0.065));
  cursor: pointer;
}

/* Same collapse as the diagnostic queue: `.pk-toast-form input` above is the
   text-field rule (flex:1 1 auto, min-width:0), and the checkbox sits in that
   form, so it computed to 6 px wide. Measured, not guessed. */
.pk-toast-form .pk-toast-consent-box,
.pk-toast-consent-box {
  flex: 0 0 auto;
  width: 20px;
  min-width: 20px;
  height: 20px;
  min-height: 20px;
  margin: 0;
  padding: 0;
  border-radius: 4px;
  accent-color: var(--pk-accent, #5956e9);
  cursor: pointer;
}

/* the form now stacks: field, permission row, error, button */
.pk-toast-form {
  flex-wrap: wrap;
}

.pk-toast-form .pk-toast-consent,
.pk-toast-form .pk-toast-err {
  flex: 1 1 100%;
}

.pk-toast-consent-line {
  color: var(--pk-text, #fff);
  font-size: 11.5px;
  line-height: 1.45;
  opacity: 0.92;
}

.pk-toast-consent-box:focus-visible,
.pk-toast-consent-box[aria-invalid="true"] {
  outline: 2px solid var(--pk-text, #fff);
  outline-offset: 3px;
}

.pk-toast-consent-box[aria-invalid="true"] {
  outline-color: #ffb4b4;
}

.pk-toast-err {
  margin: 7px 0 0;
  color: #ffb4b4;
  font-size: 12px;
}

/* the Found Score report queue: same control, inside the diagnostic window */
.dg-consent {
  display: flex;
  gap: 10px;
  align-items: center;
  min-height: 44px;
  margin: 10px 0 0;
  border: 1px solid var(--pk-glass-hairline, rgba(255, 255, 255, 0.12));
  border-radius: var(--pk-radius-control, 10px);
  padding: 8px 10px;
  background: var(--pk-glass-panel, rgba(255, 255, 255, 0.065));
  cursor: pointer;
}

/* MEASURED 2026-09-05: pekan/os2031.css:1121 styles `#win-diag .dg-form input`
   with flex:1 and min-width:0, which is the text-field rule. The consent
   checkbox lives inside that same form, so it inherited the rule and computed
   to width:0px: present in the DOM, hit-testable by nothing, invisible to a
   visitor and to Playwright. That file is the shell lane, so the override
   lives here and matches its specificity (id + two classes) rather than
   reaching for !important or editing another owner's file. */
#win-diag .dg-form .dg-consent-box,
.dg-consent-box {
  flex: 0 0 auto;
  width: 20px;
  min-width: 20px;
  height: 20px;
  min-height: 20px;
  margin: 0;
  padding: 0;
  border-radius: 4px;
  accent-color: var(--pk-accent, #5956e9);
  cursor: pointer;
}

/* the row itself is not a text input either */
#win-diag .dg-form .dg-consent {
  flex: 1 1 100%;
}

/* the queue form stacks now that it carries a field, a permission row, an
   error slot and a button, rather than sitting on one line */
#win-diag .dg-queue-form {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

#win-diag .dg-queue-form .dg-err,
#win-diag .dg-queue-form .dg-known {
  flex: 1 1 100%;
}

.dg-consent-line {
  color: var(--pk-text, #fff);
  font-size: 11.5px;
  line-height: 1.45;
  opacity: 0.92;
}

.dg-consent-box:focus-visible {
  outline: 2px solid var(--pk-text, #fff);
  outline-offset: 3px;
}

.dg-consent-box[aria-invalid="true"] {
  outline: 2px solid #ffb4b4;
  outline-offset: 3px;
}

/* the address the queue will actually use, shown instead of a blank field
   when the profile already holds one */
.dg-known {
  margin: 0 0 4px;
  color: var(--pk-text, #fff);
  font-size: 12.5px;
  opacity: 0.92;
}

.dg-err {
  margin: 7px 0 0;
  color: #ffb4b4;
  font-size: 12px;
}

.pk-toast-actions button:hover {
  filter: brightness(1.12);
}

/* On a phone the stack spans the width and sits above the dock. */
@media (max-width: 620px) {
  #pk-toasts {
    right: 12px;
    left: 12px;
    bottom: 70px;
    align-items: stretch;
  }

  .pk-toast {
    width: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .pk-toast {
    transition: opacity 240ms ease;
    transform: none;
  }
}

/* =====
   Round 5, plan 2.3 and 4.2: the Software Update toast.

   Windows 11 notification geometry, because that is the shape the owner
   asked for and the shape a business owner recognises as a system telling
   them something: bottom right, 364 px, app name over a body line, and the
   field inside the card rather than behind a click. The radius is the
   os-r-toast token, 8 px, the real Windows number. It is declared here as a
   fallback only: os2031.css loads after this file, so if the glass pass
   defines the token, the glass pass wins.

   None of the Windows artwork, none of its fonts, none of its icons. The
   refresh glyph is our own two arc mark, drawn in swarm-free CSS and SVG.
   ===== */
:root {
  --os-r-toast: var(--r-card, 12px);
}

/* Round 11: the landing notification and the Software Update toast share the
   bottom right corner. When the update toast is present, the notification
   stack moves up so neither paints over the other.

   MEASURED 2026-09-05, and the reason this is not keyed on `.show`: the
   update toast is 440 px tall once the service list and the permission row
   are open, and #pk-toasts sits at z-index 999998 against the toast's 999997.
   Keying the offset on `.show` meant any toast that had not yet been given
   that class, including the one a QA entry raises, left the notification
   stack painting straight over the consent control. elementFromPoint at the
   centre of the permission row returned .pk-toast-actions, so a visitor could
   see the sentence and not be able to reach the box.

   Two fixes together, because either alone is fragile: the stack clears the
   real height of the card rather than a guessed 150 px, and it is no longer
   allowed to sit above it. */
body:has(#pk-update-toast) #pk-toasts {
  bottom: calc(74px + 460px);
}

#pk-update-toast {
  position: fixed;
  right: 16px;
  bottom: 74px;
  /* above #pk-toasts (999998): the surface holding a permission control must
     never be the one that gets painted over */
  z-index: 999999;
  width: min(364px, calc(100vw - 32px));
  border: 1px solid var(--pk-glass-border, rgba(255, 255, 255, 0.25));
  border-radius: var(--pk-radius-panel, 16px);
  padding: 14px 15px 15px;
  /* shared spatial material: wallpaper reads through, the top edge catches
     light, and the tint is a few percent lavender rather than a purple panel */
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.085), rgba(131, 138, 255, 0.045)),
    var(--pk-glass-surface, rgba(18, 18, 22, 0.66));
  box-shadow: var(--pk-glass-shadow, 0 22px 60px rgba(0, 0, 0, 0.5));
  color: var(--pk-text, #fff);
  font-family: var(--pk-font, var(--os-body, var(--pd-font)));
  opacity: 0;
  transform: translateX(24px);
  transition:
    opacity var(--pk-duration, 240ms) var(--pk-ease, ease),
    transform var(--pk-duration, 240ms) var(--pk-ease, cubic-bezier(0.16, 1, 0.3, 1));
  backdrop-filter: var(--pk-glass-blur, blur(32px) saturate(125%));
  -webkit-backdrop-filter: var(--pk-glass-blur, blur(32px) saturate(125%));
}

#pk-update-toast.show {
  opacity: 1;
  transform: none;
}

#pk-update-toast.gone {
  opacity: 0;
  transform: translateX(24px);
  pointer-events: none;
}

.pk-up-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

.pk-up-app {
  flex: 1;
  color: var(--os-text-2, #c4c0d0);
  font-family: var(--os-ui, var(--pd-font));
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.01em;
}

.pk-up-mark {
  display: block;
  width: 18px;
  height: 18px;
  color: var(--pm-purple, #6e5ae8);
}

.pk-up-x {
  width: 26px;
  height: 26px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--os-text-2, #c4c0d0);
  cursor: pointer;
  font-size: 17px;
  line-height: 1;
}

.pk-up-x:hover {
  background: rgba(255, 255, 255, 0.1);
  color: var(--os-text, #f3f0fa);
}

/* the toast no longer has a heading: plan 14 section 8.1 makes its attribution
   row required, and that row already carries the app name, so a heading with
   the same string printed "Software Update" twice in a 364 px card. The
   selector is left on the window only, which has no attribution row. */
#win-update h4 {
  margin: 0 0 4px;
  font-family: var(--os-ui, var(--pd-font));
  font-size: 14px;
  font-weight: 700;
}

.pk-up-body {
  margin: 0;
  color: var(--os-text-2, #c4c0d0);
  font-size: 13px;
  line-height: 1.45;
}

/* The check control. Our own glyph: two arcs with arrowheads, on a quiet
   well. It spins only while a check is in flight, and the spin is paired
   with the checking line so the state is never carried by motion alone. */
.pk-up-check {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  margin-top: 10px;
  border: 1px solid var(--os-line-2, rgba(255, 255, 255, 0.18));
  border-radius: var(--os-r-btn, 5px);
  padding: 9px 12px;
  background: rgba(255, 255, 255, 0.06);
  color: var(--os-text, #f3f0fa);
  cursor: pointer;
  font-family: var(--os-ui, var(--pd-font));
  font-size: 13px;
  font-weight: 600;
  text-align: left;
}

.pk-up-check:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.12);
}

.pk-up-check:disabled {
  cursor: default;
  opacity: 0.85;
}

.pk-up-glyph {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  color: var(--pm-purple, #6e5ae8);
}

.pk-up-spin .pk-up-glyph,
.pk-up-btn.spin .pk-up-glyph {
  animation: pk-up-turn 900ms linear infinite;
}

@keyframes pk-up-turn {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .pk-up-spin .pk-up-glyph,
  .pk-up-btn.spin .pk-up-glyph {
    animation-duration: 2400ms;
  }

  #pk-update-toast {
    transition: opacity 240ms ease;
    transform: none;
  }
}

.pk-up-form {
  margin-top: 11px;
}

.pk-up-form[hidden],
.pk-up-check[hidden],
.pk-up-fine[hidden],
.pk-up-context[hidden] {
  display: none;
}

.pk-up-context {
  margin: 8px 0 0;
  color: var(--pk-text, #fff);
  font-size: 12px;
  line-height: 1.45;
  opacity: 0.88;
}

.pk-up-label {
  display: block;
  margin-bottom: 5px;
  color: var(--os-text-2, #c4c0d0);
  font-size: 12px;
  font-weight: 600;
}

.pk-up-input {
  width: 100%;
  border: 1px solid var(--pk-glass-border, rgba(255, 255, 255, 0.25));
  border-radius: var(--pk-radius-control, 10px);
  padding: 10px 11px;
  /* a recessed well in the material, not a web form field: the inner shadow
     is what makes it read as carved into glass rather than pasted onto it */
  background: var(--pk-glass-panel, rgba(255, 255, 255, 0.065));
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.22);
  color: var(--pk-text, #fff);
  font-family: var(--pk-font, var(--os-body, var(--pd-font)));
  /* 16 px so iOS does not zoom the page when the field takes focus */
  font-size: 16px;
}

/* ===== the email permission control, round 12 =====
   CASL requires an affirmative act, so this is a real unchecked box beside
   the exact sentence that is stored with the lead. It is deliberately not a
   pill and not decorative: it is a system permission row, and the 44 px
   target means a thumb on a phone can actually operate it. */
.pk-up-consent {
  display: flex;
  gap: 10px;
  align-items: center;
  /* the whole row is the touch target, so the small box is not the only
     thing a thumb on a phone can hit */
  min-height: 44px;
  margin: 11px 0 0;
  border: 1px solid var(--pk-glass-hairline, rgba(255, 255, 255, 0.12));
  border-radius: var(--pk-radius-control, 10px);
  padding: 10px 11px;
  background: var(--pk-glass-panel, rgba(255, 255, 255, 0.065));
  cursor: pointer;
}

.pk-up-consent[hidden] {
  display: none;
}

.pk-up-consent-box {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  margin: 0;
  accent-color: var(--pk-accent, #5956e9);
  cursor: pointer;
}

.pk-up-consent-line {
  color: var(--pk-text, #fff);
  font-size: 12px;
  line-height: 1.5;
  opacity: 0.92;
}

.pk-up-consent-box:focus-visible {
  outline: 2px solid var(--pk-text, #fff);
  outline-offset: 3px;
}

/* a refused send marks the control the visitor has to operate */
.pk-up-consent-box[aria-invalid="true"] {
  outline: 2px solid #ffb4b4;
  outline-offset: 3px;
}

.pk-up-input:focus-visible,
.pk-up-check:focus-visible,
.pk-up-btn:focus-visible,
.pk-up-x:focus-visible {
  outline: 2px solid var(--os-focus, #a99bff);
  outline-offset: 2px;
}

.pk-up-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  min-height: 40px;
  margin-top: 9px;
  border: 0;
  border-radius: var(--pk-radius-control, 10px);
  padding: 10px 14px;
  background: var(--pk-accent, #5956e9);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 6px 18px rgba(66, 62, 243, 0.28);
  color: #fff;
  cursor: pointer;
  font-family: var(--pk-font, var(--os-ui, var(--pd-font)));
  font-size: 14px;
  font-weight: 700;
}

.pk-up-btn:hover:not(:disabled) {
  filter: brightness(1.1);
}

.pk-up-btn:disabled {
  cursor: default;
  opacity: 0.9;
}

.pk-up-err {
  margin: 7px 0 0;
  color: #ffb4b4;
  font-size: 12px;
  min-height: 0;
}

.pk-up-fine {
  margin: 9px 0 0;
  color: var(--os-text-2, #c4c0d0);
  font-size: 11px;
  line-height: 1.5;
}

.pk-up-fine a {
  color: inherit;
}

.pk-up-sent {
  margin: 10px 0 0;
  color: var(--os-text, #f3f0fa);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.45;
}

.pk-up-sent[hidden] {
  display: none;
}

/* The Software Update window is the same copy at reading size, with the
   items the check found listed as what they are: our services. */
#win-update {
  padding: 22px 24px 26px;
  color: var(--os-text, #f3f0fa);
  font-family: var(--os-body, var(--pd-font));
  overflow: auto;
}

#win-update .pk-up-intro {
  margin: 4px 0 14px;
  color: var(--os-text-2, #c4c0d0);
  font-size: 13px;
  line-height: 1.5;
  max-width: 54ch;
}

#win-update .pk-up-items {
  margin: 0 0 16px;
  padding: 0;
  list-style: none;
}

#win-update .pk-up-items li {
  display: flex;
  gap: 10px;
  border-bottom: 1px solid var(--os-line, rgba(255, 255, 255, 0.1));
  padding: 10px 2px;
  font-size: 14px;
}

#win-update .pk-up-items b {
  color: var(--os-text-2, #c4c0d0);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

#win-update .pk-up-form,
#win-update .pk-up-check {
  max-width: 420px;
}

@media (max-width: 620px) {
  #pk-update-toast {
    right: 12px;
    left: 12px;
    bottom: 70px;
    width: auto;
  }
}

/* =====
   Round 5: the lock, as a volume gate.

   Three elements the round 4 lock did not have: the funnel line under the
   subtitle, the inline phone error, and a label the eye does not need but a
   screen reader does. Colour comes from the tokens the glass pass owns; only
   the geometry lives here, so this file never competes with os2031.css for
   a colour decision.
   ===== */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  border: 0;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.lock-funnel {
  margin: 8px 0 0;
  padding: 0 16px;
  color: var(--os-text-2);
  font-size: 12.5px;
  font-style: italic;
  line-height: 1.45;
}

.lock-err {
  margin: 8px 0 0;
  padding: 0 16px;
  color: #c0392b;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.4;
  min-height: 0;
}

.lock-err:empty {
  margin: 0;
}

/* the honeypot, plan 2.5: present for a script, absent for a person */
#login-website-url {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* the Halo sound control, plan 6.1 and 6.3. The glyph itself carries the
   state, so the toggle is readable without hearing anything. */
#os-sound {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: 0;
  border-radius: 6px;
  padding: 0;
  background: transparent;
  color: var(--os-text-2, #c4c0d0);
  cursor: pointer;
}

#os-sound svg {
  width: 17px;
  height: 17px;
}

#os-sound.on {
  color: var(--pm-purple, #6e5ae8);
}

#os-sound:hover {
  background: rgba(255, 255, 255, 0.12);
  color: var(--os-text, #f3f0fa);
}

#os-sound:focus-visible {
  outline: 2px solid var(--os-focus, #a99bff);
  outline-offset: 2px;
}
