:root {
  color-scheme: light dark;
  --op-bg: #090c0f;
  --op-surface: #11161b;
  --op-surface-raised: #151b21;
  --op-text: #f2f5f7;
  --op-muted: #93a0aa;
  --op-border: #2b343c;
  --op-border-strong: #3a454e;
  --op-accent: #72ade7;
  --op-accent-text: #071019;
  --op-success: #62d991;
  --op-warning: #f1cf78;
  --op-danger: #ff9d96;
  --op-shadow: rgba(0, 0, 0, 0.3);
}

:root[data-theme="light"] {
  color-scheme: light;
  --op-bg: #f5f7f8;
  --op-surface: #ffffff;
  --op-surface-raised: #eef2f5;
  --op-text: #111820;
  --op-muted: #5e6c77;
  --op-border: #d6dde3;
  --op-border-strong: #aebac4;
  --op-accent: #1d6fb8;
  --op-accent-text: #ffffff;
  --op-success: #147b43;
  --op-warning: #8a5b00;
  --op-danger: #b42318;
  --op-shadow: rgba(19, 34, 48, 0.12);
}

:root[data-theme="dark"] {
  color-scheme: dark;
}

.op-theme-toggle {
  display: inline-flex;
  min-width: 43px;
  min-height: 43px;
  padding: 0 13px;
  color: var(--op-text);
  background: var(--op-surface);
  border: 1px solid var(--op-border-strong);
  border-radius: 4px;
  align-items: center;
  justify-content: center;
  font: 650 13px/1 ui-sans-serif, system-ui, sans-serif;
}

.op-theme-toggle:hover,
.op-theme-toggle:focus-visible {
  border-color: var(--op-accent);
}

:root {
  font-family: "Segoe UI Variable", "Segoe UI", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
  background: var(--op-bg);
  color: var(--op-text);
}

* {
  box-sizing: border-box;
}

html,
body {
  width: 100%;
  min-height: 100%;
  margin: 0;
}

body {
  color: var(--op-text);
  background: var(--op-bg);
}

button,
input {
  font: inherit;
}

button {
  cursor: pointer;
}

.hidden {
  display: none !important;
}

.portal-view {
  width: 100%;
  min-height: 100dvh;
  padding:
    max(32px, env(safe-area-inset-top))
    max(24px, env(safe-area-inset-right))
    max(32px, env(safe-area-inset-bottom))
    max(24px, env(safe-area-inset-left));
}

.login-view {
  display: grid;
  place-items: center;
}

.login-card,
.prompt-card {
  border: 1px solid var(--op-border);
  background: var(--op-surface);
  box-shadow: 0 18px 50px var(--op-shadow);
}

.login-card {
  width: min(100%, 390px);
  padding: 30px;
  border-radius: 6px;
}

h1,
h2,
p {
  margin-top: 0;
}

h1 {
  margin-bottom: 8px;
  font-size: clamp(28px, 5vw, 36px);
  font-weight: 650;
  letter-spacing: -0.025em;
}

h2 {
  margin-bottom: 4px;
  font-size: 18px;
  font-weight: 650;
}

.eyebrow {
  margin-bottom: 12px;
  color: #70abe4;
  font-size: 11px;
  font-weight: 650;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.muted {
  color: var(--op-muted);
}

.login-card label {
  display: grid;
  gap: 8px;
  margin-top: 18px;
  color: var(--op-text);
  font-size: 13px;
  font-weight: 650;
}

.login-card input {
  width: 100%;
  height: 46px;
  padding: 0 13px;
  color: var(--op-text);
  background: var(--op-bg);
  border: 1px solid var(--op-border-strong);
  border-radius: 4px;
  outline: none;
}

.login-card input:focus {
  border-color: #69aefc;
  box-shadow: 0 0 0 3px rgba(77, 157, 246, 0.16);
}

.primary-button,
.secondary-button {
  min-height: 43px;
  padding: 0 17px;
  border-radius: 4px;
  font-weight: 650;
}

.primary-button {
  color: var(--op-accent-text);
  background: var(--op-accent);
  border: 1px solid var(--op-accent);
}

.primary-button:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

.secondary-button {
  color: var(--op-text);
  background: transparent;
  border: 1px solid var(--op-border-strong);
}

.login-card .primary-button {
  width: 100%;
  margin-top: 22px;
}

.form-error {
  margin: 14px 0 -6px;
  color: #ffb4ad;
  font-size: 13px;
}

.account-notice {
  margin: 14px 0 -6px;
  color: #a9d1f8;
  font-size: 13px;
  line-height: 1.45;
}

.auth-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 10px 18px;
  margin-top: 18px;
}

