/* An author rule that sets `display` beats the browser's own
   `[hidden] { display: none }`, so any element given a display value here would
   ignore the hidden attribute. `.multi-select-option` did exactly that: options
   already chosen stayed visible in the dropdown. Declared once, up front, so it
   cannot be reintroduced by the next component that sets display. */
[hidden] { display: none !important; }

/* Components matching the Claude Design prototypes. */

/* ---- App shell ---------------------------------------------------------- */
.app-side {
  position: fixed; inset: 0 auto 0 0; width: var(--sidebar-w);
  background: var(--surface-raised); border-right: 1px solid var(--border);
  display: flex; flex-direction: column; padding: 20px 0; z-index: 30;
}
/* Bottom-aligned: the CMS tag is a label on the wordmark, and centring it
   against a tall logo left it floating in the middle of nothing. */
.app-brand { padding: 0 20px 24px; display: flex; align-items: flex-end; gap: 7px; }
.app-brand-mark {
  width: 24px; height: 24px; border-radius: 7px; flex-shrink: 0;
  background: linear-gradient(135deg, #4F46E5 55%, #06B6D4);
  display: inline-flex; align-items: center; justify-content: center;
}
.app-brand-mark::after {
  content: ""; width: 0; height: 0; margin-left: 2px;
  border-left: 8px solid #fff;
  border-top: 5px solid transparent; border-bottom: 5px solid transparent;
}
.app-brand-name { font-weight: 800; font-size: 19px; letter-spacing: -0.02em; }
.app-brand-tag {
  font-family: var(--font-sans); font-size: 10px; color: var(--accent);
  letter-spacing: 0.08em; text-transform: uppercase; font-weight: 600;
  padding-bottom: 4px;
}

.app-nav { display: flex; flex-direction: column; gap: 2px; padding: 0 10px; }
.app-nav a {
  padding: 8px 12px; border-radius: var(--radius);
  color: var(--text-muted); font-size: 14px;
}
.app-nav a:hover { background: var(--surface-hover); color: var(--text-primary); }
.app-nav a[aria-current="page"] {
  background: var(--accent-subtle); color: var(--accent-subtle-fg); font-weight: 600;
}

.app-bar {
  position: fixed; top: 0; left: var(--sidebar-w); right: 0; height: var(--topbar-h);
  z-index: 40; display: flex; align-items: center; gap: 12px; padding: 0 24px;
  background: var(--surface-raised); border-bottom: 1px solid var(--border);
}
.app-bar-label {
  font-family: var(--font-sans); font-size: 11px;
  letter-spacing: 0.06em; color: var(--text-muted);
}
.app-bar-right { margin-left: auto; display: flex; align-items: center; gap: 10px; }

.app-main {
  margin-left: var(--sidebar-w); padding: 82px 32px 28px; min-width: 0;
}

.app-avatar {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--accent-solid); color: var(--on-accent);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700;
}

.page-head { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 24px; }
.page-sub { font-size: 13px; color: var(--text-muted); margin-top: 4px; }

/* ---- Buttons ------------------------------------------------------------ */
.btn, .btn-primary, .btn-danger {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--radius); padding: 8px 14px;
  font-family: var(--font-sans); font-weight: 600; font-size: 13.5px;
  cursor: pointer; border: 1px solid var(--border-strong);
  background: none; color: var(--text-secondary);
}
.btn:hover { background: var(--surface-hover); color: var(--text-primary); }
.btn-primary {
  background: var(--accent-solid); color: var(--on-accent); border-color: transparent;
}
.btn-primary:hover { background: var(--accent-solid-hover); color: var(--on-accent); }
.btn-danger { background: none; color: var(--danger); border-color: var(--danger-border); }
.btn-danger:hover { background: var(--danger-bg); color: var(--danger); }
.btn[disabled], .btn-primary[disabled] { opacity: 0.5; cursor: not-allowed; }

.btn-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
/* button_to renders a form; keep it from forcing a line break. */
.btn-row form { display: inline; margin: 0; }

.btn-link {
  background: none; border: none; padding: 0; cursor: pointer;
  color: var(--accent); font-size: 13px; font-weight: 600; font-family: var(--font-sans);
}
.btn-link:hover { color: var(--accent-hover); }
.btn-link-danger { color: var(--danger); }

/* ---- Cards & tables ----------------------------------------------------- */
.card {
  background: var(--surface-raised); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: 20px;
}
.panel {
  background: var(--surface-sunken); border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg); overflow: hidden;
}

.tbl { width: 100%; border-collapse: collapse; }
.tbl thead th {
  text-align: left; padding: 10px 16px; border-bottom: 1px solid var(--border-strong);
  font-family: var(--font-sans); font-size: 10.5px; font-weight: 500;
  letter-spacing: 0.06em; color: var(--text-muted); text-transform: uppercase;
  /* The same tint as the storage card, so a table's header band reads as one
     surface across every list in the app. The panel clips its own corners, so
     the band picks up the rounding at the top. */
  background: var(--tint-storage);
}
.tbl tbody td { padding: 13px 16px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.tbl tbody tr:last-child td { border-bottom: none; }
.tbl tbody tr:hover { background: var(--surface-hover); }
.tbl-name { font-weight: 600; font-size: 14.5px; }
/* Named for the monospace face it used to carry. Kept as the name for the small
   uppercase meta line under a table's primary text, now set in the sans face
   like everything else. */
.tbl-mono { font-family: var(--font-sans); font-size: 11px; color: var(--text-secondary); }
.tbl-note {
  font-size: 12px; color: var(--text-muted);
  padding: 10px 16px; border-top: 1px solid var(--border);
}
.tbl-actions { display: flex; gap: 12px; justify-content: flex-end; align-items: center; }

/* ---- Badges ------------------------------------------------------------- */
.badge {
  display: inline-block; font-family: var(--font-sans); font-size: 10px;
  padding: 3px 8px; border-radius: 99px; letter-spacing: 0.04em;
  background: var(--neutral-bg); color: var(--neutral-fg);
}
.badge-active { background: var(--ok-bg); color: var(--ok-fg); }
.badge-pending { background: var(--warn-bg); color: var(--warn-fg); }
.badge-archived { background: var(--neutral-bg); color: var(--neutral-fg); }

/* ---- Forms -------------------------------------------------------------- */
.field { margin-bottom: 14px; }
.field label, .field-label {
  display: block; font-family: var(--font-sans); font-size: 11px;
  letter-spacing: 0.04em; color: var(--text-muted);
  margin-bottom: 6px; text-transform: uppercase;
}
.field input[type="text"], .field input[type="email"],
.field input[type="number"], .field input[type="password"], .field select {
  width: 100%; background: var(--surface-raised);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  padding: 9px 12px; font-family: var(--font-sans); font-size: 14px;
  color: var(--text-primary);
}
.field input:focus, .field select:focus {
  outline: 2px solid var(--accent-solid); outline-offset: -1px;
}
.field-hint { display: block; font-size: 12px; color: var(--text-muted); margin-top: 5px; }
.form-narrow { max-width: 460px; }

/* ---- Feedback ----------------------------------------------------------- */
.flash { padding: 10px 14px; border-radius: var(--radius); margin-bottom: 18px; font-size: 13.5px; }
.flash-notice { background: var(--accent-subtle); color: var(--accent-subtle-fg); }
.flash-alert { background: var(--danger-bg); color: var(--danger); border: 1px solid var(--danger-border); }

.callout {
  padding: 12px 14px; border-radius: var(--radius); font-size: 13px;
  background: var(--surface-sunken); color: var(--text-secondary); margin-bottom: 16px;
}
.callout-danger {
  background: var(--danger-bg); color: var(--danger);
  border: 1px solid var(--danger-border);
}

.meta { display: grid; grid-template-columns: 140px 1fr; gap: 10px 16px; margin: 0; }
.meta dt { font-family: var(--font-sans); font-size: 11px; color: var(--text-muted); text-transform: uppercase; }
.meta dd { margin: 0; font-size: 14px; }

.empty { color: var(--text-muted); font-size: 13.5px; padding: 20px 0; }

@media (max-width: 900px) {
  .app-side { display: none; }
  .app-bar { left: 0; }
  .app-main { margin-left: 0; padding: 74px 14px 24px; }
  .meta { grid-template-columns: 1fr; gap: 4px 0; }
}

/* ---- Modal -------------------------------------------------------------- */
/* Native <dialog> so Escape, focus trapping and background inerting come for
 * free; Stimulus only opens it and clears the Turbo Frame on close. */
dialog.modal {
  padding: 0; border: none; background: transparent;
  max-width: none; max-height: none; width: 100%; height: 100%;
  margin: 0; overflow: visible;
}
dialog.modal::backdrop { background: rgba(15, 23, 42, 0.45); }

.modal-positioner {
  position: fixed; inset: 0; display: flex;
  align-items: center; justify-content: center; padding: 24px;
}

.modal-card {
  background: var(--surface-sunken);
  border: 1px solid var(--border-strong);
  border-radius: 14px; padding: 24px;
  width: 100%; max-width: 520px;
  box-shadow: 0 24px 60px rgba(15, 23, 42, 0.25);
  max-height: calc(100vh - 48px); overflow-y: auto;
}
.modal-title { margin: 0 0 18px; font-size: 19px; font-weight: 700; letter-spacing: -0.01em; }

.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 560px) { .field-row { grid-template-columns: 1fr; } }

