/* FrownGuard — dark, calm, technical. */

:root {
  --bg: #0b0d10;
  --bg-soft: #12151a;
  --panel: #14181e;
  --panel-2: #1a1f26;
  --line: #252b34;
  --line-soft: #1d222a;

  --text: #e8ecf2;
  --muted: #8d97a6;
  --faint: #5f6875;

  --ok: #4ade80;
  --warn: #fbbf24;
  --bad: #f87171;
  --accent: #60a5fa;
  --accent-dim: #1e3a5f;

  --radius: 14px;
  --radius-sm: 9px;
  --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 8px 24px rgba(0, 0, 0, .25);
}

* { box-sizing: border-box; }

/* An author `display` rule beats the UA stylesheet's [hidden] { display: none },
   so anything toggled via the hidden attribute needs this to actually hide.
   Without it .fatal, .cal and .stage-hud are permanently on screen. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 14px/1.55 ui-sans-serif, -apple-system, "SF Pro Text", "Segoe UI", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -0.011em; }
p { margin: 0; }
.muted { color: var(--muted); }

/* ------------------------------------------------------------------ topbar */
.topbar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 14px 22px;
  background: rgba(11, 13, 16, .86);
  backdrop-filter: saturate(140%) blur(12px);
  border-bottom: 1px solid var(--line);
}
.brand { display: flex; align-items: center; gap: 10px; }
.brand-mark {
  width: 20px; height: 20px; border-radius: 6px;
  background: linear-gradient(140deg, var(--accent), #a78bfa);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .08) inset;
}
.brand-name { font-weight: 650; letter-spacing: -0.015em; }
.chips { display: flex; gap: 7px; flex-wrap: wrap; }
.topbar-actions { margin-left: auto; }

.chip {
  font-size: 12px; line-height: 1.4; padding: 3px 10px;
  border: 1px solid var(--line); border-radius: 999px;
  color: var(--muted); white-space: nowrap;
}
.chip.live { color: var(--ok); border-color: #1e4634; background: #0f2419; }
.chip.warn { color: var(--warn); border-color: #4a3a17; background: #241d0f; }
.chip.bad { color: var(--bad); border-color: #4a2222; background: #241313; }

/* ------------------------------------------------------------------ layout */
.layout {
  display: grid; gap: 18px;
  grid-template-columns: minmax(0, 1.25fr) minmax(340px, 0.75fr);
  align-items: start;
  max-width: 1400px; margin: 0 auto; padding: 18px 22px 8px;
}
@media (max-width: 980px) { .layout { grid-template-columns: 1fr; } }

.col-stage { display: grid; gap: 14px; min-width: 0; }
.col-side { display: grid; gap: 14px; min-width: 0; }

/* ------------------------------------------------------------------- stage */
.stage {
  position: relative; aspect-ratio: 4 / 3; overflow: hidden;
  background: #000; border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
  transition: box-shadow .2s;
}
.stage.tense { box-shadow: inset 0 0 0 3px var(--bad), var(--shadow); }
.stage.paused { box-shadow: inset 0 0 0 3px var(--warn), var(--shadow); }
.stage video, .stage canvas#overlay {
  position: absolute; inset: 0; width: 100%; height: 100%;
  transform: scaleX(-1);            /* a mirror is what people expect */
  /* Both must crop identically. A canvas is a replaced element, so object-fit
     applies to its bitmap too — without this the overlay stretches while the
     video is cropped, and the mesh slides off the face on any non-4:3 camera. */
  object-fit: cover;
}

.stage-empty {
  position: absolute; inset: 0; display: grid; place-content: center;
  justify-items: center; gap: 8px; padding: 32px; text-align: center;
}
.stage-empty-mark {
  width: 42px; height: 42px; border-radius: 50%;
  border: 2px solid var(--line); position: relative;
}
.stage-empty-mark::after {
  content: ""; position: absolute; inset: 11px 9px auto 9px; height: 2px;
  border-radius: 2px; background: var(--faint);
}
.stage-empty-title { font-weight: 600; }
.stage-empty-sub { color: var(--muted); font-size: 13px; max-width: 34ch; }

.stage-hud {
  position: absolute; left: 12px; bottom: 12px; display: flex; gap: 14px;
  padding: 7px 12px; border-radius: 999px;
  background: rgba(8, 10, 13, .66); border: 1px solid rgba(255, 255, 255, .07);
  backdrop-filter: blur(8px); font-size: 12px;
}
.hud-item { display: flex; gap: 6px; align-items: baseline; }
.hud-k { color: var(--faint); }
.hud-v { font-variant-numeric: tabular-nums; }

.stage-banner {
  position: absolute; top: 12px; left: 50%; transform: translateX(-50%);
  padding: 7px 14px; border-radius: 999px; font-size: 13px; font-weight: 500;
  background: rgba(8, 10, 13, .8); border: 1px solid rgba(255, 255, 255, .1);
  backdrop-filter: blur(8px); white-space: nowrap;
}
.stage-banner.warn { color: var(--warn); border-color: #4a3a17; }
.stage-banner.bad { color: var(--bad); border-color: #4a2222; }

.cal {
  position: absolute; inset: 0; display: grid; place-content: center;
  justify-items: center; gap: 12px; text-align: center; padding: 30px;
  background: rgba(8, 10, 13, .86); backdrop-filter: blur(3px);
}
.cal-step { font-size: 11px; letter-spacing: .09em; text-transform: uppercase; color: var(--accent); }
.cal-count { font-size: 64px; font-weight: 200; line-height: 1; font-variant-numeric: tabular-nums; }
.cal-msg { font-size: 19px; font-weight: 600; max-width: 26ch; }
.cal-hint { font-size: 13px; color: var(--muted); max-width: 36ch; }

/* ------------------------------------------------------------------- cards */
.cardrow { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
@media (max-width: 720px) { .cardrow { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.card {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 12px 14px;
  transition: border-color .2s, background .2s;
}
.card.alert { border-color: #4a3a17; background: #1d1810; }
.card.bad { border-color: #4a2222; background: #1d1313; }
.card h3 {
  font-size: 11px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--muted); font-weight: 600; margin-bottom: 6px;
}
.card-value { font-size: 19px; font-weight: 500; font-variant-numeric: tabular-nums; }
.card-note { font-size: 12px; color: var(--faint); margin-top: 3px; }

/* ------------------------------------------------------------------ panels */
.panel {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px; box-shadow: var(--shadow);
}
.panel h2 {
  font-size: 11px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--muted); margin-bottom: 12px;
}

.score { display: flex; align-items: baseline; gap: 10px; margin-bottom: 9px; }
.score-num { font-size: 34px; font-weight: 300; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.score-state { font-size: 13px; color: var(--muted); }

.track {
  position: relative; height: 8px; border-radius: 5px; overflow: hidden;
  background: #0a0c0f; border: 1px solid var(--line-soft);
}
.track.lg { height: 13px; border-radius: 7px; }
.fill {
  height: 100%; width: 0; border-radius: inherit;
  background: var(--ok); transition: width .1s linear, background .25s;
}
.fill.warn { background: var(--warn); }
.fill.bad { background: var(--bad); }
.mark { position: absolute; top: -2px; bottom: -2px; width: 2px; background: #fff; opacity: .8; }

.signals { display: grid; gap: 9px; margin-top: 16px; }
.sig { display: grid; grid-template-columns: 92px 1fr 34px; align-items: center; gap: 10px; }
.sig-name { font-size: 12px; color: var(--muted); }
.sig-val { font-size: 12px; color: var(--muted); text-align: right; font-variant-numeric: tabular-nums; }
.sig.off { opacity: .35; }

.spark { width: 100%; height: 90px; display: block; border-radius: var(--radius-sm); background: #0a0c0f; }
.stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px 16px; margin-top: 14px; }
.stats > div { display: flex; justify-content: space-between; gap: 8px; font-size: 13px; }
.stat-k { color: var(--muted); }
.stat-v { font-variant-numeric: tabular-nums; }

/* ----------------------------------------------------------------- controls */
.btn {
  font: inherit; font-size: 13px; font-weight: 500;
  padding: 8px 15px; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--panel-2); color: var(--text);
  cursor: pointer; transition: background .13s, border-color .13s, opacity .13s;
}
.btn:hover:not(:disabled) { background: #222831; border-color: #39434f; }
.btn:disabled { opacity: .4; cursor: default; }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #06121f; font-weight: 650; }
.btn.primary:hover:not(:disabled) { background: #7db8f9; border-color: #7db8f9; }
.btn.danger { background: #241313; border-color: #4a2222; color: var(--bad); }
.btn.ghost { background: transparent; }
.btn.full { width: 100%; margin-top: 4px; }
.btnrow { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }

.field { display: grid; gap: 6px; margin-bottom: 16px; }
.field-label { display: flex; justify-content: space-between; font-size: 13px; color: var(--muted); }
.field-label b { color: var(--text); font-weight: 500; font-variant-numeric: tabular-nums; }
.field-hint { font-size: 12px; color: var(--faint); }
input[type=range] { width: 100%; accent-color: var(--accent); }

.toggles { border: 0; padding: 0; margin: 0 0 14px; display: grid; gap: 9px; }
.toggles legend {
  font-size: 11px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--muted); padding: 0; margin-bottom: 9px;
}
.toggles label { display: flex; align-items: center; gap: 9px; font-size: 13px; cursor: pointer; }
.toggles input { accent-color: var(--accent); width: 15px; height: 15px; }

.note {
  margin-top: 12px; padding: 10px 12px; border-radius: var(--radius-sm);
  font-size: 12.5px; line-height: 1.5;
  background: #1a1410; border: 1px solid #3d2f1c; color: #f0c98a;
}
.note.ok { background: #0f2419; border-color: #1e4634; color: #9be3b6; }
.note.bad { background: #241313; border-color: #4a2222; color: #f2a8a8; }

/* ------------------------------------------------------------------ footer */
.foot {
  max-width: 1400px; margin: 0 auto; padding: 10px 22px 28px;
  color: var(--faint); font-size: 12.5px;
}

/* ------------------------------------------------------------------- fatal */
.fatal { position: fixed; inset: 0; display: grid; place-content: center; background: rgba(6, 8, 10, .82); z-index: 50; padding: 24px; }
.fatal-box {
  max-width: 44ch; display: grid; gap: 12px; padding: 22px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
}
.fatal-box h2 { font-size: 17px; }
.fatal-box p { color: var(--muted); font-size: 13.5px; }
.fatal-box .btn { justify-self: start; }

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

/* ------------------------------------------------------------- auth pages */
.auth-page {
  min-height: 100vh; display: grid; place-content: center;
  padding: 32px 22px; gap: 18px; justify-items: center;
}
.auth-card {
  width: min(420px, 100%); background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 26px; box-shadow: var(--shadow); display: grid; gap: 16px;
}
.auth-head { display: grid; gap: 6px; }
.auth-head h1 { font-size: 19px; }
.auth-head p { color: var(--muted); font-size: 13.5px; }
.auth-brand { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }

.form-row { display: grid; gap: 6px; }
.form-row label { font-size: 13px; color: var(--muted); }
.form-row input {
  font: inherit; font-size: 14px; padding: 9px 12px; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: #0e1116; color: var(--text); width: 100%;
}
.form-row input:focus { outline: 2px solid var(--accent); outline-offset: -1px; border-color: transparent; }
.form-row .hint { font-size: 12px; color: var(--faint); }

.form-error {
  padding: 9px 12px; border-radius: var(--radius-sm); font-size: 13px;
  background: #241313; border: 1px solid #4a2222; color: #f2a8a8;
}
.form-ok {
  padding: 9px 12px; border-radius: var(--radius-sm); font-size: 13px;
  background: #0f2419; border: 1px solid #1e4634; color: #9be3b6;
}
.auth-foot { font-size: 12.5px; color: var(--faint); text-align: center; max-width: 46ch; }
.auth-foot a, .link { color: var(--accent); text-decoration: none; }
.auth-foot a:hover, .link:hover { text-decoration: underline; }

/* --------------------------------------------------------------- admin ui */
.admin-wrap { max-width: 900px; margin: 0 auto; padding: 20px 22px 40px; display: grid; gap: 16px; }
.table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.table th {
  text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--muted); font-weight: 600; padding: 0 10px 8px 0; border-bottom: 1px solid var(--line);
}
.table td { padding: 10px 10px 10px 0; border-bottom: 1px solid var(--line-soft); vertical-align: middle; }
.table tr:last-child td { border-bottom: 0; }
.table .right { text-align: right; }
.tag {
  font-size: 11px; padding: 2px 8px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--muted);
}
.tag.valid { color: var(--ok); border-color: #1e4634; }
.tag.accepted { color: var(--accent); border-color: var(--accent-dim); }
.tag.expired, .tag.revoked { color: var(--faint); }
.tag.admin { color: #c4b5fd; border-color: #3b2f66; }
.inline-form { display: flex; gap: 8px; flex-wrap: wrap; align-items: end; }
.inline-form .form-row { flex: 1 1 240px; }
.copyable {
  display: flex; gap: 8px; align-items: center; margin-top: 10px;
  padding: 9px 12px; border-radius: var(--radius-sm);
  background: #0e1116; border: 1px solid var(--line);
}
.copyable code {
  flex: 1; font-size: 12px; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; color: var(--text);
}
.account { display: flex; align-items: center; gap: 8px; }
.sync-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--faint); }
.sync-dot.saving { background: var(--warn); }
.sync-dot.saved { background: var(--ok); }
.sync-dot.error { background: var(--bad); }

/* =========================================================================
   Mobile
   -------------------------------------------------------------------------
   Phones are a different device, not a narrow desktop: the camera is portrait,
   fingers are imprecise, and the screen is the scarce resource. The layout is
   reordered so the meter sits directly under your face rather than below four
   cards you'd have to scroll past.
   ========================================================================= */

/* The stream's real shape, set from the video track once the camera opens.
   A phone's front camera is usually portrait; forcing 4:3 would crop the face. */
.stage { aspect-ratio: var(--stage-aspect, 4 / 3); }

@media (max-width: 760px) {
  .layout {
    display: flex; flex-direction: column; gap: 13px;
    padding: 13px max(13px, env(safe-area-inset-right)) 8px max(13px, env(safe-area-inset-left));
  }
  /* Dissolve the two columns so their children can be interleaved. */
  .col-stage, .col-side { display: contents; }

  .stage              { order: 1; }
  .panel-tension      { order: 2; }
  .cardrow            { order: 3; }
  .panel-session      { order: 4; }
  .panel-calibration  { order: 5; }
  .panel-settings     { order: 6; }

  /* A portrait stream can be taller than the screen; cap it so the meter is
     visible without scrolling. */
  .stage { max-height: 58vh; }

  .topbar {
    padding: 10px max(13px, env(safe-area-inset-right)) 10px max(13px, env(safe-area-inset-left));
    gap: 10px;
  }
  .topbar-actions { width: 100%; display: flex; gap: 8px; }
  .topbar-actions #btnToggle { flex: 1; }
  .chips { order: 3; width: 100%; }
  .foot { padding: 8px 16px 26px; }

  .panel { padding: 14px; }
  .cardrow { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .card-value { font-size: 17px; }
  .score-num { font-size: 30px; }
  .sig { grid-template-columns: 80px 1fr 32px; }
  .stats { grid-template-columns: 1fr; }
  .spark { height: 76px; }
}

@media (max-width: 380px) {
  .cardrow { grid-template-columns: 1fr; }
  .sig { grid-template-columns: 74px 1fr 30px; }
}

/* Touch targets. Apple and Google both put the floor near 44px, and a slider
   thumb you can't hit is worse than no slider. */
@media (pointer: coarse) {
  .btn { min-height: 44px; padding: 10px 16px; }
  .toggles label { min-height: 40px; }
  .toggles input { width: 20px; height: 20px; }
  input[type="range"] { height: 34px; }
  .field { margin-bottom: 20px; }
  .table td, .table th { padding-top: 13px; padding-bottom: 13px; }
}

/* iOS zooms the page when a focused input's text is under 16px. */
@media (max-width: 760px) {
  .form-row input, select, input[type="text"], input[type="email"], input[type="password"] {
    font-size: 16px;
  }
}

/* 100vh on mobile includes browser chrome that then slides away. */
.auth-page { min-height: 100vh; min-height: 100dvh; }

/* Landscape on a phone is mostly the video; keep the chrome out of the way. */
@media (max-height: 480px) and (orientation: landscape) and (pointer: coarse) {
  .topbar { position: static; }
  .stage { max-height: 78vh; }
}
