/* Adam V1. Tokens taken verbatim from the Clovermind site stylesheet: Geist +
   Geist Mono, monochrome, colour only where it carries information. The one
   place colour is allowed here is the verdict state and the threshold line on
   the bars, because both are the readout saying something and a monochrome
   version of them would be less legible rather than more restrained.

   Geist loads from the font CDN. Offline, the system stack takes over and the
   layout does not move, which is the reason for the fallbacks rather than a
   nicety: this is an installable offline app and the fonts are the one thing
   in it that is not self-contained. */

:root {
  --bg: #0a0a0b;
  --panel: #101013;
  --ink: #ededf0;
  --dim: #85858e;
  --faint: #4a4a52;
  --line: rgba(237, 237, 240, 0.12);
  --line-strong: rgba(237, 237, 240, 0.25);
  --accent: #5e5ce6;
  --live: #7d87e6;
  --warn: #c98a5e;
  --sans: "Geist", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --bar-h: 54px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { height: 100%; }
html {
  /* iOS Safari inflates text inside blocks it judges wide, independently of the
     viewport meta tag. Desktop browsers do not, which is why the top bar looked
     correct in every emulator and broke on a real phone: the button labels came
     out larger than they were authored and pushed themselves onto three lines.
     This turns the autosizing off and makes a phone render the sizes as
     written. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
}
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

.mono-label {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--dim);
}

/* ---------- top bar ---------- */
.bar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 40;
  height: calc(var(--bar-h) + env(safe-area-inset-top));
  padding: env(safe-area-inset-top) 16px 0 16px;
  display: flex; align-items: center; justify-content: space-between;
  background: rgba(10, 10, 11, 0.86);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}
/* The bar is a fixed height, so nothing inside it may wrap.

   On a phone it did, and the result was ugly and confusing: "WHAT THIS IS"
   broke onto three lines, which made the buttons taller than the 54px bar, so
   they hung through its bottom border and over the camera panel. "Adam V1"
   was wrapping too, for the same reason: the long arm label ("TRAINED M1, 5000
   DIGITS") was demanding its full width and squeezing everything either side of
   it.

   Three rules fix it and they have to work together. The buttons never wrap and
   never shrink. The arm label is allowed to shrink to nothing and truncate,
   because it is the one item here that can lose its tail and still read. And
   the title never wraps. */
.bar-left {
  display: flex; align-items: baseline; gap: 12px;
  flex: 1 1 auto; min-width: 0;      /* min-width:0 is what lets .arm truncate */
}
.mark {
  font-size: 16px; font-weight: 500; letter-spacing: -0.01em;
  white-space: nowrap; flex: none;
}
.arm {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bar-right { display: flex; gap: 14px; flex: none; align-items: center; }

/* THE HEIGHT IS PINNED, and that is the actual fix rather than a refinement.

   Sizing a control by its padding means its height is a function of its text,
   so anything that makes the text bigger or wrap makes the button taller, and
   in a fixed-height bar a taller button escapes through the top and bottom
   edges. That is what happened on a phone. A fixed height cannot do that:
   whatever the text does, the control is 28px and stays inside the bar. */
.ctl {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 0.1em;
  text-transform: uppercase; white-space: nowrap;
  height: 28px; flex: none; position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  transition: color 150ms, border-color 150ms, background 150ms, opacity 150ms;
}
/* The control is 28px tall because that is what fits the bar, and 28px is well
   under the 44px a finger wants. This extends the HIT AREA to 44px without
   extending the control, so the target is comfortable while the bar stays the
   size it has to be. Horizontal reach is kept under half the gap between the
   two controls so their targets cannot overlap. */
.ctl::before {
  content: ""; position: absolute; inset: -9px -5px;
}

/* The pill is for the toggle, which needs an off state and an on state and so
   needs an outline to fill. */
.ctl-pill {
  color: var(--dim);
  border: 1px solid var(--line); border-radius: 99px;
  padding: 0 13px;
}
.ctl-pill:hover { color: var(--ink); border-color: var(--line-strong); }
.ctl-pill[aria-pressed="true"] {
  color: var(--bg); background: var(--warn); border-color: var(--warn);
}

/* "What this is" is not a toggle, it opens a panel, so it does not need an
   outline to hold a state. Without one it is lighter on the bar and it can be
   brighter and heavier without shouting, which is the right weighting: it is
   the thing a first-time visitor should reach for. */
.ctl-plain {
  color: var(--ink); font-weight: 500; padding: 0;
  border: 0; border-radius: 0;
}
.ctl-plain:hover { opacity: 0.7; }

/* ---------- layout ---------- */
.stage {
  padding: calc(var(--bar-h) + env(safe-area-inset-top) + 14px) 14px
           calc(20px + env(safe-area-inset-bottom));
  max-width: 560px; margin: 0 auto;
  display: flex; flex-direction: column; gap: 14px;
}
.panel {
  background: var(--panel);
  border: 1px solid var(--line);
  padding: 12px;
}
.panel-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; margin-bottom: 10px;
}
.row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }

/* ---------- 1. camera ---------- */
.cam-wrap {
  position: relative; width: 100%; aspect-ratio: 3 / 4;
  background: #0d0d10; overflow: hidden;
}
/* contain, not cover. Cover would crop the camera frame for display while the
   network still received all of it, so the app could lock onto something the
   user cannot see and box it off-screen. The panel is titled "the live frame
   with the detected crop boxed" and it has to be the whole frame for that to be
   true. On a phone held portrait the video is close to 3:4 already, so the
   letterbox is thin where it matters. */
.cam-wrap video, .overlay {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain;
}
.overlay { pointer-events: none; }
.start {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  border: 1px solid var(--line-strong); border-radius: 99px;
  padding: 12px 26px; font-size: 14px; background: rgba(10, 10, 11, 0.55);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
}
.start[hidden] { display: none; }

