/* T410 On-Screen Keyboard skin — GENERATED by scripts/build-keyboard-bundle.js. Do not edit by hand. */
/* --- simple-keyboard base (vendored, MIT) --- */
/*!
 * 
 *   simple-keyboard v3.8.152
 *   https://github.com/hodgef/simple-keyboard
 *
 *   Copyright (c) Francisco Hodge (https://github.com/hodgef) and project contributors.
 *
 *   This source code is licensed under the MIT license found in the
 *   LICENSE file in the root directory of this source tree.
 *
 */.hg-theme-default{background-color:#ececec;border-radius:5px;box-sizing:border-box;font-family:HelveticaNeue-Light,Helvetica Neue Light,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;overflow:hidden;padding:5px;touch-action:manipulation;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}.hg-theme-default .hg-button span,.hg-theme-default .hg-button span svg{pointer-events:none}.hg-theme-default button.hg-button{border-width:0;font-size:inherit}.hg-theme-default .hg-button{display:inline-block;flex-grow:1}.hg-theme-default .hg-row{display:flex}.hg-theme-default .hg-row:not(:last-child){margin-bottom:5px}.hg-theme-default .hg-row .hg-button-container,.hg-theme-default .hg-row .hg-button:not(:last-child){margin-right:5px}.hg-theme-default .hg-row>div:last-child{margin-right:0}.hg-theme-default .hg-row .hg-button-container{display:flex}.hg-theme-default .hg-button{align-items:center;background:#fff;border-bottom:1px solid #b5b5b5;border-radius:5px;box-shadow:0 0 3px -1px rgba(0,0,0,.3);box-sizing:border-box;cursor:pointer;display:flex;height:40px;justify-content:center;padding:5px;-webkit-tap-highlight-color:rgba(0,0,0,0)}.hg-theme-default .hg-button.hg-standardBtn{width:20px}.hg-theme-default .hg-button.hg-activeButton{background:#efefef}.hg-theme-default.hg-layout-numeric .hg-button{align-items:center;display:flex;height:60px;justify-content:center;width:33.3%}.hg-theme-default .hg-button.hg-button-numpadadd,.hg-theme-default .hg-button.hg-button-numpadenter{height:85px}.hg-theme-default .hg-button.hg-button-numpad0{width:105px}.hg-theme-default .hg-button.hg-button-com{max-width:85px}.hg-theme-default .hg-button.hg-standardBtn.hg-button-at{max-width:45px}.hg-theme-default .hg-button.hg-selectedButton{background:rgba(5,25,70,.53);color:#fff}.hg-theme-default .hg-button.hg-standardBtn[data-skbtn=".com"]{max-width:82px}.hg-theme-default .hg-button.hg-standardBtn[data-skbtn="@"]{max-width:60px}.hg-candidate-box{background:#ececec;border-bottom:2px solid #b5b5b5;border-radius:5px;display:inline-flex;margin-top:-10px;position:absolute;transform:translateY(-100%);-webkit-user-select:none;-moz-user-select:none;user-select:none}ul.hg-candidate-box-list{display:flex;flex:1;list-style:none;margin:0;padding:0}li.hg-candidate-box-list-item{align-items:center;display:flex;height:40px;justify-content:center;width:40px}li.hg-candidate-box-list-item:hover{background:rgba(0,0,0,.03);cursor:pointer}li.hg-candidate-box-list-item:active{background:rgba(0,0,0,.1)}.hg-candidate-box-prev:before{content:"◄"}.hg-candidate-box-next:before{content:"►"}.hg-candidate-box-next,.hg-candidate-box-prev{align-items:center;color:#969696;cursor:pointer;display:flex;padding:0 10px}.hg-candidate-box-next{border-bottom-right-radius:5px;border-top-right-radius:5px}.hg-candidate-box-prev{border-bottom-left-radius:5px;border-top-left-radius:5px}.hg-candidate-box-btn-active{color:#444}
/* --- Oyster theme-token skin (navy↔teal) --- */
/*
 * T410 — On-Screen Keyboard skin (LD-2, LD-10).
 *
 * Themes the keyboard via the T403/T405/T407 theme tokens so keys track
 * navy↔teal AUTOMATICALLY (NO hardcoded brand colors). Falls back to the
 * current-tree --oyos-*-accent tokens when the theme engine isn't mounted.
 *
 * The build script (scripts/build-keyboard-bundle.js) concatenates
 * simple-keyboard's base CSS + this skin → host/keyboard-skin.css.
 */

/* Local token aliases live ON the keyboard root (NOT :root) so they resolve at
   the keyboard's own scope — they track the live --theme-* vars wherever the
   theme engine sets them (:root OR body), instead of being pinned to :root once.
   This is what lets the keys re-color when the theme toggles navy↔teal. */
#oyster-keyboard-root {
  --oyk-accent: var(--theme-accent, var(--oyos-channel-accent, #38bdf8));
  --oyk-accent-hover: var(--theme-accent-hover, var(--oyos-seams-accent, #2563eb));
  --oyk-surface: var(--theme-bg-surface, rgba(15, 23, 42, 0.92));
  --oyk-surface-floor: var(--theme-bg-primary, #0f172a);
  --oyk-surface-2: var(--theme-bg-secondary, rgba(30, 41, 59, 0.92));
  --oyk-key-bg: var(--theme-input-bg, rgba(30, 41, 59, 0.85));
  --oyk-key-border: var(--theme-input-border, var(--theme-border, rgba(148, 163, 184, 0.35)));
  --oyk-text: var(--theme-text, var(--theme-text-primary, #e2e8f0));
  --oyk-blur: var(--theme-glass-blur, 14px);
  --oyk-radius: 10px;

  /* T1086 P5d — MEASURED 2026-08-25: without this the dock rendered 410px wide on
     a 390px viewport and clipped the p, l, backspace and return keys by 7px each.
     (Those key names are spelled out in words deliberately. The LD-15 z-band
     guard's rule extractor in t1086-p0-keyboard-zband.test.js slices from the
     opening brace to the very next CLOSING BRACE character, so ANY closing brace
     anywhere in this comment -- including one written inside a brace-wrapped key
     token -- truncates the extracted rule mid-comment and fails that guard's own
     position:fixed positive control. Keep this whole comment brace-free.)
     Cause: the default content-box means `width:100%` (390px) EXCLUDES the 10px
     side padding, so the border-box is 390+20=410. (The -20px margin-right the
     inspector shows is not authored — it is the browser resolving the
     over-constrained `left:0; right:0; width:390px` for a fixed box.)
     `document.scrollWidth` stays 390 because the dock is fixed, so there is no
     h-scrollbar and the clipped keys are simply UNREACHABLE — backspace and
     return, the two most-used keys on the keyboard.
     P5c closed 40px of this by releasing the per-key min-width floor
     (see the phone block below); this closes the last 20px at the ROOT.
     Why the P5 FAT was green throughout: its overflow probe compared each key to
     the DOCK, never the dock to the VIEWPORT. Both are asserted now. */
  box-sizing: border-box;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  /* T1086 LD-15 — the `keyboard` band floor (z-order-manager.cjs BAND_FLOORS).
     RETIRED 2026-08-24: `z-index: 2147483000` — five orders of magnitude above
     the manager's ceiling, so no modal could EVER render over the keyboard and
     T1089's stacked Back journey was unbuildable. The fallback is NOT cosmetic:
     this stylesheet is also loaded by public/auth/login.html, which defines no
     --z-* registry, and an unresolved var() would DROP the declaration entirely
     (z-index:auto) and bury the keyboard. Login page tops out at z 60. */
  z-index: var(--z-keyboard, 4300);
  margin: 0 auto;
  max-width: 920px;
  padding: 8px 10px calc(8px + env(safe-area-inset-bottom, 0px));
  /* T2471F: an OPAQUE floor under the theme surface. The dark host theme sets the surface to
     5 percent white, so the keyboard was legible only while backdrop-filter blurred what lies
     behind it. MEASURED in WebKit (iPhone 13 emulation): the blur did not render, the dock,
     drawer and field showed through crisp and read as painted OVER the keys. The theme tint
     is kept, layered over the floor; the blur stays as decoration. */
  background: linear-gradient(var(--oyk-surface), var(--oyk-surface)), var(--oyk-surface-floor);
  backdrop-filter: blur(var(--oyk-blur));
  -webkit-backdrop-filter: blur(var(--oyk-blur));
  border-top: 1px solid var(--oyk-key-border);
  border-radius: var(--oyk-radius) var(--oyk-radius) 0 0;
  box-shadow: 0 -8px 30px rgba(0, 0, 0, 0.35);
  font-family: var(--theme-font-ui, system-ui, -apple-system, sans-serif);
  transform: translateY(100%);
  transition: transform 160ms ease;
}
#oyster-keyboard-root.oyk-visible { transform: translateY(0); }
#oyster-keyboard-root[hidden] { display: none; }
#oyster-keyboard-root.oyk-rtl { direction: rtl; }

/* candidate bar (role=listbox) */
.oyk-candidates {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding: 6px 4px;
  min-height: 0;
}
.oyk-candidates[hidden] { display: none; }
.oyk-candidate {
  flex: 0 0 auto;
  padding: 6px 12px;
  font-size: 18px;
  line-height: 1.2;
  color: var(--oyk-text);
  background: var(--oyk-key-bg);
  border: 1px solid var(--oyk-key-border);
  border-radius: 8px;
  cursor: pointer;
}
.oyk-candidate:hover,
.oyk-candidate:focus { border-color: var(--oyk-accent); outline: none; }
.oyk-candidate[role="option"][tabindex="0"] { box-shadow: 0 0 0 2px var(--oyk-accent) inset; }

/* simple-keyboard skin override → theme tokens */
#oyster-keyboard-root .hg-theme-default {
  background: transparent;
  padding: 4px 0 0;
}
#oyster-keyboard-root .hg-button {
  background: var(--oyk-key-bg);
  color: var(--oyk-text);
  border: 1px solid var(--oyk-key-border);
  border-radius: 8px;
  box-shadow: none;
  height: 44px;
  font-size: 17px;
}
#oyster-keyboard-root .hg-button:active,
#oyster-keyboard-root .hg-button.hg-activeButton {
  background: var(--oyk-accent);
  color: #ffffff;
  border-color: var(--oyk-accent-hover);
}
#oyster-keyboard-root .hg-button[data-skbtn="{bksp}"],
#oyster-keyboard-root .hg-button[data-skbtn="{enter}"],
#oyster-keyboard-root .hg-button[data-skbtn="{shift}"],
#oyster-keyboard-root .hg-button[data-skbtn="{space}"] {
  background: var(--oyk-surface-2);
}

/* coarse-pointer only by default: desktop fine-pointer users get it on demand
   (a11y, LD-12). Explicit .oyk-force shows regardless. */
@media (pointer: fine) {
  #oyster-keyboard-root:not(.oyk-force):not(.oyk-visible) { display: none; }
}

/* ── T453 P2: Chrome header (⚙/⌄/✕ cluster) ────────────────────────────────── */
.oyk-chrome {
  display: flex;
  justify-content: flex-end;
  gap: 4px;
  padding: 4px 6px 2px;
}
/* RTL: cluster mirrors to top-LEFT (LD-13) */
#oyster-keyboard-root.oyk-rtl .oyk-chrome {
  justify-content: flex-start;
}
.oyk-chrome-btn {
  background: transparent;
  color: var(--oyk-text);
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 2px 8px;
  font-size: 14px;
  cursor: pointer;
  line-height: 1.4;
  transition: background 120ms;
}
.oyk-chrome-btn:hover,
.oyk-chrome-btn:focus {
  background: var(--oyk-key-bg);
  border-color: var(--oyk-key-border);
  outline: none;
}
.oyk-chrome-btn:focus-visible {
  outline: 2px solid var(--oyk-accent);
  outline-offset: 1px;
}
/* ✕ Close: desktop (fine pointer) only (LD-4) */
.oyk-chrome-close {
  color: var(--theme-error, #ef4444);
  display: none;
}
@media (pointer: fine) {
  .oyk-chrome-close { display: inline-block; }
}

/* ── T453 P4: Settings popover ──────────────────────────────────────────────── */
.oyk-settings-popover {
  position: absolute;
  top: 0;
  right: 8px;
  transform: translateY(-100%);
  min-width: 260px;
  /* T2511F (USER FIX 57-B): a floating window paints the OPAQUE popover surface — --oyk-surface is the 5% glass veil in
     the host. Fallback (login page, no host theme): the keyboard's own opaque floor. */
  background: var(--theme-popover-bg, var(--oyk-surface-floor));
  color: var(--theme-popover-text, var(--oyk-text));
  border: 1px solid var(--oyk-key-border);
  border-radius: 8px;
  padding: 12px;
  z-index: 1;
  box-shadow: 0 -4px 16px rgba(0,0,0,0.35);
  backdrop-filter: blur(var(--oyk-blur));
  -webkit-backdrop-filter: blur(var(--oyk-blur));
}
/* Viewport-safe flip: when popover would go above screen (LD-6) */
.oyk-settings-popover--below {
  top: 100%;
  transform: none;
  box-shadow: 0 4px 16px rgba(0,0,0,0.35);
}
/* RTL: anchor to left instead of right */
#oyster-keyboard-root.oyk-rtl .oyk-settings-popover {
  right: auto;
  left: 8px;
}
.oyk-settings-popover[hidden] { display: none; }
.oyk-settings-row {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
}
.oyk-settings-row:last-child { margin-bottom: 0; }
.oyk-settings-label {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--oyk-text);
  font-size: 14px;
  cursor: pointer;
  width: 100%;
}
.oyk-autoshow-toggle {
  width: 16px;
  height: 16px;
  accent-color: var(--oyk-accent);
  cursor: pointer;
}
.oyk-layout-select {
  background: var(--oyk-key-bg);
  color: var(--oyk-text);
  border: 1px solid var(--oyk-key-border);
  border-radius: 6px;
  padding: 4px 8px;
  font-size: 13px;
  margin-left: auto;
}

/* ── T453 P3: Floating mini-icon (#oyster-keyboard-mini) ─────────────────────── */
/* z-index 2000: above drawers (--z-open-drawer 1300), below float (4100), the
   keyboard root (--z-keyboard 4300) and modals (--z-modal 5000). LD-10.
   T1086 LD-15 corrected this comment: it previously read "below modals/keyboard
   root (5000+)", which contradicted the keyboard root's own 2147483000 on
   line 31 of this same file. The comment described the INTENT; the code did not
   implement it. The code now matches the comment. */
#oyster-keyboard-mini {
  position: fixed;
  bottom: 16px;
  right: 16px;
  z-index: 2000;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--oyk-surface, rgba(15,23,42,0.92));
  border: 1px solid var(--oyk-key-border);
  color: var(--oyk-text);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 16px rgba(0,0,0,0.35);
  backdrop-filter: blur(var(--oyk-blur));
  -webkit-backdrop-filter: blur(var(--oyk-blur));
  transition: background 120ms;
  padding: 0;
}
#oyster-keyboard-mini:hover,
#oyster-keyboard-mini:focus {
  background: var(--oyk-key-bg);
  outline: 2px solid var(--oyk-accent);
}
#oyster-keyboard-mini svg {
  width: 22px;
  height: 22px;
}
/* RTL: dock bottom-LEFT (LD-13) */
#oyster-keyboard-mini.oyk-mini-icon--rtl {
  right: auto;
  left: 16px;
}

