/* iPhone Cast — connect launcher.
 *
 * TOKENS ARE A MIRROR, NOT A SOURCE.
 * ----------------------------------
 * The :root block below is a verbatim value-for-value subset of
 * `web/src/styles/tokens.css`, which is `designer`'s file and the source of truth
 * (CLAUDE.md, "Tokens only"). It is copied rather than imported because this
 * directory deploys on its own to Cloudflare Pages with no build step, and a
 * relative import out of `web/src` would 404 there.
 *
 * A copy is a drift risk, so it is checked rather than trusted: `verify.mjs` step
 * "tokens" parses BOTH files and fails if any token named here has a different
 * value in the source. Do not edit a value here — change it in
 * `web/src/styles/tokens.css` and re-run the check.
 *
 * Only the tokens this page actually uses are copied. The long explanatory
 * comments live in the source file; the pointers below say where to look.
 */

:root {
  /* ---- Surfaces (light) ---- */
  --bg: #f7f7f9;
  --surface: #ffffff;
  --surface-secondary: #f2f3f7;

  /* ---- Text (light) ---- */
  --text-primary: #111218;
  --text-secondary: #6b6f7a;
  /* Decorative tier only — deliberately NOT AA text-compliant. Used here for the
   * placeholder glyphs and the separator dot, never for anything that has to be
   * read. See tokens.css decision #17. */
  --text-tertiary: #9a9da6;

  --border: rgba(20, 20, 30, 0.08);
  --hairline: 1px;

  /* ---- Accent (light) ---- */
  --accent: #5b42f3;
  --accent-hover: #5039e2;
  --accent-soft: rgba(91, 66, 243, 0.1);
  --accent-on-surface: #5b42f3;

  /* ---- Status (light) ---- */
  --success: #25a85b;
  --success-on-surface: #1b7a44;
  --warning-on-surface: #8a6100;
  --danger: #d63838;
  --danger-on-surface: #c93030;
  --warning: #e8a11a;

  --text-on-accent: #ffffff;
  --text-on-danger: #ffffff;

  /* ---- Typography ---- */
  --font-sans: Inter, "SF Pro Text", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  --text-display: 30px;
  --text-title: 24px;
  --text-section: 16px;
  --text-body: 15px;
  --text-meta: 13px;
  --text-micro: 11px;

  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  /* ---- Spacing (DESIGN.md §5) ---- */
  --space-xs: 4px;
  --space-sm: 8px;
  --space-md: 12px;
  --space-lg: 16px;
  --space-xl: 24px;
  --space-2xl: 32px;
  --space-3xl: 40px;

  /* ---- Radius ---- */
  --radius-control: 10px;
  --radius-button: 14px;
  --radius-card: 16px;
  --radius-panel: 22px;
  --radius-pill: 999px;

  /* ---- Touch targets ----
   * DESIGN.md §3 car conventions: 48px car-browser minimum, 52–64px for primary
   * controls. --touch-car (56px) is the floor for anything primary on this page.
   */
  --touch-min: 48px;
  --touch-car: 56px;
  --touch-car-lg: 64px;

  --focus-ring-width: 2px;
  --measure: 28em;

  /* ---- Motion (DESIGN.md §10) ---- */
  --duration-fast: 160ms;
  --duration-normal: 220ms;
  --duration-slow: 280ms;
  --ease-standard: cubic-bezier(0.32, 0.72, 0, 1);

  /* ---- Elevation ---- */
  --shadow-card: 0 1px 2px rgba(16, 18, 27, 0.04), 0 4px 16px rgba(16, 18, 27, 0.06);
}

/* Dark mode. Only the tokens change — never the hierarchy (DESIGN.md §16). */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0a0d12;
    --surface: #121722;
    --surface-secondary: #191f2b;

    --text-primary: #f7f8fa;
    --text-secondary: #9ea5b3;
    --text-tertiary: #737b88;

    --border: rgba(255, 255, 255, 0.08);

    --accent: #6b4eff;
    --accent-hover: #5e43ed;
    --accent-soft: rgba(107, 78, 255, 0.12);
    --accent-on-surface: #8874ff;

    --success: #34c76f;
    --success-on-surface: #34c76f;
    --danger: #d13941;
    --danger-on-surface: #e85560;
    --warning: #ffb938;
    --warning-on-surface: #ffb938;

    --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.32), 0 4px 16px rgba(0, 0, 0, 0.4);
  }
}

/* Explicit override so the car browser can be forced either way, independent of
 * whatever the head unit reports. Nothing on this page sets it today; it exists so
 * that adding a toggle later is a one-attribute change. */
