/* uwuPromptr layout. Every colour here comes from a token in theme.css. */

body {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ---- update prompt bar ----
   Full width at the top of the document, quieter than the app's own header,
   tinted enough to read as a notice rather than part of the layout. */
.update-notice {
  flex: none;
  background: color-mix(in srgb, var(--brand) 12%, var(--surface-strong));
  border-bottom: 1px solid var(--surface-border);
  color: var(--ink);
  font-size: 0.875rem;
}

.update-notice-inner {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  max-width: 72rem;
  margin: 0 auto;
  padding: 0.5rem 1rem;
  /* Under the notch on a phone, where the bar is the topmost thing on screen. */
  padding-top: max(0.5rem, env(safe-area-inset-top));
}

.update-notice p { flex: 1 1 auto; min-width: 0; }
.update-notice .btn { flex: none; }

/* ---- buttons ---- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 14px;
  border-radius: 12px;
  font-size: 0.85rem;
  border: 1px solid var(--surface-border);
  background: var(--surface-strong);
  color: var(--ink);
  transition: transform 0.15s ease, background 0.15s ease;
}
.btn:hover { transform: translateY(-1px); }
.btn svg { width: 16px; height: 16px; }

.btn-primary {
  background: var(--brand-fill);
  color: var(--on-brand);
}
.btn-primary:hover { background: var(--brand-fill-strong); }

.btn-quiet {
  background: transparent;
  color: var(--muted-strong);
}

.btn-danger {
  background: color-mix(in srgb, var(--error) 14%, transparent);
  color: var(--error);
  border-color: color-mix(in srgb, var(--error) 30%, transparent);
}

/* ---- top bar ---- */
.topbar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  padding-top: max(10px, env(safe-area-inset-top));
  background: var(--surface);
  border-bottom: 1px solid var(--surface-border);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.brand {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 1rem;
  color: var(--brand-ink);
  flex: none;
}
.brand img { width: 26px; height: 26px; border-radius: 8px; }

/* The script switcher: a button that names the open script and opens the
   scripts menu. It is the widest thing in the bar because the script name
   is the one piece of text somebody needs to read at a glance. */
.script-switch {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  flex: 1 1 auto;
  padding: 8px 12px;
  border-radius: 999px;
  background: var(--brand-fill);
  color: var(--on-brand);
  border: 1px solid var(--surface-border);
  font-size: 0.9rem;
  transition: background 0.15s ease;
}
.script-switch:hover { background: var(--brand-fill-strong); }
.script-switch svg { width: 16px; height: 16px; flex: none; }
.script-switch .script-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.topbar-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
}

/* ---- stage ---- */
.stage {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
}

.viewport {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none;
  /* Scrolling is driven frame by frame; a smooth-scroll behaviour on top of
     that would fight it. */
  scroll-behavior: auto;
}
.viewport::-webkit-scrollbar { display: none; }

/* The script. Colour is the whole point of the two mode rules below: the
   brand swatch paints the background in light mode and the text in dark. */
.script-text {
  white-space: pre-wrap;
  overflow-wrap: break-word;
  text-align: center;
  /* Half a screen of room at each end, so the first and last lines can both
     reach the focus line rather than being stuck at the edges. */
  padding-top: 50vh;
  padding-bottom: 60vh;
  transform-origin: center center;
  user-select: none;
}

