/*
 * Reusable UI components: form controls, primary button, password
 * show/hide toggle, inline error box. Used by login.html and (when
 * Round 10 / 12 land) the dashboard shell + settings modal.
 */

/* ---- Form fields ---- */

label {
  display: block;
  font-size: 17px;
  color: var(--ink);
  margin-bottom: 8px;
  font-weight: 400;
}

input[type="email"],
input[type="password"],
input[type="text"] {
  width: 100%;
  padding: 12px 14px;
  background: var(--input-bg);
  color: var(--ink);
  border: 0;
  border-radius: 10px;
  font: inherit;
  outline: none;
}
input:focus-visible {
  box-shadow: 0 0 0 2px var(--focus);
}

/*
 * Override Chrome's autofill yellow/cream background on saved-credential
 * fills. Chrome blocks direct `background-color` on `:-webkit-autofill`,
 * so the canonical hack is a giant inset box-shadow + a long transition
 * delay (Chrome animates the bg change; 5000 s effectively never).
 * Symptom-only in Chrome's normal mode -- incognito and Safari are
 * fine because autofill is disabled / works differently there.
 */
input:autofill,
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
  -webkit-text-fill-color: var(--ink);
  -webkit-box-shadow: 0 0 0 1000px var(--input-bg) inset;
  caret-color: var(--ink);
  /* Force the input's font on autofilled values too. Without this,
   * Chrome shows the autofilled email/password in its own (system)
   * font until you focus the field -- jarring "font swap" on click. */
  font-family: inherit !important;
  font-size: inherit !important;
  font-weight: inherit !important;
  transition: background-color 5000s ease-in-out 0s;
}

/* ---- Password show/hide toggle (used inside .password-wrap) ---- */

.password-wrap { position: relative; }
.password-wrap input { padding-right: 46px; }

.toggle-pw {
  position: absolute;
  top: 50%;
  right: 8px;
  transform: translateY(-50%);
  background: transparent;
  border: 0;
  padding: 6px;
  cursor: pointer;
  border-radius: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.toggle-pw:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.toggle-pw img {
  display: block;
  width: 20px;
  height: 20px;
  opacity: 0.95;
  pointer-events: none;
}

/* ---- Primary button (white pill) ---- */

.btn-primary {
  align-self: flex-start;
  padding: 9px 22px;
  background: #f1f2f2;
  color: #0a0d12;
  border: 0;
  border-radius: 999px;
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}
.btn-primary:hover { background: #ffffff; }
.btn-primary:disabled { opacity: 0.6; cursor: progress; }

/* ---- Icon button (header help / settings, control-row affordances) ---- */

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 6px;
  background: transparent;
  border: 0;
  border-radius: 8px;
  cursor: pointer;
}
.icon-btn:hover { background: color-mix(in oklab, var(--ink) 8%, transparent); }
.icon-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.icon-btn img { width: 20px; height: 20px; opacity: 0.85; pointer-events: none; }

/* ---- Online status indicator (wifi-style icon, control row) ---- */

.online-indicator {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  display: block;
}
.online-indicator.is-pending {
  /* Hidden but holds layout space, so the surrounding control-row
   * doesn't shift when the first poll resolves and the icon swaps in. */
  visibility: hidden;
}

/* ---- Device dropdown (native select, restyled to match the dark theme) ---- */

.device-select {
  appearance: none;
  -webkit-appearance: none;
  background: var(--input-bg);
  color: var(--ink);
  border: 0;
  border-radius: 999px;
  padding: 7px 32px 7px 14px;
  font: inherit;
  font-size: 15px;
  cursor: pointer;
  /* Inline chevron via SVG data URI -- avoids one more icon file. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%23f1f2f2' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><path d='M1 1.5l5 5 5-5'/></svg>");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 10px 6px;
  outline: none;
}
/* Soft non-blue focus ring -- keeps keyboard-accessibility without
 * the harsh default browser blue outline. */
.device-select:focus-visible {
  outline: 2px solid color-mix(in oklab, var(--ink) 25%, transparent);
  outline-offset: 1px;
}

/* ---- Blink sync (sensor-time colon + polar now-line) ---- */
/*
 * Any element with `.blink-sync` is hidden while `<body>` carries
 * `.blink-off`. main.js's CLOCK_TICK_MS interval flips that
 * class on body, producing a 1 Hz blink for every tagged element in
 * lockstep -- no per-element animation state to keep in sync.
 *
 * `visibility: hidden` (not `display: none`) is intentional: layout
 * stays stable, so "11:52" doesn't reflow to "1152" on each blink.
 * Same reasoning for the SVG line: visibility leaves the line's
 * box untouched and avoids any reflow.
 */

body.blink-off .blink-sync { visibility: hidden; }

/* ---- Settings modal ---- */

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: color-mix(in oklab, #000 60%, transparent);
  display: grid;
  place-items: center;
  padding: 24px;
  z-index: 100;
}
.modal-backdrop[hidden] { display: none; }

.modal-panel {
  width: 100%;
  max-width: 360px;
  max-height: calc(100dvh - 48px);
  overflow-y: auto;
  background: #16181c;
  border: 1px solid color-mix(in oklab, var(--ink) 8%, transparent);
  border-radius: 14px;
  padding: 20px 22px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}
.modal-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: var(--ink);
}
.modal-close {
  background: transparent;
  border: 0;
  color: var(--ink-dim);
  font-size: 24px;
  line-height: 1;
  padding: 4px 8px;
  cursor: pointer;
  border-radius: 6px;
}
.modal-close:hover { color: var(--ink); background: color-mix(in oklab, var(--ink) 6%, transparent); }
.modal-close:focus-visible { outline: 2px solid color-mix(in oklab, var(--ink) 25%, transparent); outline-offset: 1px; }

/* Generic row pattern. Each row is one line (or two -- label + control). */
.modal-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 0;
  font-size: 15px;
  color: var(--ink);
  border: 0;
  background: transparent;
  text-align: left;
  width: 100%;
}