.page-stats {
  font-family: var(--font-sans); font-size: 11px; letter-spacing: 0.06em;
  color: var(--text-muted); text-transform: uppercase; margin-top: 6px;
}

/* Flash auto-dismiss (see flash_controller.js). */
.flash { transition: opacity 250ms ease, transform 250ms ease; }
.flash-leaving { opacity: 0; transform: translateY(-6px); }

@media (prefers-reduced-motion: reduce) {
  .flash { transition: none; }
}

/* ---- Client shell ------------------------------------------------------- */
.app-nav-soon {
  padding: 8px 12px; border-radius: var(--radius);
  color: var(--text-muted); font-size: 14px; opacity: 0.45; cursor: default;
}
.app-side-foot { margin-top: auto; padding: 16px 20px; border-top: 1px solid var(--border); }
.app-storage-label {
  font-family: var(--font-sans); font-size: 11px;
  color: var(--text-muted); margin-bottom: 8px; text-transform: uppercase;
}
.app-storage-bar { height: 4px; background: var(--border); border-radius: 2px; overflow: hidden; }
.app-storage-bar span { display: block; height: 100%; background: var(--accent-solid); }

/* Pairing code entry — six boxes, grouped 3 and 3. */
.code-entry { display: flex; align-items: center; gap: 8px; justify-content: center; margin: 4px 0 12px; }
.code-entry input {
  width: 46px; height: 56px; text-align: center;
  font-family: var(--font-sans); font-size: 24px; font-weight: 500;
  background: var(--surface-raised); color: var(--text-primary);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
}
.code-entry input:focus { outline: 2px solid var(--accent-solid); outline-offset: -1px; }
.code-entry span { color: var(--text-muted); font-size: 20px; }

.badge-outline {
  background: none; border: 1px solid var(--border-strong); color: var(--text-secondary);
}

/* Segmented control — the design's Landscape / Portrait toggle.
   Selection is shown with `input:checked + span` rather than `label:has(...)`.
   The radio itself is invisible, so this rule is the only thing telling the
   user which option is chosen — and :has() would have made Firefox 121 the
   minimum browser for the whole app over one selector. */
.segmented { display: inline-flex; border: 1px solid var(--border-strong); border-radius: var(--radius); overflow: hidden; }
.segmented label { display: inline-flex; margin: 0; cursor: pointer; }
.segmented label + label { border-left: 1px solid var(--border-strong); }
.segmented label input { position: absolute; opacity: 0; pointer-events: none; }
.segmented label span {
  display: inline-flex; align-items: center; padding: 8px 18px;
  font-family: var(--font-sans); font-size: 13.5px; font-weight: 600;
  color: var(--text-secondary); text-transform: none; letter-spacing: normal;
}
.segmented label input:checked + span { background: var(--accent-solid); color: var(--on-accent); }
.segmented label input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: -2px; }

.badge-failed { background: var(--danger-bg); color: var(--danger); }

.progress {
  height: 6px; background: var(--border); border-radius: 3px;
  overflow: hidden; margin-bottom: 14px;
}
.progress span {
  display: block; height: 100%; width: 0;
  background: var(--accent-solid); transition: width 150ms linear;
}

/* ---- Upload dropzone ---------------------------------------------------- */
.dropzone {
  border: 2px dashed var(--border-strong);
  border-radius: var(--radius-lg);
  padding: 28px 20px;
  text-align: center;
  cursor: pointer;
  background: var(--surface-raised);
  transition: border-color 120ms ease, background 120ms ease;
}
.dropzone:hover, .dropzone:focus-visible {
  border-color: var(--accent-solid);
  background: var(--surface-hover);
}
.dropzone.is-dragover {
  border-color: var(--accent-solid);
  background: var(--accent-subtle);
}
.dropzone-title { font-size: 15px; font-weight: 600; margin-bottom: 6px; }
.dropzone-hint {
  font-size: 12.5px; color: var(--text-muted);
  margin: 0 auto 14px; max-width: 380px; line-height: 1.45;
}
.dropzone-browse { pointer-events: none; }

/* Kept in the layout so it stays focusable and form validation still fires. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---- Media thumbnails and preview --------------------------------------- */
.media-cell { display: flex; align-items: center; gap: 12px; }

.media-thumb {
  position: relative; flex-shrink: 0;
  border-radius: var(--radius);
  overflow: hidden; background: var(--surface-sunken);
  border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center;
}

/* Fixed-width frame, thumbnail centred inside. Without it a 26px portrait
 * thumbnail and a 64px landscape one push their filenames to different
 * positions, leaving the column visibly ragged. */
