/* ============================================================
   app.css — go.sixsenselabs.com
   Brand theme extracted from sixsenselabs.com (Wix theme vars):
     bg #141416 · surface #1B1C1E · line #3F4349 · text #FFFFFF
     text-2 #8A8A8A · accent #EC34AE · accent-deep #C6067F
   Typography: Montserrat (brand heading face), self-hosted
   variable woff2 — no external requests at runtime.
   ============================================================ */

@font-face {
  font-family: 'Montserrat';
  src: url('../fonts/montserrat-var-latin.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --bg: #141416;
  --bg-glow: rgba(236, 52, 174, 0.07);
  --card: #1b1c1e;
  --card-border: #2c2e33;
  --text: #ffffff;
  --text-2: #a7a7ab;
  --text-3: #8a8a8a;
  --accent: #ec34ae;
  --accent-press: #c6067f;
  --accent-ink: #ffffff;
  --accent-soft: rgba(236, 52, 174, 0.1);
  --good: #34d399;
  --bad: #ff6a55;
  --field: #121316;
  --field-border: #3f4349;
  --radius: 14px;
}

* { box-sizing: border-box; }

/* The UA's [hidden] rule loses to any author `display` (e.g. .card's flex) —
   re-assert it at author level or every view renders stacked. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
}

body {
  min-height: 100dvh;
  background:
    radial-gradient(1200px 600px at 50% -200px, var(--bg-glow), transparent),
    var(--bg);
  color: var(--text);
  font-family: 'Montserrat', system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  display: flex;
  justify-content: center;
}

.shell {
  width: 100%;
  max-width: 430px;
  padding: 28px 16px 20px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

/* .stage groups the view cards so desktop can place them as one grid cell;
   on mobile it must not break the .shell column flow. */
.stage { display: contents; }

/* ---------- brand ---------- */

.brand { text-align: center; }

.brand-mark {
  margin: 0 0 6px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.34em;
  color: var(--text-3);
}

.brand-title {
  margin: 0;
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.brand-title span {
  display: block;
  font-size: 15px;
  font-weight: 500;
  color: var(--accent);
  margin-top: 2px;
  letter-spacing: 0.06em;
}

/* Desktop-only brand copy — hidden in the phone column layout. */
.brand-lede, .brand-points { display: none; }

/* ---------- card ---------- */

.card {
  background: var(--card);
  border: 1px solid var(--card-border);
  border-radius: var(--radius);
  padding: 22px 20px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.35);
}

.card.center { align-items: center; text-align: center; }

/* The wifi credentials <form> (password-manager semantics) must lay out
   exactly like the card it lives in — flex column, same rhythm, buttons
   stretched — or the submit button collapses to content width. */
.card form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.card h2 {
  margin: 0;
  font-size: 19px;
  font-weight: 650;
  letter-spacing: -0.01em;
}

.step {
  margin: 0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}

.hint { margin: 0; font-size: 14px; line-height: 1.55; color: var(--text-2); }
.hint.small { font-size: 12.5px; color: var(--text-3); }
.fineprint { margin: 0; font-size: 12px; line-height: 1.5; color: var(--text-3); }

.error {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--bad);
}

/* Same slot, different weight of voice. Some of what lands here is not a
   failure — cancelling the device chooser is a choice the user made — and red
   would tell them they broke something they did not. */
.error.notice {
  color: var(--text-2);
}

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

.field { display: flex; flex-direction: column; gap: 6px; }

.field span {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-2);
}

.field input {
  appearance: none;
  width: 100%;
  background: var(--field);
  border: 1px solid var(--field-border);
  border-radius: 10px;
  color: var(--text);
  font: inherit;
  font-size: 16px; /* >=16px prevents iOS zoom-on-focus */
  padding: 12px 14px;
  outline: none;
  transition: border-color 120ms ease;
}

.field input:focus { border-color: var(--accent); }

#token-input {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.45em;
  text-align: center;
  font-size: 22px;
}

/* ---------- buttons ---------- */

button {
  font: inherit;
  border: none;
  border-radius: 10px;
  cursor: pointer;
  transition: background 120ms ease, transform 60ms ease;
}