/* ── T428 LD-3: persistent launcher (#oyster-keyboard-launcher) ──────────────── */
/* The always-present OPEN affordance (distinct from the mini RESTORE handle).
   Docks just above where the mini-icon sits so the two never overlap (they are
   mutually exclusive in time, but the offset keeps the visual language clear).
   Sized to the 44px coarse-pointer touch target (LD-7 / WCAG 2.5.5). */
#oyster-keyboard-launcher {
  position: fixed;
  bottom: 16px;
  right: 16px;
  z-index: 2000;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--oyk-accent, var(--theme-accent, #38bdf8));
  border: 1px solid var(--oyk-key-border);
  color: var(--oyk-on-accent, #07111f);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 16px rgba(0,0,0,0.35);
  transition: filter 120ms, transform 120ms;
  padding: 0;
  opacity: 0.92;
}
#oyster-keyboard-launcher:hover,
#oyster-keyboard-launcher:focus {
  filter: brightness(1.12);
  transform: translateY(-1px);
  outline: 2px solid var(--oyk-accent);
  opacity: 1;
}
#oyster-keyboard-launcher svg { width: 22px; height: 22px; }
/* RTL: dock bottom-LEFT (LD-13) */
#oyster-keyboard-launcher.oyk-launcher-btn--rtl {
  right: auto;
  left: 16px;
}
@media (prefers-reduced-motion: reduce) {
  #oyster-keyboard-launcher { transition: none; }
  #oyster-keyboard-launcher:hover,
  #oyster-keyboard-launcher:focus { transform: none; }
}

