/* Shared design system for all three views.
   Dark by default: these run in dimmed venues, and a bright screen behind a stage is hostile. */

:root {
  --bg:        #0b0d12;
  --bg-raised: #141822;
  --bg-sunken: #080a0e;
  --line:      #232936;
  --line-soft: #1a1f29;

  --fg:        #eef1f6;
  --fg-muted:  #98a2b3;
  --fg-faint:  #5f6878;

  --accent:      #d4a04a;   /* warm gold — reads well on a projector */
  --accent-soft: #3a2e18;
  --teal:        #3fb6a8;
  --danger:      #e3564a;
  --ok:          #4caf7d;

  --radius: 10px;
  --radius-lg: 16px;
  --gap: 12px;

  --font-latin: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  /* Arabic needs its own stack; the Latin defaults render Arabic poorly or not at all. */
  --font-ar: "SF Arabic", "Geeza Pro", "Noto Naskh Arabic", "Segoe UI", Tahoma, sans-serif;
  --font: var(--font-latin);

  --shadow: 0 8px 30px rgba(0, 0, 0, 0.45);
}

/* ── interface language (web/shared/i18n.js) ────────────────────────────────
   Arabic is the default interface. Direction comes from <html dir>, so every flex row,
   text-align: start and logical property (margin-inline-start, inset-inline-end…)
   mirrors on its own. Use logical properties in view stylesheets; a physical
   left/right is a bug in RTL unless it is deliberately direction-independent. */

html[lang="ar"] { --font: var(--font-ar); }

/* Letter-spacing pulls apart the joined letters of Arabic script, and uppercase
   tracking has no Arabic meaning, so neither applies to an Arabic interface. Latin
   runs inside it (.en) keep their tracking. */
html[lang="ar"] :not(.en, .en *) { letter-spacing: normal !important; }

/* Arabic at the same pixel size reads noticeably smaller than Latin; the small UI
   sizes get a lift so a 11px chip does not become illegible. */
html[lang="ar"] .small { font-size: 14px; }
html[lang="ar"] .tiny  { font-size: 12px; }
html[lang="ar"] .chip  { font-size: 12px; }

/* lang-boot.js holds an English page invisible until its strings are swapped in, so an
   English reader never sees the Arabic first frame. It clears itself on a timeout. */
html.i18n-pending body { visibility: hidden; }

/* The language switch. Its label is always the *other* language in its own script. */
.lang-toggle {
  flex: none;
  min-height: 32px;
  padding: 6px 12px;
  border-radius: 999px;
  font-size: 13px; font-weight: 600;
  background: transparent; border: 1px solid var(--line); color: var(--fg-muted);
}
.lang-toggle:lang(ar) { font-family: var(--font-ar); }
.lang-toggle:lang(en) { font-family: var(--font-latin); }
.lang-toggle:hover:not(:disabled) { color: var(--fg); }

/* Media transport, timecodes, BPM and key readouts are direction-neutral data: they
   keep their LTR reading order inside an RTL page. Wrap them in .ltr (or dir="ltr"). */
.ltr { direction: ltr; unicode-bidi: isolate; }

* { box-sizing: border-box; }

/* The `hidden` attribute must beat any later `display` rule. Without this, a component
   styled `display: flex` stays on screen while JS believes it has hidden it — which is
   exactly how the signup view ended up showing its sign-up form and its signed-in form
   at the same time. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
}

/* Arabic text always gets its own element with dir=rtl — never inlined raw into an
   English sentence, where the bidi algorithm reorders punctuation unpredictably. */
.ar {
  font-family: var(--font-ar);
  direction: rtl;
  unicode-bidi: isolate;
}

.en { font-family: var(--font-latin); direction: ltr; unicode-bidi: isolate; }

/* A .en/.ar block carries its own direction so a Latin title reads LTR on an Arabic page
   — but then `text-align: start` resolves against *that* direction and pushes a Latin
   title to the far edge of an Arabic card. match-parent aligns it with the page instead.
   Zero specificity (:where) so a view that centres or end-aligns a title still wins. */
:where(.en, .ar) { text-align: match-parent; }

h1, h2, h3 { margin: 0; font-weight: 650; letter-spacing: -0.01em; }
a { color: var(--accent); }

