:root {
    --brand: #0047ff;
    --brand-dark: #05225c;
    --accent: #00c2ff;
    --bg: #f4f6fb;
    --card: #ffffff;
    --text: #1a1a2e;
    --muted: #6b7280;
    --border: #e3e6ef;
    --success: #1c8a4b;
    --danger: #c62828;
    font-family: 'Segoe UI', Arial, sans-serif;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    direction: rtl;
}

/* ---------------------------------------------------------------------------
   The header.

   Three columns - nav, logo, actions - so the logo sits in the TRUE centre of
   the bar. Centring it with flex or auto margins would put it in the middle of
   whatever space the side items leave over, so it would shift every time a
   link was added or an unread badge appeared. `1fr auto 1fr` centres the middle
   cell on the header itself and lets the sides hold anything.
   --------------------------------------------------------------------------- */
.topbar {
    background: linear-gradient(135deg, var(--brand-dark), var(--brand));
    color: #fff;
    padding: 10px 20px;
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 12px;
    position: relative;
}

.topbar-logo-link { justify-self: center; display: block; line-height: 0; }
.topbar-logo { height: 34px; width: auto; display: block; }

.topbar-nav { justify-self: start; }
.topbar-actions { justify-self: end; display: flex; align-items: center; gap: 12px; }

.nav-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    align-items: center;
    gap: 4px;
}
.nav-list a {
    display: block;
    color: #fff;
    text-decoration: none;
    font-size: 14px;
    padding: 8px 12px;
    border-radius: 6px;
    white-space: nowrap;
    opacity: .85;
    transition: background .15s ease, opacity .15s ease;
}
.nav-list a:hover { opacity: 1; background: rgba(255,255,255,.12); }
/* The current page is marked, not just hoverable: a menu that looks identical
   everywhere leaves a customer with no idea where they are. */
.nav-list a.is-active { opacity: 1; background: rgba(255,255,255,.2); font-weight: 600; }

.nav-toggle { display: none; }

.bell {
    position: relative;
    display: block;
    padding: 6px;
    border-radius: 6px;
    color: #fff;
    line-height: 0;
    opacity: .85;
}
.bell:hover, .bell.is-active { opacity: 1; background: rgba(255,255,255,.15); }
.bell svg { width: 22px; height: 22px; fill: currentColor; display: block; }
.bell .badge {
    position: absolute;
    top: -2px;
    inset-inline-end: -2px;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    border-radius: 9px;
    background: #d93025;
    color: #fff;
    font-size: 11px;
    line-height: 17px;
    text-align: center;
    font-weight: 700;
}

.topbar form { margin: 0; }
.btn-logout {
    background: rgba(255,255,255,.15);
    color: #fff;
    border: 1px solid rgba(255,255,255,.4);
    padding: 6px 14px;
    border-radius: 6px;
    cursor: pointer;
    white-space: nowrap;
    transition: background .15s ease;
}
.btn-logout:hover { background: rgba(255,255,255,.25); }

.topbar button:focus-visible,
.btn:focus-visible,
.nav-list a:focus-visible,
.bell:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* The page's own title, which used to live in the header. It belongs to the
   page: with the logo in the middle of the bar there is nowhere sensible to put
   it up there, and a heading inside the page is where a reader looks for it. */
.page-head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 10px 16px;
    margin: 0 0 16px;
}
.page-head h1 { font-size: 20px; margin: 0; }
.page-head .page-back { font-size: 14px; }

/* --- phones ---------------------------------------------------------------
   The links collapse behind one button. The logo stays exactly where it is,
   because the grid's middle column does not care what the sides contain. */
@media (max-width: 760px) {
    .topbar { padding: 8px 12px; gap: 8px; }
    .topbar-logo { height: 28px; }

    .nav-toggle {
        display: flex;
        align-items: center;
        gap: 8px;
        background: rgba(255,255,255,.15);
        color: #fff;
        border: 1px solid rgba(255,255,255,.4);
        border-radius: 6px;
        padding: 7px 10px;
        cursor: pointer;
        font: inherit;
        font-size: 14px;
    }
    .nav-toggle-bars {
        width: 16px;
        height: 2px;
        background: currentColor;
        box-shadow: 0 5px 0 currentColor, 0 -5px 0 currentColor;
    }
    .nav-toggle-text { display: none; }

    .nav-list {
        display: none;
        position: absolute;
        top: 100%;
        inset-inline-start: 8px;
        z-index: 30;
        flex-direction: column;
        align-items: stretch;
        gap: 2px;
        min-width: 190px;
        padding: 6px;
        border-radius: 10px;
        background: var(--brand-dark);
        box-shadow: 0 10px 24px rgba(0,0,0,.35);
    }
    .nav-list.is-open { display: flex; }
    .nav-list a { padding: 11px 14px; font-size: 15px; }

    .btn-logout { padding: 7px 10px; font-size: 14px; }
}