/* ── T428 P4 (LD-6): emoji picker panel ──────────────────────────────────────── */
.oyk-emoji-panel {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 6px;
  max-height: 280px;
}
/* T1086 P5c (issue #1e) — MEASURED: without this rule the emoji panel held
   196px of PERMANENT dock height while `hidden` was true, on a 440px dock.
   `emojiPanel.hide()` sets the `hidden` property, but the UA's
   `[hidden] { display: none }` has specificity (0,1,0) and loses to the
   `display: flex` above it, so the panel stayed laid out with zero pixels
   painted. That is the user's "the emoji ... has its own lines that are always
   up at the bottom" — the rows they saw were the panel's own box.
   Note the shape of the bug: this stylesheet already carries the identical
   guard for THREE other toggled surfaces — `#oyster-keyboard-root[hidden]`,
   `.oyk-candidates[hidden]` and `.oyk-settings-popover[hidden]` — and the emoji
   panel, added later in T428 P4, simply never got one. A convention applied
   three times out of four is a deadline, not a property. */
.oyk-emoji-panel[hidden] { display: none; }
.oyk-emoji-search {
  width: 100%;
  box-sizing: border-box;
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid var(--oyk-key-border);
  background: var(--oyk-key-bg, rgba(255,255,255,0.06));
  color: var(--oyk-text);
  font-size: 14px;
}
.oyk-emoji-tones, .oyk-emoji-cats {
  display: flex;
  gap: 4px;
  overflow-x: auto;
  scrollbar-width: thin;
}
.oyk-emoji-tone, .oyk-emoji-cat {
  flex: 0 0 auto;
  min-width: 36px;
  min-height: 36px;
  border-radius: 8px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--oyk-text);
  cursor: pointer;
  font-size: 16px;
  padding: 2px 8px;
}
.oyk-emoji-cat { font-size: 11px; text-transform: capitalize; }
.oyk-emoji-tone:hover, .oyk-emoji-cat:hover,
.oyk-emoji-tone:focus, .oyk-emoji-cat:focus {
  border-color: var(--oyk-accent);
  outline: none;
}
.oyk-emoji-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));
  gap: 2px;
  overflow-y: auto;
  flex: 1 1 auto;
}
.oyk-emoji-cell {
  min-width: 40px;
  min-height: 40px;
  border: none;
  background: transparent;
  cursor: pointer;
  font-size: 22px;
  border-radius: 8px;
  padding: 0;
}
.oyk-emoji-cell:hover, .oyk-emoji-cell:focus {
  background: var(--oyk-key-bg, rgba(255,255,255,0.1));
  outline: none;
}

