/* ===================================================================
   LIVR iD — live speaker identification
   A precise instrument on white. Monochrome until there's a signal;
   pine green (#20543d, from the logo) means "verified".
   =================================================================== */
:root{
  --bg:#ffffff;
  --paper:#f7f8f6;        /* panel surface */
  --paper-2:#eef1ec;      /* insets, tracks */
  --ink:#0b0f0d;          /* near-black text + logo */
  --ink-2:#222a26;
  --muted:#5d6661;        /* secondary text */
  --muted-2:#919b94;      /* tertiary / placeholders */
  --line:#e6e9e4;         /* hairline */
  --line-2:#d9ded7;       /* stronger hairline */
  --brand:#20543d;        /* pine green — the logo */
  --brand-deep:#163a2a;
  --live:#2f9e6a;         /* active / verify energy */
  --live-tint:#e9f4ee;    /* soft green wash */
  --warn:#b07514;         /* loading/busy — status only */
  --bad:#c0473b;          /* failure/error — status only */

  --font:"Inter", system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
  --r:16px; --r-sm:11px; --r-xs:8px;

  --shadow-sm:0 1px 2px rgba(16,28,22,.04), 0 4px 16px rgba(16,28,22,.05);
  --shadow-md:0 18px 50px rgba(14,32,24,.10), 0 4px 14px rgba(14,32,24,.05);

  --ease:cubic-bezier(.22,.7,.25,1);
}
*{box-sizing:border-box}
html,body{margin:0;height:100%}
body{
  background:
    radial-gradient(1100px 560px at 88% -10%, rgba(32,84,61,.035), transparent 60%),
    radial-gradient(820px 460px at -5% 108%, rgba(32,84,61,.028), transparent 55%),
    var(--bg);
  color:var(--ink);
  font-family:var(--font);
  font-optical-sizing:auto;
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
  line-height:1.5; overflow-x:hidden;
}
::selection{background:rgba(32,84,61,.16)}
.num{font-variant-numeric:tabular-nums; font-feature-settings:"tnum" 1, "cv05" 1}

.wrap{max-width:1200px; margin:0 auto; min-height:100%; display:flex; flex-direction:column; padding:0 clamp(16px,4vw,40px)}

/* ===================== header ===================== */
header{
  display:flex; align-items:center; gap:18px; flex-wrap:wrap;
  padding:22px 2px 20px; position:sticky; top:0; z-index:20;
  background:linear-gradient(180deg, rgba(255,255,255,.92), rgba(255,255,255,.66));
  backdrop-filter:blur(10px) saturate(1.1);
  border-bottom:1px solid var(--line);
}
/* Brand lockup: wordmark + "iD" + beta, all vertically centered on one line. */
.brand{display:inline-flex; align-items:center; gap:10px; text-decoration:none; position:relative}
.wordmark{height:25px; width:auto; display:block}
.wordmark path{fill:var(--ink); transition:fill .4s var(--ease)}
.brand-id{font-size:21px; font-weight:600; letter-spacing:-.01em; color:var(--brand); line-height:1}
.brand-beta{
  font-size:10px; font-weight:600; letter-spacing:.14em; text-transform:uppercase;
  color:var(--brand); background:var(--live-tint);
  border:1px solid rgba(32,84,61,.2);
  padding:3px 8px; border-radius:100px; line-height:1;
}
/* one-time underline sweep on load */
.brand::after{
  content:""; position:absolute; left:2px; right:2px; bottom:-7px; height:2px;
  background:linear-gradient(90deg, var(--brand), var(--live)); border-radius:2px;
  transform:scaleX(0); transform-origin:left; opacity:.0;
}
.js .brand::after{animation:sweep 1.1s var(--ease) .15s forwards}
@keyframes sweep{
  0%{transform:scaleX(0);opacity:.9} 60%{transform:scaleX(1);opacity:.9}
  100%{transform:scaleX(1);opacity:0}
}

.hdr-meta{margin-left:auto; display:flex; align-items:center; gap:9px; flex-wrap:wrap}
.chip{
  display:inline-flex; align-items:center; gap:8px;
  font-size:11.5px; font-weight:500; color:var(--muted);
  background:#fff; border:1px solid var(--line); border-radius:100px;
  padding:6px 12px; transition:border-color .3s, color .3s, box-shadow .3s;
}
.chip-dot{width:8px;height:8px;border-radius:50%; background:var(--muted-2); flex:none;
  transition:background .35s, box-shadow .35s}