.media-frame { display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.media-frame-md { width: 64px; }
.media-frame-sm { width: 48px; }

/* Height is held constant and width varies, so a portrait thumbnail reads as
 * portrait without changing the row height of the list it sits in. */
.media-thumb-md { height: 44px; }
.media-thumb-md.is-landscape { width: 64px; }
.media-thumb-md.is-portrait  { width: 26px; }
.media-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.media-thumb.is-empty, .media-thumb-fallback { color: var(--text-muted); font-size: 15px; }
a.media-thumb:hover { border-color: var(--accent-solid); }

/* Play affordance, so a video thumbnail reads as playable. */
.media-thumb-play {
  position: absolute; inset: 0; display: flex;
  align-items: center; justify-content: center;
  background: rgba(15, 23, 42, 0.35); color: #fff; font-size: 15px;
}
a.media-thumb:hover .media-thumb-play { background: rgba(15, 23, 42, 0.5); }

.modal-card-wide { max-width: 760px; }
.preview-stage {
  background: #000; border-radius: var(--radius);
  display: flex; align-items: center; justify-content: center;
  max-height: 60vh; overflow: hidden;
}
.preview-stage video, .preview-stage img {
  max-width: 100%; max-height: 60vh; display: block;
}

/* ---- Playlist builder --------------------------------------------------- */
.cols { display: grid; grid-template-columns: 1.3fr 1fr; gap: 24px; align-items: start; }
@media (max-width: 980px) { .cols { grid-template-columns: 1fr; } }

.panel-head {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px; border-bottom: 1px solid var(--border-strong);
}
.panel-title { font-weight: 700; font-size: 15px; }
.panel-hint { font-size: 12px; color: var(--text-muted); margin-left: auto; }

.reorder-list, .picker-list { list-style: none; margin: 0; padding: 0; }

.reorder-item, .picker-item {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px; border-bottom: 1px solid var(--border);
  background: var(--surface-raised);
}
.reorder-item:last-child, .picker-item:last-child { border-bottom: none; }
.reorder-item { cursor: grab; }
.reorder-item.is-dragging { opacity: 0.45; cursor: grabbing; }
.reorder-item:hover { background: var(--surface-hover); }

.reorder-grip { color: var(--text-muted); font-size: 15px; cursor: grab; }
.reorder-pos {
  font-family: var(--font-sans); font-size: 11px; color: var(--text-muted);
  min-width: 18px; text-align: right;
}
.reorder-body, .picker-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.picker-add { margin: 0; }

/* ---- Multi-select combobox ---------------------------------------------- */
.multi-select { position: relative; }
.multi-select-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.multi-select-chips:not(:empty) { margin-bottom: 10px; }
.multi-select-empty {
  font-size: 13px; color: var(--text-muted); margin-bottom: 10px;
}

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 6px 4px 10px; border-radius: 99px;
  background: var(--accent-subtle); color: var(--accent-subtle-fg);
  font-size: 12.5px; font-weight: 600;
}
.chip-remove {
  border: none; background: none; cursor: pointer; padding: 0 2px;
  color: inherit; font-size: 15px; line-height: 1; opacity: 0.7;
}
.chip-remove:hover { opacity: 1; }

.multi-select-toggle { width: 100%; justify-content: center; }
.multi-select-menu {
  position: absolute; left: 0; right: 0; z-index: 60; margin-top: 6px;
  background: var(--surface-raised); border: 1px solid var(--border-strong);
  border-radius: var(--radius); box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18);
  max-height: 220px; overflow-y: auto; padding: 4px;
}
.multi-select-option {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; padding: 8px 10px; border: none; background: none; cursor: pointer;
  border-radius: var(--radius); font-family: var(--font-sans); font-size: 13.5px;
  color: var(--text-primary); text-align: left;
}
.multi-select-option:hover { background: var(--surface-hover); }

/* Compact single-line picker row — fits more options in the same height than
 * the stacked .picker-item, which suits long content filenames but wastes
 * space on short screen names. */
.picker-row {
  display: flex; align-items: baseline; gap: 10px;
  padding: 7px 12px; border-bottom: 1px solid var(--border);
  cursor: pointer; font-size: 13.5px;
}
.picker-row:last-child { border-bottom: none; }
.picker-row:hover { background: var(--surface-hover); }
.picker-row input[type="checkbox"] { align-self: center; flex-shrink: 0; }

.picker-row-name { font-weight: 600; flex-shrink: 0; }
.picker-row-meta {
  font-family: var(--font-sans); font-size: 11px; color: var(--text-muted);
  margin-left: auto; text-align: right;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.picker-row.is-disabled { cursor: default; opacity: 0.5; }
.picker-row.is-disabled:hover { background: none; }

/* Smaller thumbnail for the playlist builder, where rows are denser than the
 * media list. */
.media-thumb-sm { height: 32px; }
.media-thumb-sm.is-landscape { width: 48px; }
.media-thumb-sm.is-portrait  { width: 19px; }
.media-thumb-sm .media-thumb-play { font-size: 10px; }

/* ---- Screens table: connection, sync, row menu -------------------------- */
.conn-cell { display: inline-flex; align-items: center; gap: 7px; position: relative; }

.conn-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; display: inline-block; }
.conn-dot.is-online { background: var(--ok-fg); }
.conn-dot.is-offline { background: none; border: 1.5px solid var(--text-muted); }

.conn-label { font-size: 13.5px; }
.conn-label.is-online { color: var(--ok-fg); font-weight: 600; }
.conn-muted { color: var(--text-muted); }

.sync-ok { color: var(--ok-fg); font-size: 13.5px; font-weight: 600; }

.sync-publishing {
  font-family: var(--font-sans); font-size: 11px;
  color: var(--warn-fg); letter-spacing: 0.04em;
}
.sync-bar {
  height: 3px; background: var(--border); border-radius: 2px;
  overflow: hidden; margin-top: 5px; max-width: 140px;
}
.sync-bar span { display: block; height: 100%; background: var(--warn-fg); }

.sync-error-head {
  font-family: var(--font-sans); font-size: 11px;
  color: var(--danger); letter-spacing: 0.04em;
}
.sync-error-body { font-size: 12.5px; color: var(--danger); white-space: normal; max-width: 220px; }

/* A red rule down the side of a failed row, as in the design. */
.tbl tbody tr.is-error td:first-child { box-shadow: inset 3px 0 0 var(--danger); }

/* ---- Overflow menu ------------------------------------------------------ */
.row-menu { position: relative; display: inline-block; }
.row-menu-trigger {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: var(--radius);
  color: var(--text-muted); font-size: 16px; line-height: 1; user-select: none;
}
.row-menu-trigger:hover { background: var(--surface-hover); color: var(--text-primary); }

.row-menu-items {
  /* Fixed, and placed by the dismissable controller: the panel it sits inside
     hides its overflow to keep the table corners rounded, which clipped an
     absolutely positioned menu whenever the table was shorter than the menu. */
  position: fixed; top: 0; left: 0; z-index: 60; min-width: 190px;
  background: var(--surface-raised); border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg); padding: 5px;
  box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18);
  display: flex; flex-direction: column;
}
.row-menu-item {
  display: block; width: 100%; text-align: left;
  padding: 8px 10px; border: none; background: none; cursor: pointer;
  border-radius: var(--radius); font-family: var(--font-sans); font-size: 13.5px;
  color: var(--text-primary);
}
.row-menu-item:hover { background: var(--surface-hover); color: var(--text-primary); }
.row-menu-item.is-danger { color: var(--accent); font-weight: 600; }
.row-menu-item.is-disabled { color: var(--text-muted); cursor: not-allowed; }
.row-menu-item.is-disabled:hover { background: none; }
.row-menu-divider { border-top: 1px solid var(--border); margin: 4px 0; }
.row-menu form { margin: 0; }

/* ---- Tooltip ------------------------------------------------------------ */
/* CSS-only: survives Turbo Stream replacement with nothing to re-initialise. */
[data-tooltip] { position: relative; }
[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%);
  background: var(--text-primary); color: var(--surface-raised);
  padding: 7px 10px; border-radius: var(--radius);
  font-family: var(--font-sans); font-size: 12px; font-weight: 500;
  white-space: nowrap; pointer-events: none;
  opacity: 0; visibility: hidden; transition: opacity 120ms ease;
  z-index: 70; box-shadow: 0 6px 18px rgba(15, 23, 42, 0.22);
}
[data-tooltip]::before {
  content: ""; position: absolute; bottom: calc(100% + 3px); left: 50%;
  transform: translateX(-50%); border: 5px solid transparent;
  border-top-color: var(--text-primary);
  opacity: 0; visibility: hidden; transition: opacity 120ms ease; z-index: 70;
}
[data-tooltip]:hover::after, [data-tooltip]:hover::before,
[data-tooltip]:focus-visible::after, [data-tooltip]:focus-visible::before {
  opacity: 1; visibility: visible;
}