/* ── T428 P5 (LD-7): responsive key sizing + form-factor layout ──────────────── */
/* The root is a query container so a floated/docked keyboard sizes to ITSELF. */
#oyster-keyboard-root {
  container-type: inline-size;
  container-name: oyk;
}
/* Touch-target floor: var set from JS (--oyk-key-min = 48 coarse / 34 fine). */
#oyster-keyboard-root .hg-button {
  min-height: var(--oyk-key-min, 40px);
  min-width: calc(var(--oyk-key-min, 40px) - 8px);
}
/* Coarse-pointer hard floor (WCAG 2.5.5 / Apple 44), independent of the JS var. */
@media (pointer: coarse) {
  #oyster-keyboard-root .hg-button { min-height: 44px; }
  .oyk-emoji-cell, .oyk-emoji-tone, .oyk-emoji-cat { min-height: 44px; }
}
/* Phone: full-width bottom dock, denser horizontal gaps. */
#oyster-keyboard-root[data-factor="phone"] {
  left: 0; right: 0; width: 100%;
  border-radius: 12px 12px 0 0;
}
/* T1086 P5c (LD-7) — MEASURED: the 4-row phone page overflowed the 390px dock by
   45px and the top row was CLIPPED (`p`, `l` and `⌫` ran off-screen). Cause is
   the generic floor above: `min-width: calc(var(--oyk-key-min) - 8px)` = 40px on
   a coarse pointer, and 10 keys x (40px + 5px margin) = 450px cannot fit 390px.
   That floor is correct for a desktop/tablet dock and wrong for a phone row.

   LD-7 already ruled this trade explicitly: "Key width at 10 keys on 390px is
   ~33px — clears WCAG 2.2 SC 2.5.8 AA (24x24), does NOT clear SC 2.5.5 AAA
   (44x44); that trade is accepted and documented, and the coarse-pointer 44px
   min-height floor already in keyboard-skin.css is preserved for non-letter
   keys." So the HORIZONTAL floor is released here and the VERTICAL floor is
   not — the 44px `min-height` from the (pointer: coarse) block above still
   applies, and the FAT asserts both: no overhang, and no key narrower than the
   SC 2.5.8 AA 24px minimum.

   ⚠ Do NOT "fix" a future overflow by lowering the min-height instead; that
   crosses the AA target, which the trade above does not permit. */
