/*
 * The Android app's design system, in CSS.
 *
 * Same palette, same glass cards, same 20px corners, so the two clients
 * look like one product. Nothing here is generated and nothing is imported:
 * a stylesheet is the one part of a web app that never needed a library.
 */

:root {
  --bg-deep: #070b16;
  --bg-raise: #0c1526;
  --glow-blue: #1d4e8f;
  --glow-purple: #3a2c63;

  --accent: #1e90ff;
  --accent-bright: #4fc3f7;

  --text: #f2f6ff;
  --text-2: #9aa8bf;
  --text-3: #6b7a90;

  --success: #34c759;
  --warning: #ffb020;
  --danger: #ff453a;

  --card: rgba(255, 255, 255, 0.045);
  --card-raise: rgba(255, 255, 255, 0.075);
  --card-border: rgba(255, 255, 255, 0.09);

  --radius: 20px;
  --radius-sm: 14px;
  --pad: 18px;

  /* A wall panel is landscape and a phone is not; one column that stops
     growing is the only layout both of them want. */
  --column: 720px;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0;
  min-height: 100%;
  background: var(--bg-deep);
  color: var(--text);
  font: 16px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
        "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* The app's own sky. Fixed, because a gradient that scrolls with a long
   list reads as a seam. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(1200px 700px at 12% -10%, rgba(29, 78, 143, 0.38), transparent 70%),
    radial-gradient(900px 600px at 100% 8%, rgba(58, 44, 99, 0.32), transparent 70%),
    linear-gradient(160deg, var(--bg-raise), var(--bg-deep) 55%);
}

.app {
  /*max-width: var(--column);*/
  margin: 0 auto;
  padding: max(18px, env(safe-area-inset-top)) 18px
           max(24px, env(safe-area-inset-bottom));
}

/* --- type ---------------------------------------------------------------- */

h1 { font-size: 26px; font-weight: 700; margin: 0; letter-spacing: -0.2px; }
h2 { font-size: 19px; font-weight: 600; margin: 0; }
h3 { font-size: 16px; font-weight: 600; margin: 0; }
p  { margin: 0; }

.muted   { color: var(--text-2); font-size: 14px; }
.faint   { color: var(--text-3); font-size: 13px; }
.danger  { color: var(--danger); }
.success { color: var(--success); }
.warning { color: var(--warning); }

/* --- layout -------------------------------------------------------------- */

.row { display: flex; align-items: center; gap: 12px; }
.row.wrap { flex-wrap: wrap; }
.grow { flex: 1 1 auto; min-width: 0; }
.stack { display: flex; flex-direction: column; gap: 10px; }
.stack.tight { gap: 6px; }
/* Two lines that are one sentence: the gap a stack leaves reads as two
   unrelated things, and the line boxes already carry their own air. */