/* Narrower still: the word on the logout button is the first thing to go, but
   never the button itself - signing out has to stay one tap away. */
@media (max-width: 380px) {
    .topbar { padding: 8px; }
    .topbar-logo { height: 24px; }
    .topbar-actions { gap: 6px; }
}

/* Small count/label chip - unread notifications in the top bar, "new" on a
   notification row. */
.badge {
    display: inline-block;
    min-width: 20px;
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--accent);
    color: var(--brand-dark);
    font-size: 12px;
    font-weight: 700;
    text-align: center;
}

.container { max-width: 960px; margin: 32px auto; padding: 0 16px; }

.card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 20px;
    margin-bottom: 20px;
    box-shadow: 0 1px 2px rgba(0,0,0,.03);
}

.card h2 { margin-top: 0; font-size: 17px; }
.card h3 { font-size: 15px; margin: 0 0 10px; }

.login-wrap {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
}
/* max-width, not width: a fixed 340px overflows a 320px phone in both
   directions, because the wrapper centres it. */
.login-card { width: 100%; max-width: 340px; }


label { display: block; font-size: 14px; margin: 10px 0 4px; color: var(--muted); }
input[type=text], input[type=email], input[type=password], input[type=file],
input[type=datetime-local], input[type=number], input[type=search], select, textarea {
    width: 100%;
    padding: 9px 10px;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 14px;
    font-family: inherit;
}
textarea { resize: vertical; }

input:focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--brand);
    box-shadow: 0 0 0 3px rgba(0,71,255,.12);
}

.btn {
    display: inline-block;
    background: var(--brand);
    color: #fff;
    border: none;
    padding: 10px 18px;
    border-radius: 6px;
    cursor: pointer;
    font-size: 14px;
    margin-top: 12px;
    transition: background .15s ease, transform .05s ease;
}
.btn:hover { background: var(--brand-dark); }
.btn:active { transform: translateY(1px); }

/* A link styled as a button still carries the browser's underline and the
   surrounding text's size, which made the playlist link look like a stray
   hyperlink sitting between real buttons. */
a.btn { text-decoration: none; line-height: normal; }
a.btn:hover { text-decoration: none; }

/* Secondary / destructive variants for the per-screen controls, so the one
   button that changes what the public sees doesn't look like the one that
   just reloads a picture. */