/* Light mode: near-black text on the chosen brand colour. */
:root[data-mode="light"] .stage { background: var(--brand); }
:root[data-mode="light"] .script-text { color: #121815; }

/* Dark mode: the chosen brand colour as the text, on near-black. */
:root[data-mode="dark"] .stage { background: #0c100e; }
:root[data-mode="dark"] .script-text { color: var(--brand); }

/* The reading guide. Two arrows at the edges rather than a line across the
   text, so it marks the eyeline without sitting on top of a word. They are
   positioned against the stage rather than the viewport: the viewport is the
   scrolling box, and an arrow anchored to it is clipped by its own overflow
   at exactly the two edges the arrows live on.
   The triangles point inward, so the border that carries the colour is the
   one away from the edge each sits on. */
.stage.show-focus::before,
.stage.show-focus::after {
  content: "";
  position: absolute;
  top: var(--focus-position, 40%);
  transform: translateY(-50%);
  width: 0;
  height: 0;
  border-top: 12px solid transparent;
  border-bottom: 12px solid transparent;
  pointer-events: none;
  z-index: 2;
  opacity: 0.55;
}
.stage.show-focus::before {
  left: 0;
  border-left: 16px solid currentColor;
}
.stage.show-focus::after {
  right: 0;
  border-right: 16px solid currentColor;
}
:root[data-mode="light"] .stage.show-focus { color: #121815; }
:root[data-mode="dark"] .stage.show-focus { color: var(--brand); }

/* ---- editor ---- */
.editor {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  background: color-mix(in srgb, var(--brand) 10%, var(--bg));
  transition: opacity 0.18s ease, visibility 0s linear 0s;
}
.editor.hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.18s ease, visibility 0s linear 0.18s;
}
.editor-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--surface-border);
}
.editor-name {
  flex: 1 1 auto;
  min-width: 0;
  padding: 8px 12px;
  border-radius: 12px;
  border: 1px solid var(--surface-border);
  background: var(--surface-strong);
  color: var(--ink);
  font-size: 0.95rem;
}
.editor-body {
  flex: 1 1 auto;
  width: 100%;
  padding: 14px;
  border: none;
  outline: none;
  resize: none;
  background: transparent;
  color: var(--ink);
  font-size: 1rem;
  line-height: 1.6;
}
.editor-body::placeholder { color: var(--muted-strong); opacity: 1; }

/* ---- transport bar ---- */
.transport {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  padding-bottom: max(10px, env(safe-area-inset-bottom));
  background: var(--surface);
  border-top: 1px solid var(--surface-border);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.play-btn {
  width: 52px;
  height: 52px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--brand-fill);
  color: var(--on-brand);
  border: 1px solid var(--surface-border);
  flex: none;
  transition: background 0.15s ease, transform 0.15s ease;
}
.play-btn:hover { background: var(--brand-fill-strong); transform: translateY(-1px); }
.play-btn svg { width: 22px; height: 22px; }

/* A named number with a minus and a plus on either side. The value is a
   button too: pressing it opens the settings modal at the slider. */
.stepper {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border-radius: 999px;
  background: var(--surface-strong);
  border: 1px solid var(--surface-border);
}
.stepper .icon-btn {
  width: 32px;
  height: 32px;
  border-radius: 999px;
  background: transparent;
  border: none;
  color: var(--muted-strong);
}
.stepper .icon-btn svg { width: 15px; height: 15px; }
.stepper-value {
  min-width: 74px;
  padding: 0 6px;
  font-size: 0.82rem;
  color: var(--ink);
  text-align: center;
  white-space: nowrap;
}
.stepper-value span { color: var(--muted-strong); }

.timer {
  margin-left: auto;
  font-size: 0.95rem;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  padding: 8px 12px;
  border-radius: 999px;
  background: var(--surface-strong);
  border: 1px solid var(--surface-border);
}
.timer.hidden { display: none; }

/* ---- chrome hiding while playing ----
   Fullscreen or not, the bars fade out of the way once the script is
   moving, and come back the moment somebody moves the pointer. */
body.chrome-hidden .topbar {
  opacity: 0;
  transform: translateY(-100%);
  pointer-events: none;
}
body.chrome-hidden .transport {
  opacity: 0;
  transform: translateY(100%);
  pointer-events: none;
}

/* ---- scripts menu ---- */
.script-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 46vh;
  overflow-y: auto;
}
.script-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border-radius: 14px;
  background: var(--surface);
  border: 1px solid var(--surface-border);
  text-align: left;
  transition: background 0.15s ease;
}
.script-row:hover { background: var(--surface-strong); }
.script-row.active {
  background: var(--brand-fill);
  color: var(--on-brand);
}
.script-row .row-main { flex: 1 1 auto; min-width: 0; }
.script-row .row-title {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.92rem;
}
.script-row .row-meta {
  display: block;
  font-size: 0.75rem;
  color: var(--muted-strong);
}
.script-row.active .row-meta { color: color-mix(in srgb, var(--on-brand) 70%, transparent); }