.auth-links button {
  padding: 0;
  color: #8fc4f7;
  background: none;
  border: 0;
  font-size: 13px;
}

.auth-links button:hover,
.auth-links button:focus-visible {
  color: #c4e2ff;
  text-decoration: underline;
}

.dashboard-view {
  width: min(100%, 1280px);
  margin: 0 auto;
}

.dashboard-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 44px;
}

.dashboard-header h1 {
  margin-bottom: 0;
}

.dashboard-header .op-theme-toggle {
  margin-left: auto;
}

.device-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 360px), 1fr));
  gap: 18px;
}

.allocation-notice {
  margin: 18px 0 0;
  padding: 14px 16px;
  color: var(--op-muted);
  background: var(--op-surface-raised);
  border: 1px solid var(--op-border);
  border-radius: 4px;
}

.allocation-notice.error {
  color: var(--op-danger);
}

.device-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  overflow: hidden;
  padding: 0;
  background: var(--op-surface);
  border: 1px solid var(--op-border);
  border-radius: 6px;
}

.device-card-header {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 40px 1fr auto;
  align-items: center;
  gap: 14px;
  padding: 20px 24px;
}

.device-icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  color: #9ac8f2;
  background: #152535;
  border: 1px solid #294c6c;
  border-radius: 4px;
  font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
  font-size: 16px;
  font-weight: 700;
}

.device-icon-testing {
  color: #f8d995;
  background: #2d281a;
  border-color: #594a24;
}

.device-environment {
  color: #a9b5c0;
  font-weight: 650;
}

.device-card-header p {
  margin-bottom: 0;
  font-size: 12px;
}

.status-pill {
  padding: 5px 9px;
  color: #b5c0ca;
  background: #252d35;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 750;
}

.device-card .status-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 0;
  background: transparent;
  border-radius: 0;
  font-size: 12px;
  font-weight: 650;
}

.device-card .status-pill::before {
  width: 6px;
  height: 6px;
  background: currentColor;
  border-radius: 50%;
  content: "";
}

.device-card .status-pill.ready,
.device-card .status-pill.error {
  background: transparent;
}

.status-pill.ready {
  color: #a9e8c3;
  background: #173729;
}

.status-pill.error {
  color: #ffc3be;
  background: #432522;
}

.status-pill.warn {
  color: #f8d995;
  background: #40351d;
}

.metrics {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0;
  margin: 0;
  border-top: 1px solid var(--op-border);
  border-bottom: 1px solid var(--op-border);
}

.metrics div {
  min-width: 0;
  padding: 17px 24px 18px;
  border-right: 1px solid var(--op-border);
}

.metrics div:last-child {
  border-right: 0;
}

.metrics div:nth-child(2n) {
  border-right: 0;
}

.metrics div:nth-child(-n + 2) {
  border-bottom: 1px solid #262f37;
}