/* ---- Icon button -------------------------------------------------------- */
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 999px;
  border: 1px solid var(--border-strong); background: var(--surface);
  color: var(--text-secondary); cursor: pointer; padding: 0;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.icon-btn svg { width: 15px; height: 15px; }
.icon-btn:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
.icon-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---- Screenshot grid ---------------------------------------------------- */
.shot-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 12px; margin: 4px 0 14px;
}
.shot { margin: 0; }
.shot img {
  width: 100%; aspect-ratio: 16 / 9; object-fit: contain;
  background: var(--surface-sunken); border: 1px solid var(--border);
  border-radius: var(--radius); display: block;
}
.shot figcaption { margin-top: 5px; font-size: 11px; color: var(--text-muted); }

/* ---- Dashboard ---------------------------------------------------------- */
.panel-pad { padding: 18px; }
.panel-label {
  font-family: var(--font-sans); font-size: 11px; letter-spacing: 0.05em;
  color: var(--text-muted); text-transform: uppercase;
}

.attention {
  margin-bottom: 16px; padding: 14px 16px;
  background: var(--danger-bg); border: 1px solid var(--danger-border);
  border-radius: var(--radius-lg);
  display: flex; gap: 14px; align-items: baseline; flex-wrap: wrap;
}
.attention strong { white-space: nowrap; color: var(--danger-hover); font-size: 14px; }
.attention span { font-size: 13.5px; color: var(--danger); }
.attention-link { margin-left: auto; white-space: nowrap; font-size: 13px; font-weight: 600; }

.stat-cards {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 14px; margin-bottom: 14px;
}
.stat-card {
  background: var(--surface-sunken); border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: 16px 18px;
  display: flex; flex-direction: column; gap: 6px;
}
.stat-label {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-sans); font-size: 11px; letter-spacing: 0.05em;
  color: var(--text-muted); text-transform: uppercase;
}
.stat-value { font-size: 30px; font-weight: 800; letter-spacing: -0.03em; line-height: 1; }

/* One palette drives the dots, the stacked bar and the legend chips, so a
   colour never means two different things on the same page. */
.state-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.state-chip { width: 8px; height: 8px; border-radius: 2px; display: inline-block; }

.state-total { background: var(--accent-solid); }
.state-playing, .state-bar .state-playing { background: var(--ok-fg); }
.state-syncing, .state-bar .state-syncing { background: var(--warn-fg); }
.state-online, .state-bar .state-online { background: var(--accent); }
.state-sync-error, .state-bar .state-sync-error { background: var(--danger-solid); }
.state-unassigned, .state-bar .state-unassigned { background: var(--neutral-bg); }
/* Hollow, matching the connection column: an offline screen is an absence. */
.state-dot.state-offline { background: none; border: 1.5px solid var(--border-strong); }
.state-chip.state-offline, .state-bar .state-offline { background: var(--border-strong); }

.state-bar {
  display: flex; height: 12px; border-radius: 6px;
  overflow: hidden; background: var(--border);
}
.state-bar span { display: block; height: 100%; }
.state-legend {
  display: flex; flex-wrap: wrap; gap: 14px; margin-top: 12px;
  font-size: 12.5px; color: var(--text-secondary);
}
.state-legend > span { display: inline-flex; align-items: center; gap: 6px; }

.dash-cols {
  display: grid; grid-template-columns: 1.6fr 1fr; gap: 14px;
  align-items: start; margin-bottom: 26px;
}

.storage-figure { display: flex; align-items: baseline; gap: 8px; margin-top: 12px; }
.storage-used { font-size: 26px; font-weight: 800; letter-spacing: -0.03em; }
.storage-of { font-size: 13px; color: var(--text-muted); }
.storage-bar {
  height: 10px; background: var(--border); border-radius: 5px;
  overflow: hidden; margin-top: 12px;
}
.storage-bar div { height: 100%; background: var(--accent-solid); }
.storage-foot {
  display: flex; justify-content: space-between; margin-top: 8px;
  font-family: var(--font-sans); font-size: 11px; color: var(--text-muted);
  text-transform: uppercase;
}

.section-head { display: flex; align-items: center; gap: 12px; margin: 0 0 10px; }
.section-head .btn-link { margin-left: auto; }

@media (max-width: 900px) {
  .dash-cols { grid-template-columns: 1fr; }
}

/* ---- Auth pages --------------------------------------------------------- */
.auth-split { display: grid; grid-template-columns: 1fr 1fr; min-height: 100dvh; }
.auth-centre { display: flex; align-items: center; justify-content: center; min-height: 100dvh; padding: 24px; }

.auth-panel {
  display: flex; flex-direction: column; justify-content: center;
  padding: 48px; gap: 28px; background: var(--surface-raised);
  min-height: 100dvh; box-sizing: border-box;
  /* Centred in its half rather than pinned to the outer edge: at 48px padding
     on a wide screen the form sat against the window edge with the width of a
     whole column of empty space beside it. */
  align-items: center;
  /* The photo goes on the left. Done with order rather than by moving the
     markup so the form still comes first in the document — the aside is
     aria-hidden and holds nothing focusable, so nothing is confused by it. */
  order: 2;
}
/* Brand, form and footer share one column so they stay aligned with each other
   while the stack as a whole is centred. */
.auth-panel > * { width: 100%; max-width: 380px; }
.auth-centre .auth-panel {
  width: 100%; max-width: 420px; border: 1px solid var(--border);
  border-radius: var(--radius-lg); padding: 36px; min-height: 0;
}
.auth-form { max-width: 380px; }
.auth-form h1 { margin: 0 0 8px; font-size: 26px; font-weight: 700; letter-spacing: -0.02em; }
.auth-lede { margin: 0 0 24px; font-size: 14px; color: var(--text-secondary); line-height: 1.55; }

.field { margin-bottom: 16px; }
.field-label {
  display: block; margin-bottom: 6px;
  font-family: var(--font-sans); font-size: 11px; letter-spacing: 0.06em;
  color: var(--text-muted); text-transform: uppercase;
}
.auth-form input[type="email"],
.auth-form input[type="password"],
.auth-form input[type="text"] {
  width: 100%; box-sizing: border-box; padding: 11px 13px;
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  background: var(--surface-page); color: var(--text-primary);
  font-family: var(--font-sans); font-size: 14px;
}
.auth-form input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }

.auth-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin: 4px 0 20px; flex-wrap: wrap;
}
.auth-remember {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13.5px; color: var(--text-secondary); cursor: pointer;
}
.auth-submit { width: 100%; justify-content: center; }
.auth-notes {
  margin-top: 20px; display: flex; flex-direction: column; gap: 6px;
  font-size: 12.5px; color: var(--text-muted); line-height: 1.5;
}
.auth-foot {
  font-family: var(--font-sans); font-size: 11px; letter-spacing: 0.06em;
  color: var(--text-muted); text-transform: uppercase;
}
.auth-centre .auth-foot { text-transform: none; letter-spacing: 0; font-family: var(--font-sans); font-size: 12.5px; }

.auth-aside {
  position: relative; overflow: hidden; order: 1;
  /* Fallback for the moment before the photo arrives, or if it fails. */
  background: var(--surface-sunken); border-right: 1px solid var(--border);
}
.auth-aside-photo {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center;
}