.chip-dot.on{background:var(--live); box-shadow:0 0 0 4px rgba(47,158,106,.16); animation:breathe 2.4s ease-in-out infinite}
.chip-dot.warn{background:var(--warn); box-shadow:0 0 0 4px rgba(176,117,20,.16); animation:breathe 1.3s ease-in-out infinite}
.chip-dot.busy{background:var(--warn); box-shadow:0 0 0 4px rgba(176,117,20,.16); animation:breathe 1.1s ease-in-out infinite}
.chip.live{color:var(--ink); border-color:rgba(47,158,106,.4); box-shadow:0 0 0 3px rgba(47,158,106,.07)}
.chip-ico{width:9px;height:9px;border-radius:2px; background:var(--muted-2); flex:none}
@keyframes breathe{50%{opacity:.45}}

/* ===================== layout ===================== */
/* Symmetric console: Enroll (card) · centered identity hero · Results (card).
   Equal-width flanking cards keep the hero ring on the page's centre line. */
main{
  flex:1; display:grid; grid-template-columns:300px minmax(0,1fr) 300px;
  gap:clamp(20px,2.4vw,34px); padding:clamp(22px,3.4vw,40px) 2px; align-items:start;
}
@media (max-width:1040px){
  main{grid-template-columns:1fr; gap:24px}
  .stage{order:1}
  .rail{order:2}
  .results{order:3}
  .rail, .results{position:static}
}

/* shared side-panel card (left rail + right results) */
.rail, .results{
  background:var(--paper); border:1px solid var(--line); border-radius:var(--r);
  padding:24px 22px; box-shadow:var(--shadow-sm); align-self:start;
  position:sticky; top:96px;
}

.eyebrow{
  font-size:11px; font-weight:600; letter-spacing:.2em; text-transform:uppercase;
  color:var(--muted); margin:0 0 16px; display:flex; align-items:center; gap:10px;
}
.count-badge{
  font-size:11px; font-weight:600; color:var(--brand); background:var(--live-tint);
  border-radius:100px; padding:1px 9px; letter-spacing:.02em;
}

/* ---- form ---- */
.field{margin-bottom:18px}
.lbl{display:block; font-size:12px; font-weight:500; color:var(--muted); margin-bottom:8px; letter-spacing:.01em}
input[type=text]{
  width:100%; background:#fff; border:1px solid var(--line-2); color:var(--ink);
  padding:12px 14px; border-radius:var(--r-sm); font-family:inherit; font-size:14.5px; outline:none;
  transition:border-color .2s, box-shadow .2s;
}
input[type=text]::placeholder{color:var(--muted-2)}
input[type=text]:focus{border-color:var(--brand); box-shadow:0 0 0 4px rgba(32,84,61,.1)}