.metrics dt {
  margin-bottom: 8px;
  color: #7f8d98;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

.metrics dd {
  margin: 0;
  overflow: hidden;
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  font-weight: 650;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.device-message {
  align-self: center;
  min-height: 0;
  margin: 0;
  padding: 20px 24px;
  font-size: 13px;
}

.device-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 0 24px 20px;
}

.device-actions button {
  min-width: 96px;
}

.portal-build {
  grid-column: 1 / -1;
  align-self: end;
  margin: 18px 0 0;
  color: #71818f;
  font-size: 11px;
  text-align: center;
}

.login-card > .op-theme-toggle {
  width: 100%;
  margin-top: 14px;
}

.install-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 16px;
  margin-top: 18px;
  padding: 18px 24px;
  background: var(--op-surface);
  border: 1px solid var(--op-border);
  border-radius: 6px;
}

.install-card h2 {
  margin-bottom: 2px;
}

.install-card p {
  margin: 0;
  font-size: 13px;
}

.install-steps {
  grid-column: 1 / -1;
  margin: 4px 0 0;
  padding: 14px 18px 14px 34px;
  color: #c7d0d9;
  background: #0b0f13;
  border: 1px solid #29343e;
  border-radius: 6px;
  font-size: 13px;
  line-height: 1.9;
}

.install-steps svg {
  width: 16px;
  height: 16px;
  margin: 0 2px -3px;
  color: #72ade7;
}

@media (max-width: 620px) {
  .install-card {
    grid-template-columns: minmax(0, 1fr);
  }

  .install-card .secondary-button {
    width: 100%;
  }
}

.phone-view {
  /* Replaced at runtime with the shape Android actually reports, so the frame
     and the display it shows are the same shape and nothing is letterboxed.
     The fallback is the ReDroid boot display, used until the API answers. */
  --device-aspect: 0.5;
  /* Each ad slot is 50px of banner plus the 3px divider that separates it from
     the stage. The top one also carries the status-bar inset. The bottom one
     deliberately does not: the banner sits flush on the physical glass edge,
     inside the home-indicator zone — the centered indicator overlaps only the
     banner's empty middle, and the stage keeps the reclaimed rows.
     Floating controls position against these so nothing covers an ad. */
  --ad-top: calc(53px + env(safe-area-inset-top));
  --ad-bottom: 53px;
  --phone-chrome: calc(var(--ad-top) + var(--ad-bottom));
  /* The dynamic unit is the browser's live drawable scene: it follows Safari
     chrome, rotation, fullscreen, and installed-mode safe areas. */
  --phone-viewport: 100dvh;
  /* Absolute, not fixed. iOS 26 clips fixed viewport-sized containers to the
     small viewport (852pt glass, 793pt small viewport on an iPhone 15) and
     paints the reserved strip with the canvas color, while in-flow content
     provably paints the full glass — the scrolling dashboard reaches the
     bottom edge on the same device. The document is exactly one shell tall
     and touch-action: none keeps it unscrollable, so absolute and fixed pin
     identically everywhere else. */
  position: absolute;
  inset: 0;
  /* Safe areas are already consumed by the two ad slots. Subtracting the top
     inset here double-counts it and leaves a bottom band exactly one status
     bar tall on current iOS standalone WebKit. The shell owns the complete
     dynamic viewport; its flex stage gets every pixel left after both ads. */
  bottom: auto;
  height: var(--phone-viewport);
  overflow: hidden;
  background: #080a0d;
  overscroll-behavior: none;
  touch-action: none;
}

/* Installed iOS 26 keeps a strip of glass below the largest viewport the page
   can paint (852pt screen vs a 793pt viewport that never grows), and the OS
   fills that strip with the canvas color. While the phone is open, paint the
   canvas with the ad surface so the reserved strip continues the bottom
   banner instead of reading as a dead white block. */
body:has(#phone-view:not(.hidden)) {
  background: #faf9f5;
}

/* Dashboard Start needs the exact same stage geometry as Connect without
   flashing the phone view. The real layout is rendered invisibly for two
   animation frames, measured, then returned to display:none. */
.phone-view.hidden.measure-stage {
  z-index: -1;
  display: block !important;
  visibility: hidden;
  pointer-events: none;
}