@media (max-width: 900px) {
  .auth-split { grid-template-columns: 1fr; }
  .auth-aside { display: none; }
  /* Top-aligned rather than centred: with the aside hidden the panel is the
     only row, and centring pushed the form below the fold on a tall phone.
     It also ends at its content instead of stretching to fill the viewport —
     that stretch existed to avoid a background seam in dark mode, and with one
     palette the panel and the page are the same colour anyway. Dropping its own
     background guarantees no seam whatever the height. */
  /* The page is exactly as tall as the form plus a small margin. No stretching
     to the viewport and no centring — both leave a stretch of empty page that
     serves nothing. */
  .auth-panel {
    padding: 30px 22px; justify-content: flex-start;
    min-height: auto; background: none;
  }
  .auth-split { min-height: auto; }
  .auth-centre { align-items: flex-start; padding: 24px 18px; }
  .auth-form { max-width: none; }
}

/* ---- Landing page ------------------------------------------------------- */
/* Full-bleed canvas; every section holds its own max-width and 5vw gutter, so
   the page breathes to the window rather than sitting in a narrow column. */
.lp-shell {
  background: var(--canvas); min-height: 100vh;
  overflow: hidden; position: relative;
}

.lp-bar-wrap { position: sticky; top: 16px; z-index: 40; padding: 16px 5vw 0; }
.lp-pill-nav {
  display: flex; align-items: center; gap: 24px;
  padding: 10px 10px 10px 20px; border-radius: 999px;
  /* Frosted, so content scrolling underneath stays faintly visible. */
  background: color-mix(in oklch, var(--surface-raised) 88%, transparent);
  backdrop-filter: blur(10px);
  border: 1px solid var(--border); box-shadow: 0 12px 32px rgba(15, 23, 42, 0.08);
}
.lp-brand { display: inline-flex; align-items: center; gap: 8px; color: inherit; }
.lp-brand:hover { color: inherit; }
.lp-brand-name { font-weight: 800; font-size: 19px; letter-spacing: -0.02em; }
.lp-nav-links { display: flex; gap: 22px; margin-left: 8px; font-size: 14px; font-weight: 500; }
.lp-nav-links a { color: var(--text-primary); }
.lp-nav-links a:hover { color: var(--accent); }
.lp-bar-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }

/* Pill buttons, not the app's square ones — the landing page has its own. */
.lp-btn, .lp-btn-ghost {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 999px; padding: 11px 20px;
  font-family: var(--font-sans); font-size: 14px; font-weight: 700;
  border: 1px solid transparent; cursor: pointer; white-space: nowrap;
}
.lp-btn { background: var(--accent-solid); color: var(--on-accent); }
.lp-btn:hover { background: var(--accent-solid-hover); color: var(--on-accent); }
.lp-btn-ghost { background: var(--surface-raised); color: var(--text-primary); border-color: var(--border-strong); }
.lp-btn-ghost:hover { background: var(--surface-hover); color: var(--text-primary); }
.lp-btn-lg { padding: 14px 24px; font-size: 15px; }

/* z-index 1 so the decorative washes stay behind the words. The blobs are
   positioned elements later in the document, so without this they paint over
   any section that has not claimed a layer of its own. */
.lp-section { max-width: 1360px; margin: 0 auto; padding: 0 5vw 64px; position: relative; z-index: 1; }
.lp-section h2 { margin: 10px 0 0; font-size: 28px; font-weight: 800; letter-spacing: -0.025em; }
.lp-centred { text-align: center; }
.lp-centred .lp-lede { margin-left: auto; margin-right: auto; }

.lp-hero {
  position: relative; display: grid; grid-template-columns: 1.05fr 1fr;
  gap: 48px; align-items: center; padding: 88px 5vw 100px;
  max-width: 1360px; margin: 0 auto;
}
.lp-hero-copy { position: relative; z-index: 1; }
.lp-hero-visual { position: relative; z-index: 1; }
.lp-hero-image { width: 100%; height: auto; display: block; }

.lp-blob {
  position: absolute; border-radius: 50%; z-index: 0; pointer-events: none;
}
.lp-blob-accent {
  top: -160px; left: -120px; width: 480px; height: 480px; opacity: 0.9;
  background: radial-gradient(circle, var(--accent-subtle), transparent 70%);
}
.lp-blob-cyan {
  bottom: -200px; right: 0; width: 420px; height: 420px; opacity: 0.8;
  background: radial-gradient(circle, var(--cyan-tint), transparent 70%);
}
/* A third wash further down the page, anchored to the shell rather than to any
   one section. */
.lp-blob-low {
  left: -123px; top: 1582px; width: 420px; height: 420px; opacity: 0.8;
  background: radial-gradient(circle, var(--cyan-tint), transparent 70%);
}

.lp-eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--accent-subtle); color: var(--accent-subtle-fg);
  border-radius: 999px; padding: 7px 14px 7px 10px;
  font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; font-weight: 600;
}
.lp-eyebrow-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
.lp-h1 {
  margin: 20px 0 0; font-size: 52px; line-height: 1.04;
  font-weight: 800; letter-spacing: -0.035em; text-wrap: pretty;
}
.lp-h1-mark { color: var(--accent); }
.lp-lede { margin: 18px 0 26px; font-size: 16px; line-height: 1.6; color: var(--text-secondary); max-width: 62ch; }
.lp-cta { display: flex; gap: 12px; flex-wrap: wrap; }

.lp-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-top: 40px; }
.lp-stats > span { display: flex; flex-direction: column; gap: 2px; }
.lp-stats strong { font-size: 28px; font-weight: 800; letter-spacing: -0.03em; }
.lp-stats > span > span { font-size: 13px; color: var(--text-muted); }

/* ---- How it works: a dark card, not page background --------------------- */
.lp-dark-card {
  background: var(--ink); border-radius: 24px; padding: 44px 5vw; color: #fff;
}
.lp-dark-card h2 { color: #fff; }
.lp-eyebrow-dark {
  font-size: 11px; letter-spacing: 0.08em; color: #D6F6F7;
  text-transform: uppercase; font-weight: 600;
}
.lp-dark-card .lp-3 { gap: 28px; margin-top: 30px; }
.lp-num {
  width: 34px; height: 34px; border-radius: 10px; flex-shrink: 0;
  background: rgba(255, 255, 255, 0.1); color: var(--cyan);
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 14px;
}
.lp-step-title { font-size: 15.5px; font-weight: 700; margin-top: 14px; color: #fff; }
.lp-step-body { font-size: 13.5px; color: rgba(255, 255, 255, 0.62); margin-top: 6px; line-height: 1.6; }

.lp-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.lp-4 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-top: 30px; }

/* ---- Features: a tinted row and a dark row ------------------------------ */
.lp-eyebrow-plain {
  display: block; font-size: 11px; letter-spacing: 0.08em;
  color: var(--accent); text-transform: uppercase; font-weight: 600;
}
.lp-feature-row { gap: 18px; margin-top: 28px; }
.lp-feature-row-dark { gap: 16px; margin-top: 16px; }

.lp-feature {
  display: flex; flex-direction: column; gap: 14px;
  border: 1px solid var(--border); border-radius: 18px; padding: 26px;
  background: var(--tint-feature-b); text-align: left;
}
.lp-feature.is-first { background: var(--tint-feature-a); }
.lp-feature .lp-feature-title { font-size: 16.5px; font-weight: 700; letter-spacing: -0.01em; }
.lp-feature .lp-feature-body { font-size: 13.5px; color: var(--text-muted); line-height: 1.6; }

.lp-icon {
  width: 40px; height: 40px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
}
.lp-icon-accent { background: var(--accent-subtle); }
.lp-icon-cyan { background: var(--cyan-tint); }
.lp-icon-circle { width: 14px; height: 14px; border-radius: 50%; background: var(--accent-solid); }
.lp-icon-square { width: 14px; height: 14px; border-radius: 4px; background: var(--accent-solid); }
.lp-icon-diamond { width: 14px; height: 14px; background: var(--cyan); transform: rotate(45deg); }

.lp-feature-arrow {
  margin-top: auto; align-self: flex-end;
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--accent-solid); color: var(--on-accent);
  display: flex; align-items: center; justify-content: center; font-size: 15px;
}
.lp-feature-arrow:hover { background: var(--accent-solid-hover); color: var(--on-accent); }