.filebtn{
  display:flex; align-items:center; gap:12px; width:100%;
  background:#fff; border:1.5px dashed var(--line-2); color:var(--muted);
  padding:13px 14px; border-radius:var(--r-sm); cursor:pointer; font-size:13.5px;
  transition:border-color .2s, color .2s, background .2s, box-shadow .2s;
}
.filebtn:hover{border-color:var(--brand); color:var(--ink); background:var(--live-tint)}
.filebtn.has-file{border-style:solid; border-color:rgba(47,158,106,.5); color:var(--ink); background:var(--live-tint)}
.filebtn-ico{display:inline-flex; color:var(--brand); flex:none}
.filebtn .fn{overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
input[type=file]{display:none}

.orline{display:flex; align-items:center; gap:12px; margin:14px 0; color:var(--muted-2);
  font-size:10.5px; letter-spacing:.22em; text-transform:uppercase}
.orline::before,.orline::after{content:""; height:1px; background:var(--line); flex:1}

.recrow{display:flex; align-items:center; gap:12px}
.recbtn{
  flex:none; cursor:pointer; border:1px solid var(--line-2); background:#fff; color:var(--ink);
  border-radius:var(--r-sm); padding:10px 16px; font-family:inherit; font-weight:600; font-size:13.5px;
  display:inline-flex; align-items:center; gap:9px; transition:transform .08s, border-color .2s, background .2s, box-shadow .2s;
}
.recbtn:active{transform:translateY(1px)}
.recbtn:disabled{cursor:not-allowed; opacity:.45}
.recbtn:hover:not(:disabled){border-color:var(--brand); box-shadow:0 0 0 3px rgba(32,84,61,.07)}
.recbtn .rdot{width:9px;height:9px;border-radius:50%; background:var(--bad); flex:none}
.recbtn.recording{background:var(--bad); color:#fff; border-color:transparent}
.recbtn.recording .rdot{background:#fff; animation:blink 1s steps(2,start) infinite}
@keyframes blink{50%{opacity:.2}}

.recmeter{flex:1; height:8px; background:var(--paper-2); border-radius:6px; overflow:hidden}
.recmeter i{display:block; height:100%; width:0%;
  background:linear-gradient(90deg, var(--live), var(--brand)); border-radius:6px; transition:width .08s linear}
.rectime{font-size:12px; color:var(--muted); min-width:42px; text-align:right; font-weight:500}

.linkbtn{margin-top:11px; background:none; border:none; color:var(--brand); font-family:inherit;
  font-size:12.5px; font-weight:600; cursor:pointer; padding:0; transition:color .2s}
.linkbtn:hover{color:var(--live)}
.linkbtn[hidden]{display:none}

/* ---- buttons ---- */
.btn{
  width:100%; border:none; cursor:pointer; border-radius:var(--r-sm); padding:14px 18px;
  font-family:inherit; font-weight:600; font-size:14.5px; letter-spacing:-.005em; position:relative;
  overflow:hidden; transition:transform .08s var(--ease), box-shadow .25s, background .25s, opacity .2s;
}
.btn:active{transform:translateY(1px)}
.btn:disabled{cursor:not-allowed; opacity:.4}
.btn-primary{background:var(--brand); color:#fff; box-shadow:0 6px 18px rgba(32,84,61,.22)}
.btn-primary:hover:not(:disabled){background:var(--brand-deep); box-shadow:0 10px 26px rgba(32,84,61,.3); transform:translateY(-1px)}
.btn-live{background:var(--brand); color:#fff; box-shadow:0 6px 18px rgba(32,84,61,.22); margin-top:0}
.btn-live:hover:not(:disabled){background:var(--brand-deep); box-shadow:0 10px 26px rgba(32,84,61,.3); transform:translateY(-1px)}
.btn-live.recording{background:var(--ink); box-shadow:0 6px 18px rgba(11,15,13,.25)}
.btn-live.recording:hover:not(:disabled){background:#000}
.btn-live.busy{opacity:.7}
/* sheen on enabled primary actions */
.btn-primary:not(:disabled)::after, .btn-live:not(:disabled)::after{
  content:""; position:absolute; inset:0 auto 0 -130%; width:55%;
  background:linear-gradient(100deg, transparent, rgba(255,255,255,.32), transparent);
  transform:skewX(-18deg); animation:sheen 5s ease-in-out infinite;
}
@keyframes sheen{0%,62%{left:-130%}82%,100%{left:130%}}

/* ---- voiceprints ---- */
.voiceprints{margin-top:28px; border-top:1px solid var(--line); padding-top:22px}
.vp-list{list-style:none; margin:12px 0 0; padding:0; display:flex; flex-direction:column; gap:8px}
.vp{display:flex; align-items:center; gap:12px; background:#fff;
  border:1px solid var(--line); border-radius:var(--r-sm); padding:11px 13px;
  animation:slidein .28s var(--ease); transition:border-color .2s, box-shadow .2s}
.vp:hover{border-color:var(--line-2); box-shadow:var(--shadow-sm)}
@keyframes slidein{from{opacity:0; transform:translateY(-6px)}to{opacity:1; transform:none}}
.vp .tag{width:10px;height:10px;border-radius:50%; background:var(--brand); flex:none;
  box-shadow:0 0 0 3px var(--live-tint)}
.vp .vn{font-weight:500; font-size:14px; flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.vp .cnt{font-size:11.5px; color:var(--muted); font-variant-numeric:tabular-nums; flex:none}
.vp .rm{background:none;border:none;color:var(--muted-2);cursor:pointer;font-size:18px;line-height:1;
  padding:2px 4px;border-radius:6px;transition:color .2s, background .2s; flex:none}
.vp .rm:hover{color:var(--bad); background:rgba(192,71,59,.08)}
.empty{font-size:13px; color:var(--muted); background:#fff; border:1px dashed var(--line-2); border-radius:var(--r-sm);
  padding:15px; line-height:1.55}

/* ===================== live stage (centre) ===================== */
.stage{display:flex; flex-direction:column; align-items:center; padding:4px 0 0}
.ringwrap{position:relative; width:min(400px,100%); aspect-ratio:1/1}
canvas{width:100%; height:100%; display:block}

.lockpulse{
  position:absolute; left:50%; top:50%; width:60%; height:60%;
  border:2px solid var(--live); border-radius:50%;
  transform:translate(-50%,-50%) scale(.7); opacity:0; pointer-events:none;
}
.ringwrap.lock .lockpulse{animation:lockpulse .9s var(--ease)}
@keyframes lockpulse{
  0%{opacity:.55; transform:translate(-50%,-50%) scale(.62)}
  100%{opacity:0; transform:translate(-50%,-50%) scale(1.15)}
}

.center{position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center;
  text-align:center; pointer-events:none; padding:0 16%}
.verify{
  width:34px; height:34px; color:var(--live); margin-bottom:6px;
  opacity:0; transform:scale(.6);
  stroke-dasharray:120; stroke-dashoffset:120;
  transition:opacity .3s, transform .3s;
}
.ringwrap[data-state="match"] .verify{opacity:1; transform:scale(1); animation:drawcheck .5s var(--ease) forwards}
@keyframes drawcheck{from{stroke-dashoffset:120}to{stroke-dashoffset:0}}

.state-label{font-size:11px; font-weight:600; letter-spacing:.26em; text-transform:uppercase;
  color:var(--muted-2); margin-bottom:10px; transition:color .3s}
.ringwrap[data-state="match"] .state-label{color:var(--brand)}
.name{font-weight:800; font-size:clamp(26px,5vw,46px); line-height:1.02; letter-spacing:-.03em;
  color:var(--ink); transition:color .35s; max-width:100%; overflow-wrap:anywhere}
.name.match{color:var(--brand); animation:pop .45s var(--ease)}
.name.unknown{color:var(--muted)}
@keyframes pop{0%{transform:scale(.92)}55%{transform:scale(1.04)}100%{transform:scale(1)}}
.conf{font-size:13px; color:var(--muted); margin-top:12px; min-height:18px; font-weight:500}
.conf b{color:var(--ink); font-weight:700}

/* ---- controls (under the hero) ---- */
.controls{width:100%; max-width:420px; margin:30px auto 0; display:flex; gap:18px; align-items:center}
.thr{flex:1; display:flex; align-items:center; gap:12px; font-size:12px; color:var(--muted); font-weight:500}
.thr-label{white-space:nowrap; letter-spacing:.04em}
.thr-val{color:var(--ink); min-width:34px; font-weight:600}
.startcol{width:200px}
@media (max-width:540px){ .controls{flex-direction:column-reverse; align-items:stretch} .startcol{width:100%} }

input[type=range]{
  flex:1; -webkit-appearance:none; appearance:none; height:6px; border-radius:6px;
  background:var(--paper-2); outline:none; cursor:pointer;
}
input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none; width:18px; height:18px; border-radius:50%;
  background:var(--brand); border:3px solid #fff; box-shadow:0 1px 4px rgba(32,84,61,.4); transition:transform .12s}
input[type=range]::-webkit-slider-thumb:hover{transform:scale(1.12)}
input[type=range]::-moz-range-thumb{width:16px; height:16px; border-radius:50%;
  background:var(--brand); border:3px solid #fff; box-shadow:0 1px 4px rgba(32,84,61,.4)}
input[type=range]:focus-visible{box-shadow:0 0 0 4px rgba(32,84,61,.14)}

/* ===================== results (right): match scores + hint ===================== */
.scores .eyebrow{margin-bottom:14px}
.srow{display:grid; grid-template-columns:minmax(64px,96px) 1fr 42px; align-items:center; gap:12px; margin-bottom:12px}
.srow:last-child{margin-bottom:0}
.srow .sn{font-size:13.5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.bar{height:8px; background:var(--paper-2); border-radius:6px; overflow:hidden}
.bar i{display:block; height:100%; width:0%; border-radius:6px;
  background:var(--muted-2); transition:width .3s var(--ease), background .3s}
.srow .sv{font-size:12.5px; color:var(--muted); text-align:right; font-variant-numeric:tabular-nums; font-weight:500}
.srow.best .sv{color:var(--brand); font-weight:700}
.srow.best .bar i{background:linear-gradient(90deg, var(--live), var(--brand)); box-shadow:0 0 10px rgba(47,158,106,.35)}

.hint{font-size:12px; color:var(--muted-2); margin-top:18px; padding-top:16px;
  border-top:1px solid var(--line); line-height:1.6}

/* ===================== footer ===================== */
footer{border-top:1px solid var(--line); padding:14px 2px; margin-top:auto}
.log{font-size:12px; color:var(--muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.log b{color:var(--ink); font-weight:600}

/* ===================== toasts ===================== */
.toast-host{position:fixed; right:20px; bottom:20px; display:flex; flex-direction:column; gap:10px; z-index:50}
.toast{
  font-size:13px; color:var(--ink); background:#fff;
  border:1px solid var(--line); border-left:3px solid var(--brand);
  border-radius:var(--r-sm); padding:12px 16px; max-width:330px; box-shadow:var(--shadow-md);
  animation:toastin .3s var(--ease);
}
.toast.err{border-left-color:var(--bad)}
.toast.fade{animation:toastout .32s ease forwards}
@keyframes toastin{from{opacity:0; transform:translateX(24px) scale(.98)}to{opacity:1; transform:none}}
@keyframes toastout{to{opacity:0; transform:translateX(24px)}}

/* ===================== access gate ===================== */
/* Full-screen lock shown on every load until the backend validates the code.
   Opaque (same paper-white field as the app) so nothing behind it shows. */
.gate{
  position:fixed; inset:0; z-index:100;
  display:flex; align-items:center; justify-content:center; padding:24px;
  background:
    radial-gradient(1100px 560px at 88% -10%, rgba(32,84,61,.05), transparent 60%),
    radial-gradient(820px 460px at -5% 108%, rgba(32,84,61,.04), transparent 55%),
    var(--bg);
  animation:gatein .5s var(--ease);
}
.gate.hidden{
  opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity .45s var(--ease), visibility 0s .45s;
}
@keyframes gatein{from{opacity:0}to{opacity:1}}

.gate-card{
  width:min(420px,100%); background:var(--paper); border:1px solid var(--line);
  border-radius:var(--r); box-shadow:var(--shadow-md); padding:40px 34px 30px;
  text-align:center; animation:rise .6s var(--ease);
}
.gate-brand{display:inline-flex; align-items:center; gap:10px; margin-bottom:22px; cursor:default}
.gate-brand .wordmark{height:30px}
.gate-title{font-size:21px; font-weight:700; letter-spacing:-.02em; margin:0 0 8px; color:var(--ink)}
.gate-sub{font-size:13.5px; color:var(--muted); margin:0 auto 24px; max-width:32ch; line-height:1.55}
.gate-form{display:flex; flex-direction:column; gap:12px}
.gate-input{
  width:100%; background:#fff; border:1px solid var(--line-2); color:var(--ink);
  padding:13px 15px; border-radius:var(--r-sm); font-family:inherit; font-size:15px;
  text-align:center; letter-spacing:.06em; outline:none;
  transition:border-color .2s, box-shadow .2s;
}
.gate-input::placeholder{color:var(--muted-2); letter-spacing:.01em}
.gate-input:focus{border-color:var(--brand); box-shadow:0 0 0 4px rgba(32,84,61,.1)}
.gate-btn{margin-top:2px}
.gate-err{min-height:18px; margin-top:14px; font-size:12.5px; font-weight:600; color:var(--bad)}
.gate.shake .gate-card{animation:shake .42s var(--ease)}
@keyframes shake{
  10%,90%{transform:translateX(-2px)} 30%,70%{transform:translateX(5px)} 50%{transform:translateX(-8px)}
}

/* ===================== load orchestration ===================== */
/* Gated on html.js (set synchronously in <head>) so the page is never hidden
   if scripts are disabled or the module fails to load. */
.js header, .js .rail, .js .stage, .js .results, .js footer{opacity:0}
.js header{animation:rise .6s var(--ease) forwards}
.js .rail{animation:rise .6s var(--ease) .08s forwards}
.js .stage{animation:rise .7s var(--ease) .14s forwards}
.js .results{animation:rise .7s var(--ease) .2s forwards}
.js footer{animation:rise .6s var(--ease) .26s forwards}
@keyframes rise{from{opacity:0; transform:translateY(14px)}to{opacity:1; transform:none}}

/* ===================== a11y ===================== */
a{color:var(--brand)}
:focus-visible{outline:2px solid var(--brand); outline-offset:2px; border-radius:4px}
.btn:focus-visible, .recbtn:focus-visible{outline-offset:3px}

@media (prefers-reduced-motion: reduce){
  *{animation:none !important; transition:none !important; scroll-behavior:auto}
  .js header, .js .rail, .js .stage, .js .results, .js footer{opacity:1 !important}
  .verify{stroke-dashoffset:0}
}