.stack.snug { gap: 0; }
.stack.snug > .faint { line-height: 1.2; }
.stack.snug > h2 { line-height: 1.2; }
.stack.loose { gap: 18px; }
.center { display: flex; align-items: center; justify-content: center; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.section-label {
  color: var(--text-2);
  font-size: 15px;
  font-weight: 600;
  padding: 10px 4px 0;
}

/* --- cards --------------------------------------------------------------- */

.card {
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: var(--radius);
  padding: var(--pad);
  backdrop-filter: blur(14px);
}
.card.tap { cursor: pointer; transition: background 120ms ease; }
.card.tap:active { background: var(--card-raise); }
.card.flat { padding: 0; overflow: hidden; }

.divider { height: 1px; background: var(--card-border); margin-left: var(--pad); }

.icon-box {
  width: 44px; height: 44px;
  flex: 0 0 44px;
  border-radius: 13px;
  background: var(--card-raise);
  display: flex; align-items: center; justify-content: center;
  font-size: 20px;
}
.icon-box.on {
  background: rgba(30, 144, 255, 0.22);
  color: var(--accent-bright);
}

/* --- controls ------------------------------------------------------------ */

button {
  font: inherit;
  color: inherit;
  border: 0;
  background: none;
  cursor: pointer;
}

.btn {
  padding: 13px 20px;
  border-radius: 999px;
  background: linear-gradient(100deg, var(--accent), var(--accent-bright));
  color: #fff;
  font-weight: 600;
  text-align: center;
}
.btn:disabled { opacity: 0.45; cursor: default; }
.btn.wide { display: block; width: 100%; }
.btn.danger { background: linear-gradient(100deg, var(--danger), #ff9f40); }
.btn.quiet {
  background: var(--card-raise);
  color: var(--text);
  font-weight: 500;
}

.link {
  color: var(--accent-bright);
  font-weight: 600;
  padding: 8px 4px;
}

.field { display: block; }
.field > span {
  display: block;
  color: var(--text-2);
  font-size: 13px;
  padding: 0 4px 6px;
}
.field input, .field select {
  width: 100%;
  padding: 14px 16px;
  border-radius: var(--radius-sm);
  background: var(--card-raise);
  border: 1px solid var(--card-border);
  color: var(--text);
  font: inherit;
}
/* A filter, not a form field: the label sits above in small type and the
   control is only as wide as it needs to be. */
.field.inline { flex: 0 1 auto; min-width: 128px; }
.field.inline > span { padding-bottom: 3px; font-size: 12px; }
.field.inline select { padding: 9px 10px; font-size: 14px; }

.field input:focus, .field select:focus {
  outline: none;
  border-color: var(--accent);
}

/* A switch, drawn rather than imported. */
.switch {
  width: 52px; height: 32px;
  flex: 0 0 52px;
  border-radius: 999px;
  background: var(--card-raise);
  border: 1px solid var(--card-border);
  position: relative;
  transition: background 140ms ease;
}
.switch::after {
  content: "";
  position: absolute;
  top: 3px; left: 3px;
  width: 24px; height: 24px;
  border-radius: 999px;
  background: var(--text-3);
  transition: transform 140ms ease, background 140ms ease;
}
.switch[aria-checked="true"] { background: var(--accent); border-color: transparent; }
.switch[aria-checked="true"]::after { transform: translateX(20px); background: #fff; }
.switch[aria-busy="true"] { opacity: 0.5; }

.round {
  width: 38px; height: 38px;
  flex: 0 0 38px;
  border-radius: 999px;
  background: var(--card-raise);
  display: flex; align-items: center; justify-content: center;
  font-size: 17px;
}
.round.accent { background: rgba(30, 144, 255, 0.2); color: var(--accent-bright); }

/* The three shutter buttons in a dialog, where there is room for a real target. */
.round.big {
  width: 54px; height: 54px;
  flex: 0 0 54px;
  font-size: 22px;
}

/* Smaller than a number on its own, because the drawing sits next to it. */
.marker-value { font-size: 0.7em; }

/* A style that carries its reading: the drawing, then the number beside it. */
.marker-value {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.1em;
  line-height: 1;
}

/*
 * The star is a preference, not a control, so it is drawn faint and without
 * a chip behind it: on a row of a dozen devices it must not compete with the
 * switch that actually does something.
 */
.star {
  flex: 0 0 auto;
  padding: 6px 4px;
  font-size: 19px;
  line-height: 1;
  color: var(--text-3);
  opacity: 0.55;
}
.star.on { color: #f5b942; opacity: 1; }
.star:hover { opacity: 1; }

/* The dashboard's one piece of identity, and the way into Settings. */
.logo {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  padding: 0;
  border-radius: 13px;
  overflow: hidden;
}
.logo img { display: block; border-radius: 11px; }

/* The same mark on the auth screens: no chip behind it, sized to itself. */
.logo.plain {
  align-self: flex-start;
  border-radius: 18px;
  background: none;
}
.logo.plain img { border-radius: 16px; }

/* A target the buttons have moved but the house has not been told about. */
.draft { opacity: 0.75; }

.chip {
  padding: 9px 16px;
  border-radius: 999px;
  background: var(--card-raise);
  color: var(--text-2);
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
}
.chip.on { background: var(--accent); color: #fff; }

/* --- the connection badge ------------------------------------------------ */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 40px;
  padding: 0 14px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}
.badge.bare { padding: 0 12px; }
.badge .dot {
  width: 8px; height: 8px;
  border-radius: 999px;
  background: currentColor;
}
.badge.ok      { color: var(--success); background: rgba(52, 199, 89, 0.14); }
.badge.trying  { color: var(--warning); background: rgba(255, 176, 32, 0.14); }
.badge.off     { color: var(--danger);  background: rgba(255, 69, 58, 0.14); }
.badge.trying .dot { animation: pulse 900ms ease-in-out infinite alternate; }

@keyframes pulse { from { opacity: 0.25; } to { opacity: 1; } }

/* --- the plan ------------------------------------------------------------ */

.plan {
  position: relative;
  background: #000;
  border-radius: var(--radius);
  overflow: hidden;
  touch-action: pan-y;
  /* So a marker can size its text against the **drawing** rather than the
     viewport: everything on a plan is a fraction of the image's width, the
     numbers included. */
  container-type: inline-size;
}
.plan img { display: block; width: 100%; height: auto; }

/* Positions are fractions of the drawn image, never pixels: the same plan
   is drawn at every width there is. */
.marker {
  position: absolute;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  font-weight: 700;
  /* No border, and both colours come from the placement: the disc and the
     tint are the installer's choice, and "on" is shown by the drawing
     changing shape rather than by the disc turning blue — the same as on the
     tablet, because it is the same plan. */
  background: rgba(0, 0, 0, 0.35);
  color: rgba(255, 255, 255, 0.85);
}

/* --- toast --------------------------------------------------------------- */

.toast-host {
  position: fixed;
  left: 0; right: 0;
  bottom: max(20px, env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  pointer-events: none;
  z-index: 50;
}
.toast {
  max-width: min(92vw, var(--column));
  padding: 12px 18px;
  border-radius: 999px;
  background: rgba(12, 21, 38, 0.95);
  border: 1px solid var(--card-border);
  font-size: 14px;
}

/* --- sheets and dialogs -------------------------------------------------- */

.scrim {
  position: fixed;
  inset: 0;
  background: rgba(3, 6, 12, 0.72);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px;
  z-index: 40;
}
.sheet {
  width: min(100%, 460px);
  max-height: 86vh;
  overflow: auto;
  background: var(--bg-raise);
  border: 1px solid var(--card-border);
  border-radius: 24px;
  padding: 22px;
}

/* --- splash -------------------------------------------------------------- */

.splash {
  min-height: 70vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
}
.splash img { width: 108px; height: 108px; }

.spinner {
  width: 22px; height: 22px;
  border-radius: 999px;
  border: 2px solid rgba(255, 255, 255, 0.18);
  border-top-color: var(--accent-bright);
  animation: spin 800ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

[dir="rtl"] .switch::after { left: auto; right: 3px; }
[dir="rtl"] .switch[aria-checked="true"]::after { transform: translateX(-20px); }