/* The stage ResizeObserver and visualViewport listeners report every resulting
   geometry change. Android is negotiated only when entering an idle phone;
   resize noise while a viewer is active remains layout-only. */

.phone-page {
  display: flex;
  flex-direction: column;
  /* The browser's actual drawable box is authoritative. Android and the GPU
     encoder negotiate to this stage; the shell never reserves a phone-shaped
     desktop column or derives layout from physical screen dimensions. */
  width: var(--legacy-frame-width, 100%);
  max-width: none;
  /* Of the phone view rather than a viewport unit: .phone-view is the only
     element that knows the real screen height (see above), and everything
     inside simply fills it. No safe-area-inset-bottom is reserved on
     purpose — the stage runs under the home indicator like a real phone
     would, and reserving it would recreate the very band this removes.
     Interactive floating controls respect the inset individually. */
  height: 100%;
  min-height: 0;
  margin: 0;
  background: #0b0e11;
}

.phone-view.fluid-display .phone-page {
  width: 100%;
}

.ad-slot {
  display: flex;
  align-items: center;
  background: #171c22;
}

/* The top inset belongs to the slot rather than to .phone-page: the banner
   stays readable below the status bar while the slot's own background still
   runs to the glass instead of leaving a dead band. */
.ad-slot-top {
  flex: 0 0 calc(50px + env(safe-area-inset-top));
  padding-top: env(safe-area-inset-top);
}

.ad-slot-bottom {
  /* Flush on the glass: no home-indicator inset is reserved. The indicator
     is horizontally centered and the banner's middle is empty (brand left,
     CTA right), so the bar overlays nothing that reads or taps. */
  flex: 0 0 50px;
  background: #faf9f5;
}

/* Deliberately light against the dark portal: a placement is only worth
   judging at the contrast a real advertiser's creative would arrive with. */
.fake-ad {
  width: 100%;
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 0 12px;
  color: #1f1e1d;
  background: #faf9f5;
  border: 1px solid #e3e0d6;
  font-size: 13px;
  line-height: 1;
  user-select: none;
  pointer-events: none;
}

.fake-ad-cta {
  background: #f0eee6;
}

.ad-brand {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
}

.ad-mark {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  fill: #d97757;
}

.ad-copy {
  display: grid;
  gap: 3px;
  min-width: 0;
}