/* ---- settings modal ---- */
.setting {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.setting-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  font-size: 0.85rem;
  color: var(--muted);
}
.setting-head output {
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/* A slider and its reset button. The button keeps its width when disabled
   rather than being removed, so the sliders all stop at the same place and
   the column does not shift as values change. */
.setting-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.setting-row input[type="range"] { flex: 1 1 auto; min-width: 0; }

.reset-btn {
  flex: none;
  background: transparent;
  border-color: transparent;
  color: var(--muted-strong);
}
.reset-btn:hover:not(:disabled) {
  background: var(--surface-strong);
  border-color: var(--surface-border);
  color: var(--ink);
}
/* Already at the default: nothing to undo. Dimmed rather than hidden, so the
   row does not reflow the moment somebody touches a slider. */
.reset-btn:disabled {
  opacity: 0.25;
  cursor: default;
}

input[type="range"] {
  width: 100%;
  height: 28px;
  background: transparent;
  -webkit-appearance: none;
  appearance: none;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--surface-border);
}
input[type="range"]::-moz-range-track {
  height: 6px;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--surface-border);
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 20px;
  height: 20px;
  margin-top: -8px;
  border-radius: 999px;
  background: var(--brand-fill-strong);
  border: 1px solid color-mix(in srgb, var(--ink) 40%, transparent);
}
input[type="range"]::-moz-range-thumb {
  width: 20px;
  height: 20px;
  border-radius: 999px;
  background: var(--brand-fill-strong);
  border: 1px solid color-mix(in srgb, var(--ink) 40%, transparent);
}
input[type="range"]:focus-visible { outline: 2px solid var(--brand-ink); outline-offset: 4px; }

.toggle-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px;
}
.toggle-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px;
  border-radius: 12px;
  font-size: 0.85rem;
  background: var(--surface);
  border: 1px solid var(--surface-border);
  color: var(--muted-strong);
  transition: background 0.15s ease, color 0.15s ease;
}
.toggle-btn svg { width: 16px; height: 16px; }
.toggle-btn.active {
  background: var(--brand-fill);
  color: var(--on-brand);
}

/* ---- remote modal ---- */
.remote-code {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 14px;
  border-radius: 16px;
  background: var(--brand-fill);
  color: var(--on-brand);
  font-size: 2rem;
  letter-spacing: 0.22em;
  text-indent: 0.22em;
  font-variant-numeric: tabular-nums;
  user-select: text;
}

.remote-status {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.85rem;
  color: var(--muted);
}
.status-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--busy);
  flex: none;
}
.status-dot.ok { background: var(--ok); }
.status-dot.warn { background: var(--warn); }
.status-dot.error { background: var(--error); }

.remote-link {
  font-size: 0.85rem;
  color: var(--muted);
  word-break: break-all;
  user-select: text;
}

.qr-holder {
  display: flex;
  justify-content: center;
  padding: 12px;
  border-radius: 16px;
  background: var(--surface);
  border: 1px solid var(--surface-border);
}
.qr-holder svg { width: 168px; height: 168px; }
/* The quiet zone and the modules, in tokens rather than fixed black and
   white, so the code stays legible in both modes. */