:root[data-theme="dark"] {
  --bg: #0a0d12;
  --surface: #121722;
  --surface-secondary: #191f2b;

  --text-primary: #f7f8fa;
  --text-secondary: #9ea5b3;
  --text-tertiary: #737b88;

  --border: rgba(255, 255, 255, 0.08);

  --accent: #6b4eff;
  --accent-hover: #5e43ed;
  --accent-soft: rgba(107, 78, 255, 0.12);
  --accent-on-surface: #8874ff;

  --success: #34c76f;
  --success-on-surface: #34c76f;
  --danger: #d13941;
  --danger-on-surface: #e85560;
  --warning: #ffb938;
  --warning-on-surface: #ffb938;

  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.32), 0 4px 16px rgba(0, 0, 0, 0.4);
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-fast: 1ms;
    --duration-normal: 1ms;
    --duration-slow: 1ms;
  }
}

/* ------------------------------------------------------------------------- */

*,
*::before,
*::after { box-sizing: border-box; }

html {
  /* A car head unit is a touchscreen, not a trackpad. */
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: var(--text-body);
  line-height: 1.45;
  /* Nothing on this page is a drag surface. */
  -webkit-tap-highlight-color: transparent;
}

.shell {
  max-width: 34rem;
  margin: 0 auto;
  padding: var(--space-xl) var(--space-lg) var(--space-3xl);
  /* Notched phones — the user may open this page on the iPhone too. */
  padding-left: max(var(--space-lg), env(safe-area-inset-left));
  padding-right: max(var(--space-lg), env(safe-area-inset-right));
}

/* ---- Header ---- */

.head { margin-bottom: var(--space-xl); }

.head-title {
  margin: 0;
  font-size: var(--text-title);
  font-weight: var(--weight-bold);
  letter-spacing: -0.01em;
}

.head-sub {
  margin: var(--space-xs) 0 0;
  color: var(--text-secondary);
  font-size: var(--text-body);
}

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

.form {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  margin: 0;
}

.field { display: block; }

.field-label {
  display: block;
  margin-bottom: var(--space-sm);
  font-size: var(--text-section);
  font-weight: var(--weight-semibold);
}

.field-input {
  display: block;
  width: 100%;
  /* Car-browser control height. DESIGN.md §3: 48px minimum, 52–64px for the
   * controls that matter. These are the controls that matter. */
  min-height: var(--touch-car);
  padding: var(--space-md) var(--space-lg);
  border: var(--hairline) solid var(--border);
  border-radius: var(--radius-button);
  background: var(--surface);
  color: var(--text-primary);
  font-family: inherit;
  /* 17px, not --text-body. Below 16px iOS Safari zooms the whole page on focus,
   * which on a car screen leaves the layout scrolled sideways with no obvious way
   * back. Deliberately off the type scale for that reason; DESIGN.md §4's scale
   * governs reading text, not text fields on a touchscreen. */
  font-size: 17px;
  font-weight: var(--weight-medium);
  transition: border-color var(--duration-fast) var(--ease-standard),
              box-shadow var(--duration-fast) var(--ease-standard);
}

/* The session and token are transcribed character by character off a phone
 * screen. A tabular, wide-tracked face is the whole point. */
.field-input-code {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 20px;
  letter-spacing: 0.14em;
  text-transform: none;
}

.field-input::placeholder {
  color: var(--text-tertiary);
  letter-spacing: normal;
}

.field-input:focus-visible,
.field-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 var(--focus-ring-width) var(--accent-soft);
}

.field-input.is-bad {
  border-color: var(--danger);
}

.field-hint {
  margin: var(--space-sm) 0 0;
  max-width: var(--measure);
  color: var(--text-secondary);
  font-size: var(--text-meta);
}

/* A hint that has been replaced by a specific complaint about what was typed.
 * --danger-on-surface, not --danger: this is small text on --bg/--surface, which
 * is the direction --danger was never calibrated for (tokens.css decision #18). */
.field-hint.is-bad {
  color: var(--danger-on-surface);
  font-weight: var(--weight-medium);
}

.field-hint code {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.95em;
  color: var(--text-primary);
}

.field-hint.is-bad code { color: inherit; }

/* ---- URL preview ---- */

.preview {
  margin: var(--space-xl) 0 var(--space-lg);
  padding: var(--space-lg);
  border-radius: var(--radius-card);
  background: var(--surface-secondary);
}