#oyster-keyboard-root[data-factor="phone"] .hg-button {
  min-width: 0;
  padding-left: 0;
  padding-right: 0;
  margin-right: 3px;
}
#oyster-keyboard-root[data-factor="phone"] .hg-row {
  margin-left: 2px;
}
/* Desktop: a comfortably sized, centered panel (can float per dock-mode). */
#oyster-keyboard-root[data-factor="desktop"] {
  max-width: 920px;
  margin: 0 auto;
}
/* Container-query densification when the keyboard itself is narrow. */
@container oyk (max-width: 420px) {
  #oyster-keyboard-root .hg-button { font-size: 15px; padding: 4px; }
}
@container oyk (min-width: 760px) {
  #oyster-keyboard-root .hg-button { font-size: 17px; }
}

/* ── T2427F P1 (D1): the host LIFTS above the keyboard, like a phone/pad keyboard ── */
/* Driven by shared/cores/keyboard/host-lift.js, which sets the attribute and both custom
   properties on html from MEASURED geometry and removes all three on hide (exact restore).
   A translate on body makes body the containing block of every fixed descendant, so the
   keyboard root is counter-translated by a MEASURED amount to stay on the viewport bottom.
   The overflow pair is MEASURED, not decorative: without it an off-canvas fixed panel joins
   the overflow and a mobile layout viewport widens (390 to 750). html stops propagating
   body's overflow to the viewport so body's X-only clip applies; a Y clip would cut the
   keyboard. Deliberately not animated: every measure reads a rect plus the applied lift. */
@supports (translate: 0 1px) and (overflow-x: clip) {
  html[data-oyk-lift] {
    overflow: hidden;
  }
  html[data-oyk-lift] body {
    translate: 0 calc(-1 * var(--oyk-host-lift, 0px));
    overflow-x: clip;
    overflow-y: visible;
  }
  html[data-oyk-lift] #oyster-keyboard-root {
    translate: 0 var(--oyk-root-counter, var(--oyk-host-lift, 0px));
  }
}