.modal-row--radio { padding: 8px 0; }
.modal-row__label {
  color: var(--ink-dim);
  font-size: 14px;
  flex: 0 0 auto;
}
.modal-row__radios {
  display: flex;
  gap: 14px;
  flex: 0 0 auto;
}
.modal-radio {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  font-size: 14px;
  color: var(--ink);
}
.modal-radio input[type="radio"] {
  /* Native radio, just sized small. Round 14 polish can swap for a
   * fully-styled segmented control if the visual calls for it. */
  margin: 0;
  cursor: pointer;
  accent-color: var(--ink);
}

.modal-row--info {
  color: var(--ink-dim);
  font-size: 14px;
  padding: 12px 0;
  cursor: default;
  justify-content: flex-start;
}

.modal-row--disabled {
  color: color-mix(in oklab, var(--ink) 35%, transparent);
  cursor: not-allowed;
  justify-content: flex-start;
}

.modal-row--action {
  cursor: pointer;
  font-weight: 500;
  justify-content: flex-start;
}
.modal-row--action:hover { color: var(--ink); background: color-mix(in oklab, var(--ink) 6%, transparent); border-radius: 6px; padding-left: 6px; padding-right: 6px; }
.modal-row--action:focus-visible { outline: 2px solid color-mix(in oklab, var(--ink) 25%, transparent); outline-offset: 1px; border-radius: 6px; }

/* ---- Back-to-top button ---- */

.back-to-top {
  position: fixed;
  right: 20px;
  bottom: 20px;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: #16181c;
  color: var(--ink);
  border: 1px solid color-mix(in oklab, var(--ink) 12%, transparent);
  border-radius: 999px;
  cursor: pointer;
  padding: 0;
  z-index: 50;
  box-shadow: 0 4px 14px color-mix(in oklab, #000 45%, transparent);
}
.back-to-top[hidden] { display: none; }
.back-to-top:hover { background: #1c1f24; }
.back-to-top:focus-visible { outline: 2px solid color-mix(in oklab, var(--ink) 25%, transparent); outline-offset: 2px; }
.back-to-top svg { width: 18px; height: 18px; display: block; }

/* ---- Empty-state placeholder card ---- */

.empty-state-card {
  max-width: 480px;
  margin: 64px auto;
  padding: 40px 28px;
  text-align: center;
  background: #16181c;
  border: 1px solid color-mix(in oklab, var(--ink) 8%, transparent);
  border-radius: 14px;
}
.empty-state-card__heading {
  margin: 0 0 10px;
  font-size: 18px;
  font-weight: 600;
  color: var(--ink);
}
.empty-state-card__body {
  margin: 0;
  font-size: 15px;
  color: var(--ink-dim);
  line-height: 1.5;
}
.empty-state-card__link {
  background: transparent;
  border: 0;
  padding: 0;
  font: inherit;
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
}
.empty-state-card__link:hover { color: #ffffff; }
.empty-state-card__link:focus-visible {
  outline: 2px solid color-mix(in oklab, var(--ink) 25%, transparent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ---- Inline error box ---- */

.error {
  display: none;
  padding: 10px 12px;
  border: 1px solid color-mix(in oklab, var(--error) 50%, transparent);
  background: color-mix(in oklab, var(--error) 12%, transparent);
  color: var(--ink);
  border-radius: 8px;
  font-size: 14px;
}
.error.is-shown { display: block; }