.verdict {
  position: absolute; left: 12px; bottom: 12px; right: 12px;
  display: flex; align-items: center; gap: 12px;
  padding: 10px 14px; border: 1px solid var(--line);
  background: rgba(10, 10, 11, 0.6);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  transition: border-color 200ms;
}
.verdict-glyph {
  font-size: 34px; font-weight: 600; line-height: 1; min-width: 26px;
  letter-spacing: -0.03em; font-variant-numeric: tabular-nums;
}
.verdict-note { color: var(--dim); }
.verdict[data-state="named"] { border-color: var(--live); }
.verdict[data-state="named"] .verdict-glyph { color: var(--live); }
.verdict[data-state="withheld"] .verdict-glyph { color: var(--faint); font-size: 22px; }
.verdict[data-state="control"] { border-color: var(--warn); }
.verdict[data-state="control"] .verdict-glyph { color: var(--warn); }

/* ---------- 2 and 3. the pixel views ---------- */
/* image-rendering: pixelated is load-bearing. These are 28x28 and 10x10
   canvases blown up; smoothing them would show an interpolation of the data
   rather than the data, and the whole point of the panel is to see exactly what
   the network was handed. */
.pix {
  width: 100%; height: auto; display: block;
  image-rendering: pixelated; image-rendering: crisp-edges;
  background: #000; border: 1px solid var(--line);
}

/* ---------- 4. the bars ---------- */
.bars { display: flex; flex-direction: column; gap: 5px; position: relative; }
.bar-row { display: grid; grid-template-columns: 18px 1fr 46px; align-items: center; gap: 10px; }
.bar-key {
  font-family: var(--mono); font-size: 13px; color: var(--dim);
  font-variant-numeric: tabular-nums; text-align: center;
}
.bar-track { position: relative; height: 12px; background: rgba(237, 237, 240, 0.06); }
.bar-fill { position: absolute; inset: 0 auto 0 0; width: 0; background: var(--faint); transition: width 90ms linear, background 150ms; }
.bar-row.top .bar-fill { background: var(--dim); }
.bar-row.named .bar-fill { background: var(--live); }
.bar-row.named .bar-key { color: var(--live); }
.bar-row.control.named .bar-fill { background: var(--warn); }
.bar-row.control.named .bar-key { color: var(--warn); }
.bar-val {
  font-family: var(--mono); font-size: 10.5px; color: var(--faint);
  font-variant-numeric: tabular-nums; text-align: right;
}
/* The threshold, drawn where it actually sits. A confidence gate the user
   cannot see is a claim they have to take on trust. */
.bar-mark {
  position: absolute; top: 0; bottom: 0; width: 1px;
  background: var(--line-strong); pointer-events: none;
}
.bar-mark::after {
  content: attr(data-label); position: absolute; top: -14px; left: 3px;
  font-family: var(--mono); font-size: 9px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--faint); white-space: nowrap;
}
.foot { margin-top: 12px; line-height: 1.7; text-transform: none; letter-spacing: 0.04em; }

/* ---------- about ---------- */
.about {
  position: fixed; inset: 0; z-index: 60; overflow-y: auto;
  background: var(--bg); -webkit-overflow-scrolling: touch;
}
.about[hidden] { display: none; }
.about-inner {
  max-width: 620px; margin: 0 auto;
  padding: calc(env(safe-area-inset-top) + 28px) 24px
           calc(env(safe-area-inset-bottom) + 48px);
}
.about h1 { font-size: 34px; font-weight: 500; letter-spacing: -0.02em; margin-bottom: 14px; }
.about h2 {
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--dim); font-weight: 400;
  margin: 32px 0 10px;
}
.about p { color: #b9b9c0; margin-bottom: 12px; font-size: 15.5px; }
.about .lede { color: var(--ink); font-size: 17px; }
.about .ctl { margin-top: 32px; }
/* Two lines, set in the markup as a newline rather than as a <br>, so the text
   stays text. */
.prov { white-space: pre-line; line-height: 1.9; margin-top: 44px; color: var(--faint); }
/* ---------- fatal ---------- */
.fatal {
  position: fixed; inset: 0; z-index: 80; display: flex;
  align-items: center; justify-content: center; padding: 24px;
  background: rgba(10, 10, 11, 0.96);
}
.fatal[hidden] { display: none; }
.fatal-inner { max-width: 460px; border: 1px solid var(--warn); padding: 20px; }
.fatal-inner p { margin-top: 10px; color: #b9b9c0; font-size: 15px; }

@media (min-width: 900px) {
  .stage { max-width: 1080px; display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas: "cam bars" "cam small"; align-items: start; }
  .panel-cam { grid-area: cam; }
  .panel-bars { grid-area: bars; }
  .row { grid-area: small; }
}

/* Phone widths. The two button labels are 7 and 12 characters and both have to
   sit on one line beside the title, so below 560px everything in the bar gets a
   little tighter, and below 400px the arm label goes entirely: at that width it
   would be truncated to two or three characters, which is worse than absent.
   Nothing is lost by dropping it. The Control button lights up when the control
   arm is running, and the verdict line says "untrained control" in full. */
@media (max-width: 560px) {
  .ctl { font-size: 9.5px; letter-spacing: 0.07em; height: 26px; }
  .ctl-pill { padding: 0 11px; }
  .bar-right { gap: 12px; }
  .bar-left { gap: 9px; }
  .about-inner { padding-left: 20px; padding-right: 20px; }
  .about h1 { font-size: 30px; }
}
@media (max-width: 400px) {
  .arm { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .bar-fill, .verdict, .ctl { transition: none; }
}