button:active { transform: translateY(1px); }

.primary {
  background: var(--accent-press);
  color: var(--accent-ink);
  font-weight: 700;
  font-size: 15.5px;
  padding: 13px 16px;
}

.primary:hover { background: var(--accent); }
.primary:disabled { opacity: 0.55; cursor: default; }

.ghost {
  background: transparent;
  border: 1px solid var(--field-border);
  color: var(--text-2);
  font-size: 13px;
  padding: 8px 12px;
  white-space: nowrap;
}

.ghost:hover { border-color: var(--accent); color: var(--text); }
.ghost:disabled { opacity: 0.55; cursor: default; }

.linklike {
  background: none;
  border: none;
  color: var(--accent);
  font-size: 13px;
  font-weight: 600;
  padding: 8px 0;
  text-align: left;
}

.linklike:hover { color: var(--accent-press); }

/* ---------- gate copy row ---------- */

.copy-row {
  display: flex;
  gap: 8px;
  align-items: center;
  min-width: 0;
}

.url {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  background: var(--field);
  border: 1px solid var(--field-border);
  border-radius: 8px;
  padding: 9px 11px;
  font-size: 12.5px;
  color: var(--text-2);
}

/* ---------- device chip ---------- */

.chip {
  margin: 0;
  align-self: flex-start;
  background: var(--field);
  border: 1px solid var(--field-border);
  border-radius: 999px;
  padding: 6px 12px;
  font-size: 12.5px;
  color: var(--text-2);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- SSID picker ---------- */

.picker { display: flex; flex-direction: column; gap: 10px; }

.netlist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 244px;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.net {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  text-align: left;
  background: var(--field);
  border: 1px solid var(--field-border);
  border-radius: 10px;
  color: var(--text);
  font-size: 15px;
  font-weight: 500;
  padding: 12px 14px;
  overflow: hidden;
  transition: border-color 120ms ease, background 120ms ease;
}

.net:hover { border-color: var(--accent); }

.net[aria-selected="true"] {
  border-color: var(--accent);
  background: var(--accent-soft);
}

/* Wi-Fi glyph, drawn with a currentColor mask so it follows text color. */
.net::before {
  content: "";
  flex: none;
  width: 18px;
  height: 18px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 18.2a2.2 2.2 0 1 0 0 4.4 2.2 2.2 0 0 0 0-4.4zM4.9 14.1l2.15 2.15a7 7 0 0 1 9.9 0l2.15-2.15a10 10 0 0 0-14.2 0zM.65 9.85 2.8 12a13 13 0 0 1 18.4 0l2.15-2.15a16 16 0 0 0-22.7 0z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 18.2a2.2 2.2 0 1 0 0 4.4 2.2 2.2 0 0 0 0-4.4zM4.9 14.1l2.15 2.15a7 7 0 0 1 9.9 0l2.15-2.15a10 10 0 0 0-14.2 0zM.65 9.85 2.8 12a13 13 0 0 1 18.4 0l2.15-2.15a16 16 0 0 0-22.7 0z'/%3E%3C/svg%3E") center / contain no-repeat;
}

.net-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Signal / "open" hint, pushed to the trailing edge. Recedes so the SSID stays
   the thing you read: this is context for choosing, not the choice itself. */
.net-meta {
  flex: none;
  margin-left: auto;
  padding-left: 10px;
  font-size: 12px;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  color: var(--text-3);
}

.picker-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
}

/* ---------- progress / done ---------- */

.spinner {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: 4px solid var(--card-border);
  border-top-color: var(--accent);
  animation: spin 0.9s linear infinite;
  margin: 6px 0;
}

@keyframes spin { to { transform: rotate(360deg); } }

.okmark {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: rgba(52, 211, 153, 0.12);
  color: var(--good);
  font-size: 38px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 6px 0;
}

/* ---------- footer ---------- */

.foot {
  text-align: center;
  font-size: 12px;
  color: var(--text-3);
  margin-top: auto;
  padding-top: 8px;
}

.foot a { color: var(--text-3); }

/* ---------- small screens ---------- */