.preview-label {
  margin: 0 0 var(--space-sm);
  color: var(--text-secondary);
  font-size: var(--text-micro);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.preview-url {
  margin: 0;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: var(--text-section);
  line-height: 1.5;
  /* An IP plus two codes will not fit one line on a phone. Break anywhere rather
   * than overflow — a URL the user cannot see all of defeats the point. */
  overflow-wrap: anywhere;
  word-break: break-all;
}

.preview-empty {
  color: var(--text-secondary);
  font-family: var(--font-sans);
  word-break: normal;
}

/* The two values the user just typed, marked in the assembled URL so a
 * transposed character is findable. */
.preview-value {
  color: var(--accent-on-surface);
  font-weight: var(--weight-semibold);
}

/* Two ranks, and the distinction is load-bearing rather than decorative.
 * `is-error` means the URL was NOT built and nothing will open. `is-advisory`
 * means it WAS built and will open — the shape is just unusual. Both rendered in
 * --danger-on-surface at first; an advisory painted like a failure teaches the
 * driver to ignore the colour, which costs the real error its meaning.
 * --warning-on-surface, not --warning: this is small text on --surface-secondary,
 * where --warning measures ~1.98:1 (tokens.css decision #18). */
.preview-problem {
  margin: var(--space-md) 0 0;
  font-size: var(--text-meta);
  font-weight: var(--weight-medium);
}

.preview-problem.is-error { color: var(--danger-on-surface); }
.preview-problem.is-advisory { color: var(--warning-on-surface); }

/* ---- Actions ---- */

.actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.btn {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--touch-car);
  padding: var(--space-md) var(--space-lg);
  border: none;
  border-radius: var(--radius-button);
  font-family: inherit;
  font-size: var(--text-section);
  font-weight: var(--weight-semibold);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-standard),
              opacity var(--duration-fast) var(--ease-standard);
}

.btn:focus-visible {
  outline: var(--focus-ring-width) solid var(--accent);
  outline-offset: 2px;
}

.btn-primary {
  min-height: var(--touch-car-lg);
  background: var(--accent);
  color: var(--text-on-accent);
  font-size: 17px;
}

.btn-primary:hover { background: var(--accent-hover); }

.btn-secondary {
  min-height: var(--touch-car);
  border: var(--hairline) solid var(--border);
  background: var(--surface);
  color: var(--accent-on-surface);
}

.btn-quiet {
  min-height: var(--touch-min);
  background: transparent;
  color: var(--text-secondary);
  font-size: var(--text-body);
  font-weight: var(--weight-medium);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* An <a> has no disabled attribute, and a disabled-looking control that still
 * navigates is worse than one that looks enabled. The JS REMOVES href when the
 * input cannot produce a URL; this only has to make that state legible and
 * un-tappable. `pointer-events: none` alone would be a lie to a keyboard, so
 * href removal is the real mechanism and this is the paint. */
.btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}

.actions-note {
  margin: var(--space-xs) 0 0;
  color: var(--text-secondary);
  font-size: var(--text-meta);
}

/* ---- Scan (optional) ---- */

.scan {
  margin-top: var(--space-2xl);
  padding-top: var(--space-lg);
  border-top: var(--hairline) solid var(--border);
}

.scan-body { margin-top: var(--space-md); }

.scan-video {
  display: none;
  width: 100%;
  max-height: 40vh;
  border-radius: var(--radius-card);
  background: #000;
  object-fit: cover;
}

.scan-body.is-live .scan-video { display: block; }

.scan-status {
  margin: var(--space-md) 0 0;
  color: var(--text-secondary);
  font-size: var(--text-meta);
}

.scan-status.is-bad { color: var(--danger-on-surface); }
.scan-status.is-good { color: var(--success-on-surface); }

/* ---- Footer ---- */

.foot {
  margin-top: var(--space-2xl);
  padding-top: var(--space-lg);
  border-top: var(--hairline) solid var(--border);
  max-width: var(--measure);
  color: var(--text-secondary);
  font-size: var(--text-meta);
}

.foot p { margin: 0 0 var(--space-sm); }
.foot strong { color: var(--text-primary); }
.foot-quiet { color: var(--text-secondary); }

/* ---- Wide car screen ----
 * A Tesla centre screen is landscape and roughly 1200–1400 CSS px wide. Two
 * columns keeps the primary button above the fold instead of below a scroll.
 */
@media (min-width: 60rem) and (min-height: 30rem) {
  .shell {
    max-width: 68rem;
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "head    head"
      "form    preview"
      "form    actions"
      "scan    foot";
    column-gap: var(--space-2xl);
    align-content: start;
  }
  .head    { grid-area: head; }
  .form    { grid-area: form; }
  .preview { grid-area: preview; margin-top: 0; }
  .actions { grid-area: actions; align-self: start; }
  .scan    { grid-area: scan; }
  .foot    { grid-area: foot; }
}