.lp-feature-dark {
  border: 1px solid var(--border); border-radius: 16px; padding: 20px;
  background: var(--ink-card); text-align: left;
}
.lp-feature-dark .lp-feature-title { font-size: 15px; font-weight: 700; color: #F8F3F3; }
.lp-feature-dark .lp-feature-body { font-size: 13px; color: var(--text-muted); margin-top: 6px; line-height: 1.55; }

.lp-slot {
  display: flex; align-items: center; justify-content: center; padding: 18px;
  background: var(--surface-sunken); border: 1px dashed var(--border-strong);
  border-radius: 16px; aspect-ratio: 3 / 2;
}
.lp-slot-note { font-size: 12px; color: var(--text-muted); text-align: center; max-width: 22ch; line-height: 1.5; }
.lp-solution { margin: 0; }
.lp-solution img {
  display: block; width: 100%; height: auto; aspect-ratio: 3 / 2;
  object-fit: cover; border-radius: 16px; border: 1px solid var(--border);
  background: var(--surface-sunken);
}
.lp-solution figcaption { margin-top: 10px; font-size: 14.5px; font-weight: 600; }

/* ---- Pricing: one dark card, split in two ------------------------------- */
.lp-testi {
  display: grid; grid-template-columns: 1fr 0.9fr; gap: 0;
  background: var(--ink); border-radius: 24px; overflow: hidden; position: relative;
}
.lp-quote {
  margin: 0; padding: 44px 40px; border: none; background: none;
  display: flex; flex-direction: column; gap: 18px; color: #fff;
}
.lp-quote-mark { font-size: 44px; font-weight: 800; color: var(--cyan); line-height: 1; }
.lp-quote p { margin: 0; font-size: 19px; line-height: 1.5; font-weight: 600; max-width: 420px; }
.lp-quote footer { border: none; padding: 0; }
.lp-quote-name { font-size: 14px; font-weight: 700; color: #fff; }
.lp-quote-role { font-size: 12.5px; color: rgba(255, 255, 255, 0.6); }

/* A lighter pane on the same card rather than a separate block. */
.lp-price-pane {
  padding: 44px 40px; background: rgba(255, 255, 255, 0.04);
  display: flex; flex-direction: column; gap: 16px; justify-content: center;
}
.lp-price-pane h3 { margin: 0; font-size: 22px; font-weight: 800; letter-spacing: -0.02em; color: #fff; }
.lp-price-pane p { margin: 0; font-size: 14px; line-height: 1.6; color: rgba(255, 255, 255, 0.65); }
.lp-price-pane .lp-cta { margin-top: 6px; }

.lp-btn-cyan, .lp-btn-onDark {
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 999px; padding: 12px 20px;
  font-family: var(--font-sans); font-size: 14px; font-weight: 700; white-space: nowrap;
}
.lp-btn-cyan { background: var(--cyan); color: var(--ink); border: 1px solid transparent; }
.lp-btn-cyan:hover { background: var(--cyan); color: var(--ink); filter: brightness(1.06); }
.lp-btn-onDark { border: 1px solid rgba(255, 255, 255, 0.25); color: #fff; }
.lp-btn-onDark:hover { background: rgba(255, 255, 255, 0.08); color: #fff; }

.lp-foot {
  position: relative; z-index: 1;
  display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
  max-width: 1360px; margin: 0 auto; padding: 28px 5vw;
  border-top: 1px solid var(--border);
}
.lp-foot-meta { font-size: 12px; color: var(--text-muted); }
.lp-foot-links { margin-left: auto; display: flex; gap: 18px; font-size: 13.5px; flex-wrap: wrap; }

@media (max-width: 900px) {
  .lp-nav-links { display: none; }
  .lp-pill-nav { gap: 10px; padding: 8px 8px 8px 14px; }
  .lp-hero { grid-template-columns: 1fr; padding: 40px 5vw 56px; gap: 24px; }
  .lp-hero-visual { margin-top: 8px; }
  .lp-h1 { font-size: 34px; }
  /* Three across rather than the design's two: with only three figures, 2+1
     leaves the last one stranded beside a gap. Smaller type keeps them on the
     one row. */
  .lp-stats { grid-template-columns: repeat(3, 1fr); margin-top: 28px; gap: 12px; }
  .lp-stats strong { font-size: 21px; }
  .lp-stats > span > span { font-size: 11.5px; }
  .lp-3 { grid-template-columns: 1fr; }
  .lp-4 { grid-template-columns: repeat(2, 1fr); }
  .lp-testi { grid-template-columns: 1fr; }
  .lp-quote, .lp-price-pane { padding: 32px 22px; }
  .lp-dark-card { padding: 32px 22px; border-radius: 18px; }
  .lp-foot-links { margin-left: 0; }

  /* Side by side these two wrap onto separate rows and read as an accident.
     Full width, stacked, is a deliberate-looking arrangement at this size. */
  .lp-cta { flex-direction: column; align-items: stretch; }
  .lp-cta > a { width: 100%; }

  /* The pill has to stay one row. Log in is dropped rather than wrapped — it is
     repeated immediately below in the hero, so nothing is lost. */
  .lp-bar-right .lp-btn-ghost { display: none; }
  .lp-btn, .lp-btn-ghost { padding: 10px 16px; font-size: 13.5px; }
  .lp-btn-lg { padding: 13px 20px; font-size: 14.5px; }
  .lp-brand-name { font-size: 17px; }
}

/* Below the smallest phones the pill needs to shed its padding too. */
@media (max-width: 400px) {
  .lp-stats { gap: 8px; }
  .lp-stats strong { font-size: 19px; }
  .lp-stats > span > span { font-size: 11px; }
  .lp-bar-wrap { padding: 12px 4vw 0; }
  .lp-pill-nav { padding: 7px 7px 7px 12px; gap: 8px; }
  .lp-btn { padding: 9px 13px; font-size: 13px; }
}

/* ---- Account menu ------------------------------------------------------- */
.acct-menu { position: relative; }

.acct-trigger {
  cursor: pointer; user-select: none; list-style: none;
  display: flex; align-items: center; gap: 9px;
  padding: 5px 10px 5px 6px;
  border: 1px solid var(--border-strong); border-radius: 999px;
}
.acct-trigger::-webkit-details-marker { display: none; }
.acct-trigger:hover { background: var(--surface-hover); }
.acct-trigger:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.acct-avatar {
  width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0;
  background: var(--accent-solid); color: var(--on-accent);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700;
}
.acct-name { font-size: 13px; font-weight: 600; }
.acct-caret { font-size: 10px; color: var(--text-muted); }

.acct-panel {
  position: absolute; right: 0; top: 44px; z-index: 50; min-width: 210px;
  background: var(--surface-hover); border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg); padding: 6px;
  box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18);
  display: flex; flex-direction: column;
}
.acct-head { padding: 8px 10px; border-bottom: 1px solid var(--border); margin-bottom: 4px; }
.acct-head-name { font-size: 13.5px; font-weight: 600; }
.acct-head-meta { font-size: 11px; color: var(--text-muted); word-break: break-word; }

.acct-item {
  display: block; width: 100%; text-align: left;
  padding: 7px 10px; border-radius: var(--radius); border: none; background: none;
  font-family: var(--font-sans); font-size: 13px; font-weight: 500;
  color: var(--text-primary); cursor: pointer;
}
.acct-item:hover { background: var(--border); color: var(--text-primary); }
.acct-item.is-disabled { color: var(--text-muted); cursor: not-allowed; }
.acct-item.is-disabled:hover { background: none; }
.acct-item.is-logout { color: var(--accent); font-weight: 600; }
.acct-panel form { margin: 0; }

.acct-divider { border-top: 1px solid var(--border); margin: 4px 0; }

/* The name is the first thing to go when the bar gets tight; the avatar alone
   still identifies who is signed in. */
@media (max-width: 900px) {
  .acct-name { display: none; }
}

/* The admin console's avatar is a rounded square, not a circle — the design
   uses the shape to tell the two consoles apart at a glance. */
.acct-avatar.is-square { border-radius: var(--radius); width: 30px; height: 30px; font-size: 12px; }
.app-bar-admin { border-bottom: 2px solid var(--accent-solid); }

/* ---- Coming soon: placeholder map --------------------------------------- */
.soon-head { display: flex; align-items: center; gap: 12px; margin: 30px 0 10px; }
.soon-rule { flex: 1; height: 1px; background: var(--border); }
.soon-head .sample-badge { margin-left: 0; }

.soon-panel {
  border: 1px dashed var(--border-strong); border-radius: var(--radius-lg);
  padding: 18px; background: var(--tint-soon);
}

.map {
  position: relative; height: 260px; border-radius: 8px;
  background: var(--surface-hover); border: 1px solid var(--border);
  overflow: hidden;
}
.map-grid {
  position: absolute; inset: 0; opacity: 0.75;
  background-image:
    linear-gradient(var(--border) 1px, transparent 1px),
    linear-gradient(90deg, var(--border) 1px, transparent 1px);
  background-size: 44px 44px;
}
.map-caption {
  position: absolute; left: 8px; bottom: 8px;
  font-family: var(--font-sans); font-size: 10px; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.04em;
}

.map-pin {
  position: absolute; transform: translate(-50%, -100%);
  display: flex; flex-direction: column; align-items: center; gap: 3px;
}
.map-pin-label {
  font-size: 10px; font-weight: 700; white-space: nowrap;
  background: var(--surface-raised); border: 1px solid var(--border-strong);
  border-radius: 4px; padding: 1px 5px; color: var(--text-primary);
}
.map-pin-dot {
  width: 9px; height: 9px; border-radius: 50%;
  box-shadow: 0 0 0 2px var(--surface-raised);
}
/* Offline is a hollow ring in the tables, where it sits beside text that
   explains it. On the map a pin has to be a solid mark or it reads as absent. */
.map-pin-dot.state-offline { background: var(--border-strong); }

/* ---- Mobile navigation -------------------------------------------------- */
/* The sidebar is hidden below 900px, so without this there is no way to move
   between sections on a phone at all. */
.m-nav { display: none; position: relative; }
.m-nav-trigger {
  cursor: pointer; user-select: none; list-style: none;
  width: 34px; height: 34px; display: flex; align-items: center;
  justify-content: center; font-size: 16px; line-height: 1;
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  color: var(--text-primary);
}
.m-nav-trigger::-webkit-details-marker { display: none; }
.m-nav-trigger:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.m-nav-items {
  position: absolute; left: 0; top: 42px; z-index: 60; min-width: 190px;
  background: var(--surface-raised); border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg); padding: 6px;
  box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18);
}
/* The sidebar's own nav colours are for a dark panel; this one sits on a light
   surface, so it uses the ordinary text tokens. */
.m-nav-items a { color: var(--text-secondary); padding: 8px 12px; }
.m-nav-items a:hover { background: var(--surface-hover); color: var(--text-primary); }
.m-nav-items a[aria-current="page"] { background: var(--accent-subtle); color: var(--accent-subtle-fg); }
.m-nav-items .app-nav-soon { color: var(--text-muted); }

@media (max-width: 900px) {
  .m-nav { display: inline-block; }

  /* Wide tables scroll rather than compress. Squeezing six columns into a phone
     made every cell wrap to three lines and pushed the actions column out of
     reach entirely. */
  .panel { overflow-x: auto; }
  .tbl { min-width: 680px; }
}

/* ---- Brand wordmark ----------------------------------------------------- */
/* Artwork rather than the CSS mark plus text it replaced. Sized by height so it
   scales with the surrounding type rather than to a fixed pixel width. */
.brand-logo { display: block; height: 26px; width: auto; }
/* The sidebar has 176px of usable width and the mark was using 69px of it.
   34px tall puts the wordmark at ~106px, still leaving room for the CMS tag. */
.app-brand .brand-logo { height: 34px; }
.lp-pill-nav .brand-logo { height: 24px; }
.lp-foot .brand-logo { height: 22px; }

/* ---- Restored: lost when the landing block was rewritten ----------------- */
/* These sat between the landing and account-menu sections and were removed by
   a slice-and-replace edit that used those two comments as boundaries. */

/* Dashboard: tinted cards and the section heading */
.stat-card.is-playing { background: var(--tint-playing); }
.stat-card.is-error { background: var(--tint-error); }
.panel.is-storage { background: var(--tint-storage); }
.section-title {
  font-family: var(--font-sans); font-size: 11px; letter-spacing: 0.06em;
  font-weight: 700; color: var(--text-primary); text-transform: uppercase;
}

/* The badge itself, not just its margin override in .soon-head. */
.sample-badge {
  margin-left: auto; font-family: var(--font-sans); font-size: 9.5px;
  letter-spacing: 0.06em; padding: 2px 6px; border: 1px dashed var(--border-strong);
  border-radius: 4px; color: var(--text-muted); text-transform: uppercase;
}

/* Dashboard: proof of play */
.pop-chart { display: flex; align-items: flex-end; gap: 7px; height: 88px; }
.pop-bar {
  flex: 1; background: var(--border); border-radius: 3px 3px 0 0; min-height: 2px;
}
.pop-bar.is-peak { background: var(--accent-solid); }
.pop-axis {
  display: flex; justify-content: space-between; margin-top: 8px;
  font-family: var(--font-sans); font-size: 10px; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.04em;
}
.pop-total { font-size: 12.5px; color: var(--text-secondary); margin-top: 10px; }

/* Screenshot request form */
.shot-form { margin-top: 4px; }
.shot-count {
  padding: 8px 10px; border: 1px solid var(--border-strong);
  border-radius: var(--radius); background: var(--surface-page);
  color: var(--text-primary); font-family: var(--font-sans); font-size: 13.5px;
}

/* Landing */
.lp-lede-wide { max-width: 620px; }

/* Client sidebar: the dark panel. Only the client shell — the admin console
   keeps the light sidebar its own design specifies, and both share .app-side. */
.app-side-dark { background: var(--sidebar-bg); }
.app-side-dark .app-brand-name { color: var(--sidebar-text-strong); }
.app-side-dark .app-brand-tag { color: var(--sidebar-tag); }
/* :not() excludes the current page — this selector has the same specificity as
   the aria-current rule and comes later, so without it the active item loses
   its dark-on-lilac contrast and washes out. */
.app-side-dark .app-nav a:not([aria-current="page"]),
.app-side-dark .app-nav-soon { color: var(--sidebar-text); }
.app-side-dark .app-nav a:not([aria-current="page"]):hover {
  background: var(--sidebar-hover); color: var(--sidebar-text-strong);
}
.app-side-dark .app-side-foot { border-top-color: rgba(255, 255, 255, 0.12); }
.app-side-dark .app-storage-label { color: #FBFBFB; }
.app-side-dark .app-storage-bar { background: rgba(255, 255, 255, 0.18); }

/* --- Schedule form ------------------------------------------------------- */
/* The design puts the form and a live "what this will do" panel side by side,
   so the consequences of a selection are visible before saving rather than
   discovered after. */

.sched-cols {
  display: grid; grid-template-columns: 1.35fr 1fr; gap: 28px; align-items: start;
}

/* The same surface the tables' data section sits on, so the schedule form and
   its sidebar read as one material with the rest of the app rather than as bare
   white panels. */
.sched-card, .sched-aside > .card { background: var(--surface-sunken); }

.sched-card { display: flex; flex-direction: column; gap: 20px; }

.sched-aside { display: flex; flex-direction: column; gap: 16px; }

/* The pickers sit on that surface, so they take the raised one to separate
   from it — the same relationship inputs have to the card everywhere else. */
.sched-card .panel { background: var(--surface-raised); }

/* The small letter-spaced section labels the design uses throughout. The
   design's monospace face was dropped in the font pass, so these match
   .tbl-mono and use the sans stack. */
.sched-label {
  font-family: var(--font-sans); font-size: 11px; letter-spacing: 0.05em;
  color: var(--text-secondary); margin-bottom: 7px;
}

.sched-sub { font-size: 12px; color: var(--text-muted); margin-bottom: 5px; }

.sched-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

.sched-check {
  display: flex; align-items: center; gap: 9px; font-size: 13.5px;
  cursor: pointer; color: var(--text-primary); margin-top: 12px;
}

.sched-foot {
  display: flex; gap: 10px; justify-content: flex-end;
  border-top: 1px solid var(--border); padding-top: 18px;
}

/* A bordered box holding the chosen chips with the search inline, rather than
   a separate "add" button. */
.token-box {
  background: var(--surface-raised); border: 1px solid var(--border-strong);
  border-radius: 8px; padding: 10px;
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
}

.token-box .multi-select-chips { display: contents; }

.token-search {
  flex: 1; min-width: 120px; background: none; border: none; outline: none;
  font-family: var(--font-sans); font-size: 13.5px; color: var(--text-primary);
  padding: 4px 2px;
}

.chip-mono {
  font-family: var(--font-sans); font-size: 11px; font-weight: 500;
  border-radius: 5px; padding: 4px 6px 4px 8px;
}

.multi-select-nomatch {
  padding: 10px; font-size: 13px; color: var(--text-muted);
}

/* Live summary rows in the sidebar. */
.sum-row {
  display: flex; justify-content: space-between; gap: 12px;
  font-size: 13.5px; padding: 5px 0;
}

.sum-row span { color: var(--text-secondary); }
.sum-row strong { text-align: right; }

.sum-screen {
  display: flex; align-items: center; gap: 9px; padding: 9px 0;
  border-bottom: 1px solid var(--border);
}

.sum-screen:last-child { border-bottom: none; }
.sum-screen-name { flex: 1; font-size: 13.5px; font-weight: 600; }

.sum-screen-tag {
  font-family: var(--font-sans); font-size: 10px; color: var(--text-secondary);
}

.sum-dot {
  width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
  background: var(--cyan);
}

/* Reached, but nothing in the schedule it can play — the one orientation case
   the operator has to be told about. */
.sum-dot.is-stranded { background: var(--danger); }

.sum-empty { padding: 10px 0; font-size: 13px; }

@media (max-width: 1000px) {
  .sched-cols { grid-template-columns: 1fr; }
}

/* Breadcrumb above the page title, as in the schedule design. */
.page-crumb {
  font-size: 13px; color: var(--text-muted); margin-bottom: 4px;
  display: flex; align-items: center; gap: 8px;
}

.page-head-actions {
  margin-left: auto; display: flex; align-items: center; gap: 10px;
}

/* The schedule form's own inputs. The shared rule is scoped to `.field input`
   and lists types explicitly, so this form's date, time and bare text inputs
   matched nothing and rendered as unstyled browser defaults. */
.sched-card input[type="text"],
.sched-card input[type="date"],
.sched-card input[type="time"],
.sched-card select,
.sched-card .flatpickr-visible {
  width: 100%; box-sizing: border-box; background: var(--surface-raised);
  border: 1px solid var(--border-strong); border-radius: 8px;
  padding: 10px 12px; font-family: var(--font-sans); font-size: 14px;
  color: var(--text-primary);
}

.sched-card input:focus-visible,
.sched-card select:focus-visible,
.sched-card .flatpickr-visible:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent);
}