.btn-secondary {
    background: #fff;
    color: var(--brand);
    border: 1px solid var(--brand);
}
.btn-secondary:hover { background: #eef2ff; color: var(--brand-dark); }

.btn-danger { background: var(--danger); }
.btn-danger:hover { background: #8e1f1f; }


.error { color: var(--danger); font-size: 14px; margin-top: 8px; }
.success { color: var(--success); font-size: 14px; margin-top: 8px; }
.meta { color: var(--muted); font-size: 13px; }

table { width: 100%; border-collapse: collapse; font-size: 14px; }
th, td { text-align: right; padding: 8px 6px; border-bottom: 1px solid var(--border); }
th { color: var(--muted); font-weight: 600; }

.status-pill {
    display: inline-block;
    padding: 2px 10px;
    font-weight: 600;
    border-radius: 999px;
    font-size: 12px;
}
.status-live { background: #e3f6e9; color: var(--success); }
.status-pending { background: #fff4e0; color: #a06a00; }
.status-failed { background: #fdeaea; color: var(--danger); }
.status-removed { background: #eef0f5; color: var(--muted); }

/* "What is this screen doing right now" block inside each screen's card:
   connection state, a picture of what is on it, and the controls that act on
   it. */
.screen-state {
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 14px;
    margin: 14px 0 18px;
    background: #fafbff;
}
.screen-state-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}

/* The preview window. Small on purpose: a customer with several screens is
   comparing them side by side, so each one gets a postcard rather than the
   full width of the page. */
.screen-preview-row {
    display: flex;
    gap: 16px;
    align-items: flex-start;
    flex-wrap: wrap;
    margin-bottom: 12px;
}
.screen-preview {
    position: relative;
    flex: 0 0 320px;
    max-width: 100%;
    background: #0d1117;
    border-radius: 6px;
    overflow: hidden;
}
.screen-preview-stage {
    position: absolute;
    inset: 0;
}
.screen-preview-stage.hidden { display: none; }
/* Each zone sits where it sits on the real screen, in percentages, so the
   window is a scale model rather than a list of pictures. */
.screen-preview-zone {
    position: absolute;
    overflow: hidden;
    background: #000;
}
.screen-preview-media {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
    background: #000;
}
.screen-preview-shot {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    background: #000;
}
.screen-preview-shot.hidden { display: none; }
.screen-preview-empty {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 12px;
    color: #c9d1d9;
    font-size: 13px;
}
.screen-preview-empty.hidden { display: none; }
.screen-preview-facts {
    flex: 1 1 220px;
    min-width: 200px;
}
.screen-preview-facts p { margin: 0 0 8px; }

@media (max-width: 560px) {
    .screen-preview { flex-basis: 100%; }
}

/* Any table wide enough to overflow scrolls inside its own card instead of
   pushing the whole page sideways. */
.table-wrap { overflow-x: auto; }
.table-wrap table { min-width: 480px; }

.screen-actions {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    align-items: center;
}
.screen-actions form { margin: 0; }

.notification-list { list-style: none; margin: 16px 0 0; padding: 0; }
.notification {
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 12px 14px;
    margin-bottom: 10px;
    background: #fff;
}
/* Severity paints the bar; unread adds the tint and wins the bar when both
   apply. These used to be four rules at equal specificity, so source order
   decided - and an unread warning lost its unread marker entirely. */
.notification-info { border-right: 4px solid var(--muted); }
.notification-warning { border-right: 4px solid #a06a00; }
.notification-success { border-right: 4px solid var(--success); }
.notification-error { border-right: 4px solid #c62828; }
.notification.notification-unread { border-right-color: var(--brand); background: #f7f9ff; }
.notification-read { opacity: .75; }
.notification-body {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 4px;
}
.notification-message { font-size: 14px; }

.radio-row { display: flex; gap: 18px; margin-top: 8px; }
.radio-row label { display: flex; align-items: center; gap: 6px; font-size: 14px; color: var(--text); margin: 0; }
.hidden { display: none; }

/* Playlist page: one row per item, with the duration editable in place. The
   table scrolls horizontally on a phone rather than squeezing the columns. */
.playlist-table-wrap { overflow-x: auto; margin-top: 14px; }
/* min-width is what makes the wrapper actually scroll on a phone - without it
   the table just squeezes until the action buttons fall off the edge. */
.playlist-table { width: 100%; min-width: 540px; border-collapse: collapse; font-size: 14px; }
.playlist-table th,
.playlist-table td {
  text-align: right;
  padding: 10px 8px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.playlist-table th { font-size: 13px; color: var(--muted); font-weight: 600; }
.playlist-table tbody tr:last-child td { border-bottom: none; }
.playlist-position { color: var(--muted); width: 58px; }
.playlist-name { word-break: break-word; max-width: 280px; }
.playlist-empty { margin-top: 14px; }
.playlist-duration-form { display: flex; align-items: center; gap: 6px; margin: 0 0 4px; }
.playlist-duration-input { width: 78px; margin: 0; padding: 6px 8px; }
.playlist-table form { margin: 0; }
.btn-small { padding: 6px 12px; font-size: 13px; }


/* On a phone the row does not fit side by side, and a horizontally scrolling
   table hides the remove button off the edge with no hint that it is there.
   Below 640px each row becomes its own small card instead, with the column
   headings carried along as labels. */
@media (max-width: 640px) {
  .playlist-table { min-width: 0; }
  .playlist-table thead { display: none; }
  .playlist-table,
  .playlist-table tbody,
  .playlist-table tr,
  .playlist-table td { display: block; width: 100%; }
  .playlist-table tr {
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 10px 12px;
    margin-bottom: 10px;
  }
  .playlist-table td { border-bottom: none; padding: 4px 0; }
  .playlist-table td[data-label]::before {
    content: attr(data-label) ': ';
    color: var(--muted);
    font-size: 13px;
  }
  .playlist-name { max-width: none; font-weight: 600; }
  .playlist-position { width: auto; }
}

/* Zone editor: a scaled picture of the screen with draggable boxes on it, and
   an editing panel beside it. The canvas holds its aspect ratio from an inline
   style, so a portrait screen is edited as a portrait rectangle rather than a
   squashed landscape one. */
.container-wide { max-width: 1200px; }

.zone-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin: 14px 0 12px;
}
.zone-toolbar .btn { margin-top: 0; }
.zone-toolbar-sep { width: 1px; align-self: stretch; background: var(--border); margin: 0 4px; }

/* The panel comes first in the document, so on this RTL page it sits on the
   right and the canvas fills what is left. */
.zone-editor { display: flex; gap: 20px; align-items: flex-start; flex-wrap: wrap; }
.zone-side { flex: 0 0 320px; max-width: 100%; }
.zone-stage-wrap { flex: 1 1 420px; min-width: 0; }

/* Rulers and canvas share one grid so the ticks line up with the canvas edges
   at any page width. */
.zone-stage {
  display: grid;
  grid-template-columns: 34px 1fr;
  grid-template-rows: 20px 1fr;
  /* Explicitly left-to-right. The page is RTL, so grid column 1 was the RIGHT
     edge - which put the "left" ruler on the right of the canvas, with its
     labels pinned to the edge furthest from the rows they measure. The canvas
     is a picture of a screen and its coordinates start at the left, so the
     whole stage reads left-to-right regardless of the page. */
  direction: ltr;
}
.zone-ruler-corner { grid-column: 1; grid-row: 1; }
.zone-ruler { position: relative; color: var(--muted); font-size: 10px; }
.zone-ruler-top { grid-column: 2; grid-row: 1; }
.zone-ruler-left { grid-column: 1; grid-row: 2; }
.zone-tick { position: absolute; white-space: nowrap; }
.zone-ruler-top .zone-tick { top: 2px; transform: translateX(-50%); }
/* Zero has nothing to its left to overhang into. */
.zone-ruler-top .zone-tick-start { transform: translateX(0); }
.zone-ruler-left .zone-tick-start { transform: translateY(0); }
.zone-ruler-top .zone-tick::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -4px;
  width: 1px;
  height: 4px;
  background: var(--border);
}
/* Against the canvas edge, so a label sits beside the row it measures. */
.zone-ruler-left .zone-tick { right: 4px; transform: translateY(-50%); }
.zone-ruler-top .zone-tick-end { transform: translateX(-100%); }
.zone-ruler-left .zone-tick-end { transform: translateY(-100%); }

.zone-canvas {
  grid-column: 2;
  grid-row: 2;
  position: relative;
  width: 100%;
  background: #0d1117;
  border-radius: 6px;
  overflow: hidden;
  /* Stops the browser panning the page when a finger drags a zone. */
  touch-action: none;
  user-select: none;
}
.zone-box {
  position: absolute;
  border: 2px solid rgba(255, 255, 255, .45);
  background: rgba(255, 255, 255, .10);
  cursor: move;
  box-sizing: border-box;
  min-width: 8px;
  min-height: 8px;
}
/* What is actually playing inside a zone.
   A rectangle labelled "אזור 1" says where a zone is but nothing about what is
   in it, and the whole reason to split a screen is to place content. Each box
   replays its own zone's playlist, so the canvas shows the wall.
   Never a pointer target: the box underneath is what gets dragged. */
.zone-box-media {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}
.zone-box-media img,
.zone-box-media video {
  width: 100%;
  height: 100%;
  /* contain, not cover: a zone the customer sized wrongly for its content
     should LOOK wrong here, the same way it will on the wall. */
  object-fit: contain;
  display: block;
  background: #000;
}
.zone-box-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4px;
  text-align: center;
  font-size: 11px;
  color: rgba(255, 255, 255, .55);
}

/* The selected zone is the bright one. The reverse - dimming the others - read
   as "this one is disabled" rather than "this one is selected". */
.zone-box-selected {
  border-color: var(--accent);
  background: rgba(0, 194, 255, .28);
  box-shadow: 0 0 0 2px rgba(0, 194, 255, .35);
  z-index: 2;
}
.zone-box-label,
.zone-box-size {
  position: absolute;
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .85);
  pointer-events: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.zone-box-label { top: 4px; right: 6px; max-width: calc(100% - 24px); }
/* Clear of the resize grip in the same corner - the two used to sit on top of
   each other and the size read as "1280x10". */
.zone-box-size { bottom: 4px; right: 24px; opacity: .8; font-weight: 400; }

/* Bottom-RIGHT. The drag anchors the zone's top-left corner and adds the
   pointer's movement to its size, so the grip has to be on the corner that
   actually grows: on the bottom-left it shrank the box when dragged left and
   grew it out of the opposite edge when dragged right. */
.zone-handle {
  position: absolute;
  right: -1px;
  bottom: -1px;
  width: 18px;
  height: 18px;
  background: #fff;
  border: 2px solid var(--brand);
  border-radius: 3px;
  cursor: nwse-resize;
}

.zone-hint { margin-top: 12px; }
.zone-warning { margin: 8px 0 0; }
.zone-count { margin-right: 12px; }

.zone-list { margin: 0; }
.zone-row {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 8px;
  cursor: pointer;
}
.zone-row-selected { border-color: var(--brand); background: #f7f9ff; }
.zone-row-head { display: flex; align-items: flex-end; gap: 10px; }
.zone-row-head .zone-field-name { flex: 1 1 auto; }
.zone-row .btn { margin-top: 0; }
.zone-row-fields { display: flex; gap: 8px; margin-top: 8px; }
.zone-field { display: block; font-size: 12px; color: var(--muted); margin: 0; }
.zone-field input { width: 100%; margin-top: 2px; padding: 6px 8px; }
.zone-row-fields .zone-field { flex: 1 1 0; min-width: 0; }

@media (max-width: 900px) {
  .zone-side { flex: 1 1 100%; }
  .zone-stage-wrap { flex: 1 1 100%; }
}

/* Zone tabs on the playlist page - only rendered when a screen is actually
   split, so a plain screen keeps the simpler page it had before. */
.zone-tabs {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin: 12px 0 4px;
}
.zone-tab {
  display: inline-block;
  padding: 6px 14px;
  border: 1px solid var(--brand);
  border-radius: 999px;
  color: var(--brand);
  text-decoration: none;
  font-size: 13px;
  font-weight: 600;
}
.zone-tab:hover { background: #eef2ff; }
.zone-tab-active { background: var(--brand); color: #fff; }

/* Groups of screens. */
.group-members { display: flex; flex-wrap: wrap; gap: 10px 18px; margin: 6px 0 4px; }
.group-member {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  color: var(--text);
  margin: 0;
}
.group-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
  margin: 16px 0 4px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.group-actions form { margin: 0; }
.group-rename { display: flex; gap: 6px; align-items: center; }
.group-rename input { width: 200px; margin: 0; padding: 6px 10px; }
.group-upload-heading { margin-top: 18px; }

/* Right-click menu on a screen card. Positioned in viewport coordinates, so it
   is fixed rather than absolute. */
.quick-menu-hint { margin: 0 0 14px; }
.quick-menu {
  position: fixed;
  z-index: 50;
  min-width: 210px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, .14);
  padding: 6px;
}
.quick-menu-title {
  font-size: 12px;
  color: var(--muted);
  padding: 6px 10px 8px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 4px;
  font-weight: 600;
}
.quick-menu-item {
  display: block;
  width: 100%;
  text-align: right;
  background: none;
  border: none;
  border-radius: 6px;
  padding: 9px 10px;
  font-size: 14px;
  font-family: inherit;
  color: var(--text);
  text-decoration: none;
  cursor: pointer;
}
.quick-menu-item:hover { background: #eef2ff; color: var(--brand-dark); }
.quick-menu-danger { color: var(--danger); }
.quick-menu-danger:hover { background: #fdeaea; color: var(--danger); }

/* Playlist reorder buttons sit one above the other in their own column. */
.playlist-order { white-space: nowrap; }
.playlist-order form { display: inline-block; margin: 0 0 4px; }
.playlist-order .btn { margin-top: 0; }
.playlist-order .btn[disabled] { opacity: .4; cursor: default; }

/* The one upload panel on the dashboard. The screen checkboxes are chips
   rather than a plain list, because a customer with a dozen screens is
   scanning for names, not reading down a column. */
.upload-card { border-color: var(--brand); }
.upload-targets {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 10px;
  margin: 6px 0 4px;
}
.upload-target {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 7px 12px;
  font-size: 14px;
  color: var(--text);
  background: #f5f5f7;
  border: 1px solid var(--border, #ddd);
  border-radius: 999px;
  cursor: pointer;
}
/* The checked chip has to read as checked at a glance. It used to be a hair
   LIGHTER than an unchecked one, so on a single-screen dashboard - where the
   only chip ships pre-ticked - selected and unselected looked identical. */
.upload-target:has(input:checked) {
  border-color: var(--brand);
  background: #eaf0ff;
  font-weight: 600;
}
.upload-target input { margin: 0; }
.upload-target-actions {
  display: flex;
  gap: 8px;
  margin: 4px 0 2px;
}

/* The admin's customer switcher. Deliberately plain and at the top of the
   page: it changes what everything below it means, so it should read as a
   setting rather than as one more control among the screen buttons. */
.admin-scope { border-color: #6b7280; }
.admin-scope-form {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 6px;
}
.admin-scope-form label { margin: 0; }
.admin-scope-form select { width: auto; min-width: 220px; margin: 0; }

/* The text editor. Two hundred fields is a lot of page, so each row shows what
   the built-in wording is and whether this one has been changed - otherwise an
   admin cannot tell their own edits from the defaults. */
.settings-group h2 { margin-top: 0; }
.settings-row {
    padding: 10px 0;
    border-bottom: 1px solid var(--border, #eee);
}
.settings-row:last-child { border-bottom: none; }
.settings-row label { display: block; margin-bottom: 4px; }
.settings-row-changed label { font-weight: 600; }
.settings-badge {
    display: inline-block;
    margin-inline-start: 6px;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    background: #fff4e5;
    color: #a06a00;
}
.settings-default {
    margin: 4px 0 0;
    font-size: 12px;
    opacity: 0.75;
    word-break: break-word;
}
.settings-save {
    position: sticky;
    bottom: 0;
    z-index: 2;
}

/* Per-item scheduling. Collapsed by default: most items play always, and two
   date pickers on every row would bury the running order the page is for. */
.playlist-schedule details > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}
.playlist-schedule details > summary::-webkit-details-marker { display: none; }
.playlist-schedule .link-like {
  color: #1a6fd4;
  text-decoration: underline;
  font-size: 0.85rem;
}
.playlist-schedule-form {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 8px;
  max-width: 240px;
}
.playlist-schedule-form label { font-size: 0.8rem; }
/* A datetime-local is wider than its content on a phone and pushes the table
   sideways; the table's own overflow container would then scroll for a reason
   nobody can see. */
.playlist-schedule-form input { max-width: 100%; }

/* The mark above the sign-in form. Sized by width so it scales down on a phone
   instead of pushing the password field off the screen. */
.login-logo {
    display: block;
    width: min(240px, 70%);
    height: auto;
    margin: 4px auto 18px;
}

/* Reordering arrows. Sized to the 44px touch target a thumb needs - the text
   buttons they replaced were 28px tall, which on a phone meant hitting "move
   down" when you meant "move up" on the row below. */
.playlist-order { display: flex; gap: 6px; align-items: center; }
.btn-arrow {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: #fff;
    color: var(--brand-dark);
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease;
}
.btn-arrow svg { width: 20px; height: 20px; fill: currentColor; display: block; }
.btn-arrow:hover:not(:disabled) { background: #eef3fb; border-color: var(--brand-dark); }
.btn-arrow:disabled { opacity: .3; cursor: default; }
.btn-arrow:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The one-time password link. Loud on purpose: it is shown exactly once and
   the admin has to notice it before navigating away. */
.setup-link-card { border-color: #1c8a4b; }
.setup-link-row { display: flex; gap: 8px; align-items: center; margin: 10px 0; }
.setup-link-row input {
    flex: 1;
    min-width: 0;
    font-family: ui-monospace, Menlo, Consolas, monospace;
    font-size: 13px;
}
.inline-form { display: flex; gap: 6px; align-items: center; margin: 0; }
.inline-form input { margin: 0; }

/* How much space a customer has left. A bar rather than a number, because
   "340 MB" means nothing without knowing what it is out of. */
.storage-bar {
    height: 10px;
    border-radius: 5px;
    background: var(--border);
    overflow: hidden;
    margin: 8px 0 6px;
}
.storage-bar > span { display: block; height: 100%; background: var(--brand); border-radius: 5px; }
.storage-bar.is-nearly-full > span { background: #e8a33d; }
.storage-bar.is-full > span { background: var(--danger); }

/* The new-customer guide. Collapsed by default - it is read once by each
   person and then only when something has gone wrong. */
.onboarding-guide > summary { cursor: pointer; list-style: none; }
.onboarding-guide > summary::-webkit-details-marker { display: none; }
.onboarding-guide > summary::after { content: ' ▾'; color: var(--muted); }
.onboarding-guide[open] > summary::after { content: ' ▴'; }
.onboarding-steps { margin: 12px 0 0; padding-inline-start: 22px; line-height: 1.9; }
.onboarding-steps li { margin-bottom: 4px; }

/* The "you are looking as somebody else" bar. Deliberately loud and above
   everything: the only real danger of the feature is an admin forgetting. */
.impersonation-bar {
    background: #b3540a;
    color: #fff;
    padding: 8px 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    flex-wrap: wrap;
    font-size: 14px;
}
.impersonation-bar form { margin: 0; }
.impersonation-bar button {
    background: rgba(255,255,255,.2);
    color: #fff;
    border: 1px solid rgba(255,255,255,.6);
    padding: 5px 12px;
    border-radius: 6px;
    cursor: pointer;
    font: inherit;
    white-space: nowrap;
}
.impersonation-bar button:hover { background: rgba(255,255,255,.32); }

/* The customer table. Wide on purpose - it is the one place the whole business
   is visible at once, and squeezing it into the standard column would defeat
   that. */
.customers-table { min-width: 1000px; }
.customers-table td { vertical-align: top; }
.customers-table .storage-bar { max-width: 160px; }
.screen-line { display: flex; align-items: center; gap: 6px; font-size: 13px; margin-top: 3px; }
.dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.dot-on { background: var(--success); }
.dot-off { background: var(--muted); }
.dot-missing { background: var(--danger); }
.customers-actions { display: flex; flex-direction: column; gap: 6px; }
.customers-actions form { margin: 0; }
.customers-actions .btn { text-align: center; text-decoration: none; white-space: nowrap; }

/* System state. Three facts side by side, because the question is always
   "is it working" and never "read me a paragraph". */
.health-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 16px;
    margin: 12px 0;
}

/* --- the help page ------------------------------------------------------- */
/* Deliberately plain. It is a page somebody reads top to bottom while
   something is going wrong, so the only thing worth styling is the reading. */
.help-intro { max-width: 58ch; margin: 0 0 18px; }
.help-list { margin: 0 0 12px; padding-inline-start: 22px; }
.help-list li { margin-bottom: 8px; line-height: 1.55; }
.card > p { line-height: 1.6; max-width: 68ch; }
.card h3 { margin-top: 20px; }
.card h3:first-of-type { margin-top: 16px; }

/* --- two-factor ---------------------------------------------------------- */
/* The secret and the recovery codes are read off the screen and typed or
   copied by hand, once. Monospace and generous spacing are the whole design:
   a mistaken 0 for O here costs somebody their account. */
.totp-secret {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 19px; letter-spacing: 2px; background: #f4f6fb;
  border: 1px solid var(--line, #dde3ee); border-radius: 8px;
  padding: 12px 14px; margin: 8px 0 14px; user-select: all;
}
.recovery-codes {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  list-style: none; padding: 12px 14px; margin: 10px 0 14px;
  background: #f4f6fb; border: 1px solid var(--line, #dde3ee); border-radius: 8px;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 6px 18px;
}
.recovery-codes li { user-select: all; }
.twofactor-form { margin: 12px 0; }
.twofactor-form input[type=text] { max-width: 220px; }

/* Restore is folded away on purpose: needed almost never, and destructive. */
.restore-panel { margin-top: 18px; border-top: 1px solid var(--line, #dde3ee); padding-top: 12px; }
.restore-panel > summary { cursor: pointer; font-weight: 600; color: var(--danger); }
.restore-panel input[type=text] { max-width: 220px; }