@media (max-width: 360px) {
  .shell { padding: 20px 10px 16px; }
  .card { padding: 18px 14px; }
  .brand-title { font-size: 22px; }
}

/* ---------- desktop (two-pane hero) ----------
   Brand pane left, active card right, footer across the bottom.
   .stage collapses the sibling cards into one grid cell (only one
   card is ever visible — [hidden] removes the rest from the flow). */

@media (min-width: 900px) {
  .shell {
    max-width: 1060px;
    min-height: 100dvh;
    padding: 48px 40px 24px;
    display: grid;
    grid-template-columns: minmax(0, 1fr) 460px;
    grid-template-rows: 1fr auto;
    column-gap: 72px;
    align-items: center;
  }

  .brand {
    grid-column: 1;
    grid-row: 1;
    text-align: left;
    max-width: 460px;
  }

  .brand-mark { font-size: 12px; }

  .brand-title { font-size: 46px; letter-spacing: -0.02em; }

  .brand-title span {
    font-size: 20px;
    margin-top: 8px;
    letter-spacing: 0.08em;
  }

  .brand-lede {
    display: block;
    margin: 18px 0 0;
    font-size: 16.5px;
    line-height: 1.6;
    color: var(--text-2);
  }

  .brand-points {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin: 22px 0 0;
    padding: 0;
    list-style: none;
    font-size: 14px;
    color: var(--text-2);
  }

  .brand-points li {
    display: flex;
    align-items: center;
    gap: 10px;
  }

  .brand-points li::before {
    content: "";
    flex: none;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--accent);
  }

  .stage {
    display: block;
    grid-column: 2;
    grid-row: 1;
  }

  .card { padding: 30px 28px; gap: 16px; }

  .card h2 { font-size: 22px; }

  .foot {
    grid-column: 1 / -1;
    grid-row: 2;
    margin-top: 0;
    padding-top: 24px;
  }
}

/* Respect reduced-motion users: freeze the spinner rotation. */
@media (prefers-reduced-motion: reduce) {
  .spinner { animation-duration: 3s; }
}

/* ============================================================
   Demo mode (?demo=1) — see js/demo.js
   ============================================================
   Deliberately loud. These frames end up in a document another team
   builds from, and a demo screenshot that is not obviously a demo
   screenshot becomes evidence of behaviour nobody ever observed.
   It is also sticky: the banner has to survive scrolling, or a
   cropped capture loses the only thing marking it as simulated. */

#demo-banner {
  /* FIXED, not sticky. body is `display: flex` (row), and a sticky element
     stays IN the flex flow -- so the banner became a flex ITEM and rendered as
     a narrow vertical pink strip down the left edge instead of a band across
     the top. It shipped that way and the first round of documentation
     screenshots came back unmarked, which is the exact failure this banner
     exists to prevent. Fixed positioning takes it out of flow entirely, so it
     does not care what the parent's layout is today or becomes later. */
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  line-height: 18px;   /* deterministic height: 10 + 18 + 10 = 38px */
  padding: 10px 14px;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-align: center;
  /* The band is the signal; do not let it be mistaken for a toast that
     can be dismissed. No close button, no fade. */
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
}

/* The banner is out of flow, so the page must make room for it itself. */
body.demo-mode { padding-top: 38px; }

/* Second marker, INSIDE the card — defence in depth, and not redundancy.
   The top band is the right signal for a full-window capture and is worth
   nothing the moment someone crops to the card, which is exactly what people
   do when the card is the subject. Round one of the documentation screenshots
   lost the marking to a flexbox bug; round two lost it to cropping, on five of
   nine frames. Two different causes, one outcome: an unmarked frame of a
   simulated device, heading into a document another team builds from.
   This one travels with the content it could be mistaken for. */
.demo-mode .card { position: relative; }
.demo-mode .card::after {
  content: 'DEMO';
  position: absolute;
  top: 0;
  right: 0;
  padding: 3px 9px;
  /* Matches the card's own corner on the outside, square on the inside, so it
     reads as part of the card rather than an element floating over it. */
  border-radius: 0 var(--radius) 0 8px;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  pointer-events: none;
}