button, .btn {
  font: inherit;
  font-weight: 550;
  color: var(--fg);
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 9px 14px;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease, opacity 0.12s ease;
}
button:hover:not(:disabled), .btn:hover { background: #1d2330; border-color: #303849; }
button:disabled { opacity: 0.4; cursor: not-allowed; }
button.primary { background: var(--accent); border-color: var(--accent); color: #1a1204; }
button.primary:hover:not(:disabled) { background: #e0ae58; border-color: #e0ae58; }
button.ghost { background: transparent; }
button.danger { color: var(--danger); border-color: #40282a; }
button.icon { padding: 7px 10px; line-height: 1; }

input, select, textarea {
  font: inherit;
  color: var(--fg);
  background: var(--bg-sunken);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 9px 12px;
  width: 100%;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(212, 160, 74, 0.14);
}
label { display: block; font-size: 13px; color: var(--fg-muted); margin-bottom: 6px; }

.card {
  background: var(--bg-raised);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-lg);
  padding: 16px;
}

.row { display: flex; align-items: center; gap: var(--gap); }
.col { display: flex; flex-direction: column; gap: var(--gap); }
.spacer { flex: 1; }
.muted { color: var(--fg-muted); }
.faint { color: var(--fg-faint); }
.small { font-size: 13px; }
.tiny  { font-size: 11px; }
.mono  { font-variant-numeric: tabular-nums; }
/* Same effect as .mono, named for the intent: a counter that must not jitter as it ticks. */
.tabular { font-variant-numeric: tabular-nums; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Advisory, not fatal — the gold reads as "read this", the danger red is kept for failures. */
.warn { color: var(--accent); }

/* Minimum comfortable touch target. signup.css raises this to its own --tap for phones. */
.tap { min-height: 44px; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* Metadata chips. `.guess` marks Tier C fields (maqam / iqa' / style) whose confidence
   is low — the contract requires these never look like established fact. */
.chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; font-weight: 600; letter-spacing: 0.02em;
  padding: 3px 8px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent);
  border: 1px solid transparent;
  white-space: nowrap;
}
.chip.neutral { background: #1b2130; color: var(--fg-muted); }
.chip.guess {
  background: transparent;
  color: var(--fg-faint);
  border: 1px dashed var(--line);
}
.chip.guess::after { content: "?"; opacity: 0.7; }
html[lang="ar"] .chip.guess::after { content: "؟"; }

.badge {
  display: inline-block; min-width: 20px; text-align: center;
  background: var(--danger); color: #fff;
  font-size: 11px; font-weight: 700;
  padding: 2px 6px; border-radius: 999px;
}

.empty {
  padding: 32px 16px;
  text-align: center;
  color: var(--fg-faint);
  font-size: 14px;
}

.scroll { overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
.scroll::-webkit-scrollbar { width: 8px; }
.scroll::-webkit-scrollbar-thumb { background: var(--line); border-radius: 4px; }

.toast-host {
  position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%);
  display: flex; flex-direction: column; gap: 8px; z-index: 100; align-items: center;
}
.toast {
  background: var(--bg-raised); border: 1px solid var(--line);
  box-shadow: var(--shadow);
  padding: 10px 16px; border-radius: var(--radius);
  font-size: 14px; animation: toast-in 0.18s ease;
}
.toast.err { border-color: var(--danger); color: #ffb4ae; }
.toast.ok  { border-color: var(--ok); }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } }

/* ── capture panel (web/shared/capture.js) ──────────────────────────────────
   One stylesheet for both mounts: the DJ console gets the roomy layout, the guest phone
   gets `.compact`, where every control has to clear the 44px touch minimum. The module
   builds its own DOM, so these class names are the contract between it and this file.
   Direction: everything here is flex/grid with logical alignment, so the panel mirrors
   in an Arabic page on its own. The exceptions are data, not prose — the timecode, the
   level meter, the camera preview and the token id keep LTR in both languages. */

.capture { display: flex; flex-direction: column; gap: var(--gap); min-width: 0; }

/* Recording is a state the operator must never be in by accident. The whole panel is
   tinted and outlined, not just the button, so it reads from across a dark booth. */
.capture.is-recording {
  outline: 1px solid var(--danger);
  outline-offset: 6px;
  border-radius: var(--radius);
}

.capture-modes { gap: 8px; flex-wrap: wrap; }

.chip-btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 32px; padding: 6px 14px;
  border-radius: 999px;
  font-size: 12px; font-weight: 600; letter-spacing: 0.02em;
  background: transparent; border: 1px solid var(--line); color: var(--fg-muted);
}
.chip-btn:hover:not(:disabled) { background: #1d2330; border-color: #303849; }
.chip-btn.is-on {
  background: var(--accent-soft); border-color: var(--accent); color: var(--accent);
}

.capture-row { display: flex; align-items: center; gap: 10px; min-width: 0; flex-wrap: wrap; }
/* Labels in a row are inline captions, not form-field headings. */
.capture-row label { margin: 0; flex: none; }

.capture-device-row { gap: 8px; }
.capture-device { flex: 1 1 160px; min-width: 0; padding: 7px 10px; font-size: 13px; }
/* Shown only while device labels are still hidden behind the permission prompt. */
.capture-enable { flex: none; white-space: nowrap; }
.capture-device[disabled] { opacity: 0.6; cursor: not-allowed; }
.capture-device-note { margin: -2px 0 0; line-height: 1.4; }

.capture-record { flex: none; }
.capture-record.is-recording {
  background: var(--danger); border-color: var(--danger); color: #fff;
  animation: capture-throb 1.1s ease-in-out infinite;
}
@keyframes capture-throb { 50% { box-shadow: 0 0 0 6px rgba(227, 86, 74, 0.22); } }

.capture-clock {
  flex: none; min-width: 5ch;
  direction: ltr; unicode-bidi: isolate;
  font-size: 15px; font-weight: 650; color: var(--fg-muted);
}
.capture.is-recording .capture-clock { color: var(--fg); }

/* Level meter. A take with no visible level is how you learn afterwards that the line
   input was muted all night — so it is always on screen, even at rest. It is a
   visualiser, so it fills left to right in both languages, like every DJ tool's meter. */
.capture-level {
  display: block; flex: 1 1 90px; min-width: 70px; height: 8px;
  direction: ltr;
  background: var(--bg-sunken); border: 1px solid var(--line);
  border-radius: 999px; overflow: hidden;
}
.capture-level-bar {
  display: block; width: 0; height: 100%;
  background: var(--teal); border-radius: 999px;
  transition: width 0.08s linear;
}
.capture-level-bar.is-hot { background: var(--danger); }

.capture-preview {
  direction: ltr;                          /* media stays LTR (web/shared/base.css header) */
  width: 100%; max-height: 260px;
  background: var(--bg-sunken); border: 1px solid var(--line);
  border-radius: var(--radius); object-fit: cover;
}

.capture-file-row { gap: 10px; }
/* The <input type=file> is .sr-only, so its own label has to carry the button styling
   that `button.ghost` would otherwise give it — and the focus ring the input can't show. */
.capture-file-label {
  display: inline-flex; align-items: center; justify-content: center;
  margin: 0; padding: 9px 14px;
  font: inherit; font-weight: 550; color: var(--fg);
  background: transparent; border: 1px solid var(--line);
  border-radius: var(--radius); cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.capture-file-label:hover { background: #1d2330; border-color: #303849; }
.capture-file-row input:focus-visible + .capture-file-label {
  outline: 2px solid var(--accent); outline-offset: 2px;
}

.capture-status { margin: 0; line-height: 1.45; }
.capture-status:empty { display: none; }

/* Shown instead of the recorder when getUserMedia cannot work here (plain http on the
   venue LAN). It explains itself, so give it the room to be read. */
.capture-blocked {
  margin: 0;
  padding: 10px 12px; line-height: 1.5;
  background: var(--accent-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.capture-result {
  display: flex; flex-direction: column; gap: 10px;
  padding: 12px;
  background: var(--bg-sunken);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
}
.capture-result-head { align-items: flex-start; gap: 12px; }
/* .col's default gap is page-level spacing; these are three stacked lines of one block. */
.capture-result-head .col { gap: 3px; min-width: 0; }

.capture-thumb {
  flex: none; width: 48px; height: 48px;
  border-radius: var(--radius); border: 1px solid var(--line);
  background: var(--bg); object-fit: cover;
}
/* The name is guest text of either script (dir="auto"); align it with the page, not with
   its own direction, the same way base.css treats .en/.ar blocks. */
.capture-result-name { font-size: 14px; font-weight: 650; overflow-wrap: anywhere; text-align: match-parent; }
.capture-token-id {
  font-variant-numeric: tabular-nums;
  direction: ltr; unicode-bidi: isolate;
  color: var(--fg-muted);
  background: var(--bg); border: 1px solid var(--line-soft);
  border-radius: 6px; padding: 2px 6px;
  align-self: flex-start;
}
.capture-result-links { gap: 14px; flex-wrap: wrap; }

/* ── compact (guest phone) ───────────────────────────────────────────────── */

.capture.compact .chip-btn { min-height: 44px; padding: 10px 18px; font-size: 13px; }
.capture.compact .capture-device { flex-basis: 100%; padding: 12px 14px; font-size: 16px; }
.capture.compact .capture-enable { width: 100%; min-height: 44px; }
/* Record gets the full width; the clock and meter share the line below it. */
.capture.compact .capture-record { flex: 1 1 100%; }
.capture.compact .capture-file-label { width: 100%; min-height: 44px; }
.capture.compact .capture-preview { max-height: 42vh; }

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