/*
 * Neuron Drift "Signal" palette and type, copied from neurondrift-web
 * (app/assets/css/main.css). Dark first; light follows the system setting.
 * Lime (signal) is a fill only; accent-coloured text uses mark.
 *
 * Shared by every prototype: served from /_kit/style.css (synced, do not edit
 * the copy). Prototype-specific rules go in the prototype's own style.css,
 * loaded after this one.
 */
@font-face {
  font-family: "Unbounded";
  font-style: normal;
  font-display: swap;
  font-weight: 200 900;
  src: url(fonts/unbounded-latin-wght-normal.woff2) format("woff2");
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-display: swap;
  font-weight: 400 700;
  src: url(fonts/instrument-sans-latin-wght-normal.woff2) format("woff2");
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-display: swap;
  font-weight: 100 800;
  src: url(fonts/jetbrains-mono-latin-wght-normal.woff2) format("woff2");
}

:root {
  color-scheme: dark;
  --nd-ground: #111210;
  --nd-surface: #1c1d1a;
  --nd-line: #2e2f2b;
  --nd-ink: #eeeee8;
  --nd-muted: #a2a49c;
  --nd-mark: #c8f25a;
  /* Fills: same in both schemes, always with signal-ink text. */
  --nd-signal: #c8f25a;
  --nd-signal-ink: #111210;
  --nd-error: #e5484d;

  --font-display: "Unbounded", sans-serif;
  --font-sans: "Instrument Sans", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, monospace;
  --radius-card: 6px;
  --radius-control: 4px;
}
@media (prefers-color-scheme: light) {
  :root {
    color-scheme: light;
    --nd-ground: #f3f3ef;
    --nd-surface: #e6e7e0;
    --nd-line: #d4d5cd;
    --nd-ink: #131412;
    --nd-muted: #55574f;
    --nd-mark: #4f6b00;
  }
}

* { box-sizing: border-box; }
/* The hidden attribute must win over the display rules below (form is a grid). */
[hidden] { display: none !important; }

html { background: var(--nd-ground); -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--nd-ground);
  color: var(--nd-ink);
  font: 17px/1.55 var(--font-sans);
  -webkit-font-smoothing: antialiased;
}
::selection { background: var(--nd-signal); color: var(--nd-signal-ink); }
:focus-visible { outline: 2px solid var(--nd-mark); outline-offset: 2px; }
a { color: inherit; }

.shell { max-width: 1200px; margin: 0 auto; padding: 0 20px; min-height: 100dvh; display: flex; flex-direction: column; }
main { flex: 1; display: flex; flex-direction: column; }

/*
 * Gate or app, never both. gate.js sets html.unlocked before first paint when
 * a passcode is stored; app.js keeps it in step. Without it, the gate shows.
 */
html:not(.unlocked) #app, html.unlocked #gate { display: none; }

/* Header, as on neurondrift.co.uk: wordmark left, hairline underneath. */
.topbar { height: 64px; display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid var(--nd-line); }
.wordmark { font-family: var(--font-display); font-weight: 500; letter-spacing: -0.03em; white-space: nowrap; font-size: 18px; }
.wordmark .dot { color: var(--nd-mark); }
.tag, .eyebrow { font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--nd-muted); }
.tag { border: 1px solid var(--nd-line); border-radius: var(--radius-control); padding: 4px 8px; }

.intro { display: flex; flex-direction: column; gap: 12px; padding: 28px 0 24px; }
.eyebrow { margin: 0; }
h1 { font-family: var(--font-display); font-weight: 500; font-size: 32px; line-height: 1.08; letter-spacing: -0.04em; margin: 0; }
.lede { margin: 0; color: var(--nd-muted); max-width: 620px; }
h2 { font-family: var(--font-display); font-weight: 500; font-size: 20px; line-height: 1.2; letter-spacing: -0.03em; margin: 0 0 16px; }
h3 { font-size: 15px; font-weight: 600; margin: 0 0 8px; }

/* Passcode screen: one centred step, nothing else on the page. */
.gate { flex: 1; display: grid; place-items: center; padding: 40px 0; }
.gate-inner { width: 100%; max-width: 420px; display: flex; flex-direction: column; gap: 12px; }
.gate .lede { margin-bottom: 12px; }
.gate-card label { margin-top: 0; }
.gate-card button.primary { margin-top: 12px; }
.gate-error { margin: 0; color: var(--nd-error); font-size: 15px; }
.gate-error:empty { display: none; }
#passcode[aria-invalid=true] { border-color: var(--nd-error); }