.qr-holder .qr-bg { fill: #ffffff; }
.qr-holder .qr-fg { fill: #121815; }

.banner {
  padding: 10px 12px;
  border-radius: 12px;
  font-size: 0.85rem;
}
.banner.error {
  background: color-mix(in srgb, var(--error) 14%, transparent);
  color: var(--error);
}
.banner.warn {
  background: color-mix(in srgb, var(--warn) 14%, transparent);
  color: var(--warn);
}

/* ---- toast ---- */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(24px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 60;
  padding: 10px 16px;
  border-radius: 999px;
  font-size: 0.85rem;
  background: var(--brand-fill);
  color: var(--on-brand);
  border: 1px solid var(--surface-border);
  box-shadow: var(--shadow);
  transition: opacity 0.18s ease, transform 0.18s ease, visibility 0s linear 0s;
}
.toast.hidden {
  opacity: 0;
  visibility: hidden;
  transform: translateX(-50%) translateY(8px);
  transition: opacity 0.18s ease, transform 0.18s ease, visibility 0s linear 0.18s;
}

/* ---- shortcuts list ---- */
.shortcut-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: 0.85rem;
  color: var(--muted);
  padding: 4px 0;
}
kbd {
  padding: 2px 8px;
  border-radius: 8px;
  background: var(--surface-strong);
  border: 1px solid var(--surface-border);
  color: var(--ink);
  font-size: 0.78rem;
}

/* ---- the remote page ---- */
.remote-page {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
  max-width: 480px;
  margin: 0 auto;
  padding: 14px;
}
.remote-page .glass { padding: 16px; display: flex; flex-direction: column; gap: 12px; }

.code-input {
  width: 100%;
  padding: 14px;
  border-radius: 16px;
  border: 1px solid var(--surface-border);
  background: var(--surface-strong);
  color: var(--ink);
  font-size: 1.6rem;
  letter-spacing: 0.2em;
  text-align: center;
  text-transform: uppercase;
}
.code-input::placeholder { color: var(--muted-strong); opacity: 1; letter-spacing: 0.2em; }

.remote-controls {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}
.remote-controls .btn { padding: 14px; font-size: 0.9rem; }
.remote-controls .btn-wide { grid-column: 1 / -1; }

.remote-preview {
  max-height: 34vh;
  overflow-y: auto;
  padding: 12px;
  border-radius: 14px;
  background: var(--surface);
  border: 1px solid var(--surface-border);
  white-space: pre-wrap;
  overflow-wrap: break-word;
  font-size: 0.9rem;
  color: var(--muted-strong);
  line-height: 1.5;
}

.remote-page .timer {
  margin: 0;
  text-align: center;
  font-size: 1.6rem;
}

/* The preview, and the control that turns it into an editor. */
#previewBlock {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.preview-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.preview-head .modal-section-label { margin: 0; }

.edit-panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.edit-body {
  width: 100%;
  min-height: 34vh;
  padding: 12px;
  border-radius: 14px;
  border: 1px solid var(--surface-border);
  background: var(--surface-strong);
  color: var(--ink);
  font-size: 0.95rem;
  line-height: 1.5;
  resize: vertical;
}
.edit-body::placeholder { color: var(--muted-strong); opacity: 1; }
.edit-body:focus-visible,
.editor-name:focus-visible { outline: 2px solid var(--brand-ink); outline-offset: 2px; }

/* The remote is a page that scrolls, unlike the prompter. */
body.page-remote { overflow: auto; display: block; }

/* Covers the whole remote while the script is being edited on the prompter.
   It takes the pointer events rather than merely looking like it does, so a
   tap lands on the cover and not on the control underneath it. */
.editing-lock {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 1;
  visibility: visible;
  transition: opacity 0.2s ease, visibility 0s linear 0s;
}
.editing-lock.hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.18s ease, visibility 0s linear 0.18s;
}

.editing-lock-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  max-width: 320px;
  padding: 22px;
  text-align: center;
  background: var(--surface-strong);
}
.editing-lock-card svg { width: 28px; height: 28px; color: var(--brand-ink); }
.editing-lock-card h2 { font-size: 1rem; color: var(--brand-ink); }
.editing-lock-card p { font-size: 0.85rem; color: var(--muted-strong); line-height: 1.5; }

/* Nothing behind the cover scrolls or takes a key while it is up. */
body.locked { overflow: hidden; }

@media (max-width: 480px) {
  .toggle-grid { grid-template-columns: 1fr; }
  .brand span { display: none; }

  /* On a phone the transport cannot hold everything at once. The clock and
     the fullscreen button are the two that can go: the clock is repeated on
     the remote, and fullscreen has the F key and the browser's own control.
     The play button and the two steppers are what the bar is for, so they
     stay, and the row keeps its single line rather than overflowing. */
  .transport { gap: 4px; padding-left: 8px; padding-right: 8px; }
  .transport .timer,
  .transport #fullscreenBtn { display: none; }
  .stepper { flex: 1 1 0; min-width: 0; justify-content: space-between; }
  .stepper-value { min-width: 0; font-size: 0.78rem; padding: 0 2px; }
}

/* Under about 700px the two steppers and the clock cannot share a row with
   the play button, so the transport wraps into two. */
/* Between phone and desktop the transport has more in it than fits
   comfortably, but letting it wrap puts the clock alone on a second row with
   a gap above it, which reads as a mistake. Tighten the row instead, and let
   the steppers give up their fixed width first. */
@media (max-width: 760px) {
  .transport { gap: 6px; padding-left: 10px; padding-right: 10px; }
  .stepper-value { min-width: 0; }
  .timer { padding: 8px 10px; }
}