.ad-copy strong {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.ad-copy small {
  overflow: hidden;
  color: #6b6862;
  font-size: 10px;
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ad-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
}

.ad-chip {
  padding: 3px 5px;
  color: #6b6862;
  background: #e8e5dc;
  border-radius: 3px;
  font-size: 9px;
  font-weight: 750;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.ad-cta {
  padding: 6px 10px;
  color: #faf9f5;
  background: #d97757;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}

.impression {
  color: #6b6862;
  font-size: 10px;
  white-space: nowrap;
}

.impression strong {
  color: #1f1e1d;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}

.divider {
  flex: 0 0 3px;
  background: #3a4550;
}

.android-stage {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  background: #0b0e11;
}

#android-frame {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  background: #0b0e11;
  touch-action: none;
}

.ios-touch-proxy {
  position: absolute;
  z-index: 2;
  inset: 0;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

.stream-message {
  position: absolute;
  z-index: 3;
  inset: 0;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 14px;
  padding: 24px;
  color: #b8c2cc;
  background: #0b0e11;
  text-align: center;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}

.stream-message p {
  margin: 0;
}

.boot-progress {
  display: grid;
  justify-items: center;
  gap: 10px;
  width: min(260px, 100%);
}

.boot-progress-hint {
  color: #7f8b96;
  font-size: 12px;
  line-height: 1.4;
}

.boot-progress-track {
  width: 100%;
  height: 4px;
  overflow: hidden;
  background: rgba(184, 194, 204, 0.18);
  border-radius: 999px;
}

.boot-progress-fill {
  width: 0%;
  height: 100%;
  background: #8fc8ff;
  border-radius: inherit;
  /* Boot state is polled every 500ms; a matching linear transition turns the
     step updates into one continuous fill. */
  transition: width 0.5s linear;
}

.stream-message[data-waiting="true"]::before {
  position: absolute;
  top: calc(50% - 48px);
  left: calc(50% - 14px);
  width: 24px;
  height: 24px;
  border: 2px solid rgba(184, 194, 204, 0.22);
  border-top-color: #8fc8ff;
  border-radius: 50%;
  content: "";
  animation: stream-wait-spin 0.75s linear infinite;
}

@keyframes stream-wait-spin {
  to {
    transform: rotate(1turn);
  }
}

@media (prefers-reduced-motion: reduce) {
  .stream-message[data-waiting="true"]::before {
    animation-duration: 1.8s;
  }
}

.stream-message.error {
  color: #ffb4ad;
}

/* Every overlay in the phone view positions against .phone-view itself, not
   the viewport: they are its children, and it is the element whose box is
   corrected to the real glass in installed mode. position: fixed would anchor
   them to the status-bar-short ICB and float the bottom row 59pt up. */
.floating-button {
  position: absolute;
  z-index: 6;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  padding: 0;
  color: #e7edf3;
  background: rgba(18, 23, 29, 0.76);
  border: 1px solid rgba(126, 144, 161, 0.55);
  border-radius: 50%;
  backdrop-filter: blur(12px);
  font-size: 24px;
}

/* Every floating control clears the ad slots rather than overlapping them:
   a placement judged underneath a button is not the placement that ships. */
.floating-back {
  top: calc(var(--ad-top) + 12px);
  left: max(12px, env(safe-area-inset-left));
}

.floating-fullscreen {
  top: calc(var(--ad-top) + 12px);
  right: max(12px, env(safe-area-inset-right));
  font-size: 18px;
}

/* A real editable surface is required for iOS and Android browsers to raise
   their native keyboard. It is only enabled after the UHID safety proof. */
.native-keyboard-input {
  position: absolute;
  z-index: 5;
  left: 0;
  bottom: 0;
  width: 1px;
  height: 1px;
  padding: 0;
  border: 0;
  color: transparent;
  background: transparent;
  caret-color: transparent;
  opacity: 0;
  resize: none;
}

/* Viewport units are only readable through a property that resolves them, so
   the debug panel measures them off zero-width probes. Fixed data attributes
   keep the probes compatible with the portal's no-inline-style CSP. */
.viewport-unit-probe {
  position: fixed;
  top: 0;
  left: 0;
  width: 0;
  visibility: hidden;
  pointer-events: none;
}

.viewport-unit-probe[data-unit="vh"] {
  height: 100vh;
}

.viewport-unit-probe[data-unit="svh"] {
  height: 100svh;
}

.viewport-unit-probe[data-unit="lvh"] {
  height: 100lvh;
}

.viewport-unit-probe[data-unit="dvh"] {
  height: 100dvh;
}

.viewport-unit-probe[data-unit="pct"] {
  height: 100%;
}

/* env() is only readable through a property that resolves it, so the insets get
   measured off a zero-sized probe rather than guessed at from the device. */
.safe-area-probe {
  position: fixed;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  visibility: hidden;
  pointer-events: none;
  padding:
    env(safe-area-inset-top)
    env(safe-area-inset-right)
    env(safe-area-inset-bottom)
    env(safe-area-inset-left);
}

/* A small rounded box rather than a pill: it reads as the settings affordance
   it opens, and takes no more of the stream than the other controls. */
.floating-settings {
  /* Above the panel it opens: a launcher the panel covers cannot close it, and
     the panel is anchored clear of this button rather than over it. */
  z-index: 9;
  top: calc(var(--ad-top) + 112px);
  right: max(12px, env(safe-area-inset-right));
  bottom: auto;
  border-radius: 13px;
  font-size: 20px;
  line-height: 1;
}

.floating-settings[aria-expanded="true"] {
  color: #0b0e11;
  background: #7bb7ff;
  border-color: #7bb7ff;
}

.debug-panel {
  position: absolute;
  z-index: 8;
  top: calc(var(--ad-top) + 12px);
  right: max(12px, env(safe-area-inset-right));
  /* Clears the ad slot and the 42px settings button standing above it. */
  bottom: calc(var(--ad-bottom) + 64px);
  width: min(390px, calc(100vw - 24px));
  padding: 20px;
  overflow: auto;
  color: #edf3f8;
  background: rgba(13, 17, 22, 0.96);
  border: 1px solid rgba(105, 174, 252, 0.34);
  border-radius: 18px;
  box-shadow: 0 28px 80px rgba(0, 0, 0, 0.58);
  backdrop-filter: blur(18px);
  overscroll-behavior: contain;
  touch-action: pan-y;
}

.debug-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
}

.debug-header h2,
.debug-header .eyebrow {
  margin-bottom: 0;
}

.debug-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.debug-close {
  display: grid;
  place-items: center;
  width: 31px;
  height: 31px;
  padding: 0;
  color: #dbe5ed;
  background: #202832;
  border: 1px solid #3c4855;
  border-radius: 50%;
  font-size: 21px;
  line-height: 1;
}

.debug-note {
  margin: 16px 0 18px;
  color: #8f9eac;
  font-size: 11px;
  line-height: 1.5;
}

.debug-section {
  padding: 15px 0;
  border-top: 1px solid #28313a;
}

.debug-section h3 {
  margin: 0 0 11px;
  color: #bdc9d3;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.debug-section-first {
  padding-top: 18px;
  border-top: 0;
}

.debug-control {
  padding: 11px;
  background: #11171d;
  border: 1px solid #29343e;
  border-radius: 10px;
}

.debug-switch {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  cursor: pointer;
}

.debug-switch input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.debug-switch-track {
  position: relative;
  flex: 0 0 auto;
  width: 38px;
  height: 22px;
  margin-top: 1px;
  background: #202832;
  border: 1px solid #3c4855;
  border-radius: 999px;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.debug-switch-track::after {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 14px;
  height: 14px;
  background: #8b9aa8;
  border-radius: 50%;
  transition: transform 0.15s ease, background 0.15s ease;
  content: "";
}

.debug-switch input:checked + .debug-switch-track {
  background: #1d3c5c;
  border-color: #69aefc;
}

.debug-switch input:checked + .debug-switch-track::after {
  background: #69aefc;
  transform: translateX(16px);
}

.debug-switch input:focus-visible + .debug-switch-track {
  outline: 2px solid #69aefc;
  outline-offset: 2px;
}

.debug-switch input:disabled + .debug-switch-track {
  cursor: wait;
  opacity: 0.65;
}

.debug-switch-text {
  color: #e1e8ee;
  font-size: 12px;
  font-weight: 700;
}

.debug-switch-text small {
  display: block;
  margin-top: 4px;
  color: #81909d;
  font-size: 10px;
  font-weight: 500;
  line-height: 1.45;
}

/* Replaces the button that used to float over the video. It carries the same
   data-state the floating one did, because the states it reports — connecting,
   proven, unavailable — are the same ones Android takes seconds to reach. */
.debug-action {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  min-height: 36px;
  margin-top: 11px;
  padding: 0 12px;
  color: #e7edf3;
  background: #202832;
  border: 1px solid #3c4855;
  border-radius: 8px;
  font-size: 12px;
  font-weight: 700;
}

.debug-action-icon {
  font-size: 15px;
  line-height: 1;
}

.debug-action:focus-visible {
  outline: 2px solid #69aefc;
  outline-offset: 2px;
}

.debug-action[data-state="pending"] {
  cursor: progress;
  border-color: rgba(125, 187, 255, 0.75);
  opacity: 0.7;
}

.debug-action[data-state="ready"] {
  border-color: rgba(125, 187, 255, 0.75);
}

.debug-action[data-state="error"] {
  color: #ffc3be;
  border-color: rgba(255, 140, 130, 0.75);
}

.debug-action[aria-pressed="true"] {
  color: #0b0e11;
  background: #7bb7ff;
  border-color: #7bb7ff;
}

.debug-control-state {
  margin: 10px 0 0;
  color: #a9e8c3;
  font-size: 10px;
  font-weight: 650;
}

.debug-control-state.error {
  color: #ffc3be;
}

.debug-metric-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  margin: 0;
}

.debug-metric-grid div {
  padding: 11px;
  background: #11171d;
  border: 1px solid #29343e;
  border-radius: 10px;
}

.debug-metric-grid dt,
.service-health dt,
.debug-rows dt {
  color: #81909d;
  font-size: 10px;
}

.debug-metric-grid dd {
  margin: 5px 0 0;
  font-size: 16px;
  font-variant-numeric: tabular-nums;
  font-weight: 760;
}

.service-health {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 7px;
  margin: 0;
}

.service-health div,
.debug-rows div {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.service-health div {
  padding: 9px 10px;
  background: #11171d;
  border-radius: 8px;
}

.service-health dd {
  margin: 0;
  color: #a9e8c3;
  font-size: 11px;
  font-weight: 750;
}

.service-health dd.error {
  color: #ffc3be;
}

.debug-rows {
  display: grid;
  gap: 0;
  margin: 0;
}

.debug-rows div {
  min-height: 31px;
  padding: 6px 0;
  border-bottom: 1px solid rgba(48, 59, 69, 0.58);
}

.debug-rows div:last-child {
  border-bottom: 0;
}

.debug-rows dd {
  margin: 0;
  color: #e1e8ee;
  text-align: right;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  font-weight: 650;
}

.debug-event-log {
  display: grid;
  max-height: 210px;
  gap: 7px;
  margin: 0;
  padding: 9px;
  overflow: auto;
  color: #c8d4dd;
  background: #090e13;
  border: 1px solid #29343e;
  border-radius: 10px;
  font: 9px/1.45 ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  list-style: none;
  overscroll-behavior: contain;
}

.debug-event-log li {
  overflow-wrap: anywhere;
}

.debug-event-placeholder {
  color: #71818f;
}

.debug-updated {
  margin: 8px 0 0;
  color: #71818f;
  font-size: 10px;
  text-align: right;
}

.fullscreen-prompt {
  position: absolute;
  z-index: 10;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgba(3, 5, 7, 0.72);
  backdrop-filter: blur(8px);
}

.prompt-card {
  width: min(100%, 410px);
  padding: 24px;
  border-radius: 18px;
}

.prompt-card p {
  color: #a9b5c0;
  line-height: 1.5;
}

.prompt-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 22px;
}

@media (max-width: 620px) {
  .portal-view {
    padding-left: 16px;
    padding-right: 16px;
  }

  .dashboard-header {
    align-items: flex-start;
  }

  .login-card {
    padding: 24px;
  }

  .device-card {
    grid-template-columns: minmax(0, 1fr);
  }

  .device-card-header {
    padding: 18px 20px;
  }

  .metrics {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .metrics div {
    padding: 15px 20px 16px;
  }

  .metrics dd {
    font-size: 13px;
  }

  .metrics div:nth-child(2) {
    border-right: 0;
  }

  .metrics div:nth-child(-n + 2) {
    border-bottom: 1px solid var(--op-border);
  }

  .device-message {
    padding: 18px 20px 12px;
  }

  .device-actions {
    padding: 0 20px 20px;
  }

  .debug-panel {
    left: 12px;
    right: 12px;
    width: auto;
  }
}

@media (display-mode: fullscreen) {
  .floating-back,
  .floating-fullscreen {
    opacity: 0.35;
  }
}