/* Cards: surface fill, no border, as the site's service cards and contact form. */
.card { background: var(--nd-surface); border-radius: var(--radius-card); padding: 20px; }
.col-output { display: grid; gap: 16px; margin-top: 16px; }
.col-output > * { margin: 0; }

form { display: grid; gap: 8px; }
label { font-size: 14px; font-weight: 600; margin-top: 12px; }
.hint { font-weight: 400; color: var(--nd-muted); }
input {
  font: inherit; font-size: 16px; /* 16px stops iOS zooming on focus */
  height: 48px; padding: 0 14px; width: 100%;
  border: 1px solid var(--nd-line); border-radius: var(--radius-control);
  background: var(--nd-ground); color: var(--nd-ink);
}
input[type=file] { position: absolute; width: 1px; height: 1px; opacity: 0; }

.photo {
  display: grid; place-items: center; min-height: 176px; margin-top: 0; padding: 8px;
  border: 1px dashed var(--nd-muted); border-radius: var(--radius-card);
  background: var(--nd-ground); color: var(--nd-muted); text-align: center; font-size: 15px;
  cursor: pointer; overflow: hidden;
}
/* The file input is visually hidden, so show its keyboard focus on the drop zone. */
form:has(#photo:focus-visible) .photo { outline: 2px solid var(--nd-mark); outline-offset: 2px; }
.photo img { max-width: 100%; max-height: 256px; border-radius: var(--radius-control); }

/*
 * Drop and paste. Phones keep the camera wording; only a device with hover and
 * a fine pointer (a desktop) is told it can drop or paste a file.
 */
.photo { position: relative; transition: border-color .15s, background-color .15s; }
.wording-desktop { display: none; }
@media (hover: hover) and (pointer: fine) {
  .wording-camera { display: none; }
  .wording-desktop { display: inline; }
}
/* app.js sets .dragging while a file is dragged over the window. */
.drop-cue {
  display: none; position: absolute; inset: 0; place-items: center; padding: 8px;
  background: color-mix(in srgb, var(--nd-signal) 14%, var(--nd-ground));
  color: var(--nd-mark); font-weight: 600; font-size: 17px;
}
/* Solid accent border, thickened with a shadow so the layout does not shift. */
.photo.dragging { border-style: solid; border-color: var(--nd-signal); box-shadow: inset 0 0 0 1px var(--nd-signal); }
.photo.dragging .drop-cue { display: grid; }
.cue-replace { display: none; }

/*
 * Filled: once a photo is set the dashed drop target becomes a solid frame,
 * the image fills its width at a fixed height and a caption bar sits under it.
 * object-fit: contain, not cover: samples are often tall stems or wide
 * garlands, and cropping would hide the very part staff are checking (the
 * model sees the whole photo). The spare space is a quiet tint, not black bars.
 */
.photo-box { border-radius: var(--radius-card); }
.photo-box.filled {
  border: 1px solid var(--nd-line); background: var(--nd-ground);
  overflow: hidden; transition: border-color .15s;
}
.photo-box.filled .photo {
  display: block; height: 220px; min-height: 0; padding: 0;
  border: 0; border-radius: 0;
  background: color-mix(in srgb, var(--nd-line) 45%, var(--nd-ground));
}
.photo-box.filled .photo img {
  display: block; width: 100%; height: 100%; max-width: none; max-height: none;
  object-fit: contain; border-radius: 0;
  animation: photo-in .2s ease-out;
}
.photo-box.filled .cue-empty { display: none; }
.photo-box.filled .cue-replace { display: inline; }
.photo-box.filled .drop-cue { background: color-mix(in srgb, color-mix(in srgb, var(--nd-signal) 14%, var(--nd-ground)) 90%, transparent); }
.photo-box.filled:has(.dragging) { border-color: var(--nd-signal); }
.photo-box.filled .photo.dragging { box-shadow: inset 0 0 0 1px var(--nd-signal); }
/* Focus shows on the whole frame once filled (overflow would clip the label's). */
form:has(#photo:focus-visible) .photo-box.filled .photo { outline: 0; }
form:has(#photo:focus-visible) .photo-box.filled { outline: 2px solid var(--nd-mark); outline-offset: 2px; }
@keyframes photo-in { from { opacity: 0; } to { opacity: 1; } }

.photo-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0 10px;
  padding: 2px 4px 2px 12px; border-top: 1px solid var(--nd-line);
}
.photo-check { flex: none; fill: var(--nd-signal); stroke: var(--nd-signal-ink); }
.photo-meta { flex: 1 1 9rem; min-width: 0; display: flex; flex-direction: column; padding: 6px 0; line-height: 1.3; }
.photo-name { font-size: 15px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.photo-size { font-family: var(--font-mono); font-size: 12px; color: var(--nd-muted); }
.photo-size:empty { display: none; }
.photo-actions { flex: none; display: flex; margin-left: auto; }
/* Text actions with full-size tap targets. */
button.photo-action {
  min-height: 44px; min-width: 44px; padding: 0 12px;
  border: 0; background: none; color: var(--nd-mark);
  font-size: 15px; font-weight: 600; text-underline-offset: 3px;
}
button.photo-action:hover { opacity: 1; text-decoration: underline; }
button.photo-action-quiet { color: var(--nd-muted); }
button.photo-action-quiet:hover { color: var(--nd-ink); }

@media (prefers-reduced-motion: reduce) {
  .photo, .photo-box.filled { transition: none; }
  .photo-box.filled .photo img { animation: none; }
}

/* The note is the photo's live region. Errors show; success lines are only
   announced, because the caption bar already says the same thing. */
.photo-note { margin: 0; font-size: 14px; color: var(--nd-muted); }
/* Never display: none, so the live region stays in the accessibility tree. */
.photo-note:not(.error) {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
.photo-note.error { color: var(--nd-error); }

button {
  font: inherit; font-size: 16px; min-height: 48px; padding: 0 24px; cursor: pointer;
  border: 1px solid var(--nd-line); border-radius: var(--radius-control);
  background: var(--nd-ground); color: var(--nd-ink); transition: opacity .15s;
}
button:hover { opacity: .85; }
button:disabled { opacity: .6; cursor: progress; }
button.primary { margin-top: 20px; border-color: var(--nd-signal); background: var(--nd-signal); color: var(--nd-signal-ink); font-weight: 600; }

.placeholder {
  color: var(--nd-muted); text-align: center; padding: 40px 16px;
  border: 1px dashed var(--nd-line); border-radius: var(--radius-card);
}
#status:empty { display: none; }
#status { color: var(--nd-muted); }
#status.error { color: var(--nd-error); }

.footer { margin-top: 64px; padding: 32px 0; border-top: 1px solid var(--nd-line); display: flex; flex-direction: column; gap: 16px; font-size: 14px; }
html:not(.unlocked) .footer { margin-top: 0; }
.footer-brand { display: inline-flex; flex-direction: column; gap: 6px; text-decoration: none; color: var(--nd-muted); align-self: flex-start; }
.footer-brand .wordmark { color: var(--nd-ink); font-size: 18px; }
.footer-brand:hover span:last-child { color: var(--nd-ink); text-decoration: underline; text-underline-offset: 2px; }
.credit { margin: 0; color: var(--nd-muted); font-size: 12px; line-height: 1.5; }
.credits { display: flex; flex-direction: column; gap: 4px; }
.credit a { text-underline-offset: 2px; }
.credit a:hover { color: var(--nd-ink); }

@media (min-width: 48rem) {
  .shell { padding: 0 32px; }
  .topbar { height: 88px; }
  .wordmark { font-size: 22px; }
  .intro { padding: 56px 0 40px; gap: 16px; }
  .gate { padding: 64px 0; }
  .gate-inner { gap: 16px; }
  h1 { font-size: 52px; }
  .lede { font-size: 20px; }
  .card { padding: 32px; }
  .footer { flex-direction: row; justify-content: space-between; align-items: flex-end; padding-bottom: 48px; }
  .credits { text-align: right; max-width: 22rem; }
}

/* Desktop: inputs left, results right, so a demo shows the whole flow on one screen. */
@media (min-width: 60rem) {
  .layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 24px; align-items: start; }
  .col-output { position: sticky; top: 24px; margin-top: 0; }
  .photo { min-height: 160px; }
  .photo img { max-height: 28vh; }
  .photo-box.filled .photo { height: 260px; }
}