/* Replacing the native inputs took their calendar and clock affordances with
   them, so the field no longer looked like something you could open. flatpickr
   builds the visible input itself, which leaves no element to hang an icon off
   — hence a background image rather than a pseudo-element or a wrapper the
   controller would then have to clean up on destroy.

   #616467 is --text-muted resolved to sRGB: a data URI cannot read a custom
   property. The app is light-mode only, so it has one value to track.

   Selected as `input.flatpickr-visible` rather than `.flatpickr-visible`: the
   field flatpickr builds is a text input, so the shared `input[type="text"]`
   rule above matches it too and would win the padding on specificity. */
.sched-card input.flatpickr-visible {
  padding-right: 38px;
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 16px 16px;
}

.sched-card input.flatpickr-visible.is-date {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23616467' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2'/%3E%3Cpath d='M16 2v4M8 2v4M3 10h18'/%3E%3C/svg%3E");
}

.sched-card input.flatpickr-visible.is-time {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23616467' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3 2'/%3E%3C/svg%3E");
}


/* Daily / Weekdays / Weekends / Custom. The radio is hidden and the label
   carries the selected state, so the control reads as a segmented switch. */
.preset-row { display: flex; flex-wrap: wrap; gap: 8px; }

.preset input { position: absolute; opacity: 0; pointer-events: none; }

.preset span {
  display: inline-block; cursor: pointer; user-select: none;
  padding: 7px 14px; border-radius: 99px; font-size: 13px; font-weight: 600;
  border: 1px solid var(--border-strong); color: var(--text-secondary);
  background: var(--surface-raised);
}

.preset input:checked + span {
  background: var(--accent); border-color: var(--accent); color: #fff;
}

.preset span:hover { border-color: var(--accent); }

/* The round M T W T F S S toggles. */
.day-dots { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }

.day-dot { position: relative; cursor: pointer; }

.day-dot input { position: absolute; opacity: 0; pointer-events: none; }

.day-dot span[aria-hidden] {
  display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 50%;
  border: 1px solid var(--border-strong); background: var(--surface-raised);
  font-size: 13px; font-weight: 600; color: var(--text-secondary);
  user-select: none;
}

.day-dot input:checked + span[aria-hidden] {
  background: var(--accent); border-color: var(--accent); color: #fff;
}

.day-dot input:focus-visible + span[aria-hidden] {
  outline: 2px solid var(--accent); outline-offset: 2px;
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* flatpickr, tinted to the app's accent rather than its own blue. */
.flatpickr-day.selected,
.flatpickr-day.selected:hover,
.flatpickr-day.startRange,
.flatpickr-day.endRange {
  background: var(--accent); border-color: var(--accent);
}

.flatpickr-calendar { font-family: var(--font-sans); }

/* An invalid date pair, marked while the operator is still on the field. The
   model still refuses it — this only moves the moment they find out. */
.field-error {
  display: block; margin-top: 6px; font-size: 12px; color: var(--danger);
}

.sched-card input.flatpickr-visible.is-invalid {
  border-color: var(--danger);
}
