/* ScreenSign — admin design system.
   The subject is screens: a wall of remote panels someone has to keep alive. So the panel is the
   object on the page (true orientation, live thumbnail, state written on it), and everything around
   it stays quiet — hairlines instead of shadows, one accent, two radii, no decoration.
   Palette is taken from the ScreenSign logo: brass on warm white, near-black wordmark. */

:root {
  /* brand */
  --brand:#bb9862;          /* the logo's brass — marks, selection, fills */
  --brand-deep:#8a6522;     /* the same hue at AA contrast — accent text, primary buttons */
  --brand-tint:#faf6ef;
  --brand-line:#e7d9c0;

  /* ink & ground (warm neutrals, so the brass never reads as a stray colour) */
  --ink:#1c1b19; --ink-2:#3a372f; --muted:#5f5c55; --faint:#7a746b;
  --paper:#fff; --wash:#f6f5f3; --wash-2:#efedea; --wash-3:#e9e6e1;
  --line:#e7e4df; --line-2:#d9d5ce;

  /* screen states — each one also gets a word and an icon, never colour alone */
  --live:#186c3c;  --live-tint:#e8f4ed;  --live-line:#bfdfcd;
  --down:#b23b32;  --down-tint:#fbecea;  --down-line:#f0cdc9;
  --wait:#93641a;  --wait-tint:#fbf3e3;  --wait-line:#ecdcb8;
  --rest:#5b6673;  --rest-tint:#eef1f4;  --rest-line:#d5dce3;

  --r-xs:7px; --r-sm:10px; --r:13px; --r-lg:17px; --r-xl:22px;
  --sh-1:0 1px 2px rgba(28,27,25,.05);
  --sh-2:0 1px 3px rgba(28,27,25,.08), 0 12px 30px -14px rgba(28,27,25,.32);
  --sh-3:0 24px 60px -20px rgba(28,27,25,.34), 0 2px 8px rgba(28,27,25,.08);
  --side:250px;
  --fast:.14s cubic-bezier(.32,.72,0,1);
  --panel-bg:#15161a;       /* what an unlit screen looks like */
}

*, *::before, *::after { box-sizing:border-box; margin:0; padding:0; }
html { -webkit-text-size-adjust:100%; }
body {
  background:var(--wash); color:var(--ink); min-height:100vh; font-size:16px; line-height:1.45;
  font-family:'IBM Plex Sans Hebrew','Heebo',system-ui,-apple-system,'Segoe UI','Noto Sans Hebrew',Arial,sans-serif;
  font-feature-settings:'tnum' 0; -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
}
[hidden] { display:none !important; }
a { color:var(--brand-deep); text-underline-offset:3px; }
:focus-visible { outline:2px solid var(--brand-deep); outline-offset:2px; border-radius:4px; }
::selection { background:var(--brand-tint); }
@media (prefers-reduced-motion:reduce) { *, *::before, *::after { animation-duration:.01ms !important; transition-duration:.01ms !important; } }

/* ---------- icons: one family, 24px box, 1.6 stroke, currentColor ---------- */
.i { width:20px; height:20px; flex:0 0 auto; stroke:currentColor; fill:none; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round; }
.i.sm { width:16px; height:16px; stroke-width:1.75; }
.i.lg { width:26px; height:26px; stroke-width:1.5; }

/* ---------- form primitives ---------- */
button, input, select, textarea { font:inherit; color:inherit; }
input, select, textarea {
  width:100%; min-height:42px; padding:9px 12px; background:var(--paper); color:var(--ink);
  border:1px solid var(--line-2); border-radius:var(--r-sm); transition:border-color var(--fast), box-shadow var(--fast);
}
input::placeholder, textarea::placeholder { color:var(--faint); }
input:hover, select:hover, textarea:hover { border-color:#c6c1b9; }
input:focus, select:focus, textarea:focus { outline:0; border-color:var(--brand-deep); box-shadow:0 0 0 3px rgba(138,101,34,.14); }
input:disabled, select:disabled, textarea:disabled { background:var(--wash-2); color:var(--muted); border-color:var(--line); cursor:not-allowed; }
textarea { min-height:92px; resize:vertical; line-height:1.5; }
select { appearance:none; padding-inline-end:32px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236e6a64' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-size:16px; background-position:left 10px center; }
input[type="color"] { padding:3px; height:42px; cursor:pointer; }
input[type="time"], input[type="date"], input[type="number"], input[type="url"], input[type="email"], input[type="tel"] { direction:ltr; text-align:left; font-variant-numeric:tabular-nums; }
input[type="checkbox"] { width:18px; height:18px; min-height:0; accent-color:var(--brand-deep); margin-inline-end:8px; vertical-align:-3px; }
label { display:block; font-size:13px; font-weight:500; color:var(--muted); margin-bottom:5px; letter-spacing:.005em; }
.field { margin-bottom:14px; }
.row { display:flex; gap:12px; align-items:end; flex-wrap:wrap; }
.row > * { flex:1; min-width:130px; }
.row > .auto { flex:0 0 auto; min-width:0; }

/* ---------- a picker you can type into: same field, a searchable list under it ---------- */
.combo { position:relative; }
.combo-ctl { position:relative; display:flex; align-items:center; }
.combo-ctl > .i { position:absolute; inset-inline-start:11px; color:var(--faint); pointer-events:none; }
.combo-in { padding-inline-start:35px; padding-inline-end:40px; text-overflow:ellipsis; }
.combo-x { position:absolute; inset-inline-end:5px; display:inline-flex; align-items:center; justify-content:center;
  width:32px; height:32px; border:0; border-radius:50%; background:transparent; color:var(--faint); cursor:pointer; }
.combo-x:hover { background:var(--wash-2); color:var(--ink); }
.combo-list { position:absolute; z-index:20; inset-inline-start:0; inset-inline-end:0; top:calc(100% + 6px);
  max-height:min(44vh, 320px); overflow-y:auto; -webkit-overflow-scrolling:touch; list-style:none; padding:4px;
  background:var(--paper); border:1px solid var(--line-2); border-radius:var(--r-sm); box-shadow:var(--sh-2); }
.combo.up .combo-list { top:auto; bottom:calc(100% + 6px); }
.combo-list li { display:flex; align-items:baseline; gap:8px; padding:10px; border-radius:var(--r-xs); cursor:pointer; line-height:1.3; }
.combo-list li b { font-weight:600; min-width:0; overflow-wrap:anywhere; }
.combo-list li span { color:var(--muted); font-size:13.5px; }
.combo-list li em { margin-inline-start:auto; color:var(--faint); font-size:12.5px; font-style:normal; white-space:nowrap; }
.combo-list li.blank { color:var(--muted); }
.combo-list li.act { background:var(--wash-2); }
.combo-list li.on { background:var(--brand-tint); color:var(--brand-deep); }
.combo-list li.on.act { box-shadow:inset 0 0 0 1px var(--brand-line); }
.combo-none { padding:16px 10px; color:var(--muted); text-align:center; cursor:default; }
.rowacts { white-space:nowrap; display:flex; gap:6px; justify-content:flex-end; }
@media (max-width:560px) { .rowacts { flex-direction:column; align-items:stretch; } }

/* ---------- price list (Shimi, 16/09/2026) ----------
   Found by looking at 375px, not by reading: the action cell was `white-space:nowrap`, so the
   input and the Save button sat on one unbreakable line wider than the column — and the button
   was clipped off the edge of the card. A save button you cannot see is a feature that does not
   exist on a phone, which is the device this admin is used from.

   So the actions wrap instead of overflowing, and below 560px the row stops pretending to be a
   three-column table: the name gets the full width and the controls sit under it. */
.pr-tbl { width:100%; border-collapse:collapse; }
.pr-tbl th, .pr-tbl td { padding:8px 6px; vertical-align:top; border-bottom:1px solid var(--line-2); }
.pr-act { display:flex; flex-wrap:wrap; align-items:center; gap:6px; }
.pr-in { width:110px; min-width:90px; }
.pr-name .meta { margin-top:2px; }
@media (max-width:560px) {
  .pr-tbl thead { display:none; }                 /* the headers repeat what each row already says */
  .pr-tbl, .pr-tbl tbody, .pr-tbl tr, .pr-tbl td { display:block; width:auto; }
  .pr-tbl tr { padding:10px 0; border-bottom:1px solid var(--line-2); }
  .pr-tbl td { border:0; padding:2px 0; }
  .pr-in { flex:1 1 120px; }
  .pr-act .btn { min-height:40px; }               /* a finger, not a cursor */
}

/* ---------- buttons ---------- */
.btn {
  display:inline-flex; align-items:center; justify-content:center; gap:7px; min-height:42px; padding:9px 16px;
  border:1px solid transparent; border-radius:var(--r-sm); background:var(--brand-deep); color:#fff;
  font-weight:600; font-size:15px; letter-spacing:.005em; cursor:pointer; white-space:nowrap; text-decoration:none;
  transition:background var(--fast), border-color var(--fast), transform var(--fast), box-shadow var(--fast);
}
.btn:hover { background:#75551c; }
.btn:active { transform:scale(.985); }
.btn.ghost { background:var(--paper); color:var(--ink); border-color:var(--line-2); box-shadow:var(--sh-1); }
.btn.ghost:hover { background:var(--wash); border-color:#c6c1b9; }
.btn.quiet { background:transparent; color:var(--ink-2); border-color:transparent; box-shadow:none; font-weight:500; }
.btn.quiet:hover { background:var(--wash-2); }
.btn.danger { background:var(--paper); color:var(--down); border-color:var(--down-line); box-shadow:var(--sh-1); }
.btn.danger:hover { background:var(--down-tint); }
.btn.warn { background:var(--wait); color:#fff; }
.btn.warn:hover { background:#7d5514; }
.btn.sm { min-height:34px; padding:5px 12px; font-size:14px; border-radius:var(--r-xs); }
/* A full-width button spans its card, so a long label wraps onto a second line instead of being
   cut off. The Portuguese for the passkey button is 48 characters; the English is 38. */
.btn.block { width:100%; white-space:normal; }
.btn[disabled] { opacity:.45; cursor:not-allowed; transform:none; }
.btn .i { margin-inline-start:-2px; }
.linkish { background:none; border:0; padding:0; font:inherit; color:inherit; cursor:pointer; }

/* ---------- app shell: sidebar on a desktop, top bar + tab bar on a phone ----------
   One DOM, two shapes. `.side` and `.sbar` swap which of them is display:contents so the same
   markup can be a column beside the page or a bar above it - no duplicate ids, no second nav. */
.app { min-height:100vh; }
.side { display:contents; }
.sbar {
  position:sticky; top:0; z-index:30; display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:8px 16px calc(8px + env(safe-area-inset-top)); background:rgba(255,255,255,.86);
  backdrop-filter:saturate(180%) blur(18px); -webkit-backdrop-filter:saturate(180%) blur(18px);
  border-bottom:1px solid var(--line);
}
.lockup { display:flex; align-items:center; gap:9px; min-width:0; }
.lockup .logo { height:34px; width:auto; display:block; }
.lockup .mark { display:none; width:30px; height:29px; flex:0 0 auto; }
.foot { display:flex; align-items:center; gap:9px; min-width:0; }
/* switching customer is how a super starts every task - it sits under the logo, not in a corner */
.switch { display:flex; align-items:center; gap:8px; padding:8px 16px; background:var(--paper); border-bottom:1px solid var(--line); }
.switch label { flex:0 0 auto; margin:0; font-size:13px; font-weight:600; color:var(--muted); }
.switch select { flex:1 1 auto; width:auto; min-width:0; min-height:38px; font-size:14.5px; font-weight:600; border-radius:var(--r-sm); }
.switch .acct { flex:1 1 auto; min-width:0; font-size:14.5px; font-weight:600; color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.main { padding:8px 16px 92px; }
.wrap { max-width:1200px; margin:0 auto; }

/* page header */
.phead { display:flex; align-items:flex-end; justify-content:space-between; gap:14px; flex-wrap:wrap; padding:20px 0 14px; }
.phead h1 { font-size:25px; font-weight:600; letter-spacing:-.02em; line-height:1.15; }
.phead .sub { display:flex; align-items:center; gap:10px; flex-wrap:wrap; font-size:14.5px; color:var(--muted); margin-top:5px; }
.pending { display:inline-flex; align-items:center; gap:5px; font-size:13px; font-weight:600; color:var(--wait);
  background:var(--wait-tint); border:1px solid var(--wait-line); border-radius:99px; padding:2px 10px 2px 8px; }
.pending .i { color:var(--wait); }
.phead .acts { display:flex; gap:8px; align-items:center; flex-wrap:wrap; }

/* publish state */
.pub { display:flex; align-items:center; gap:8px; }
.pub .ver { display:inline-flex; align-items:center; gap:7px; font-size:11.5px; color:var(--muted); text-align:start;
  line-height:1.25; white-space:nowrap; padding:5px 8px; border-radius:var(--r-xs); transition:background var(--fast); }
.pub .ver .i { color:var(--faint); }
button.ver:hover { background:var(--wash-2); }
button.ver:hover .i { color:var(--ink-2); }
.pub .ver b { display:block; font-weight:600; color:var(--ink-2); font-size:12.5px; }
.pub .btn.dirty { background:var(--brand-deep); color:#fff; }
.pub .btn.dirty::before { content:''; width:6px; height:6px; border-radius:50%; background:#fff; opacity:.9; }
.pub .btn.clean { background:transparent; color:var(--muted); border-color:var(--line-2); box-shadow:none; font-weight:500; }
.pub .btn.clean .i { color:var(--live); }

/* tab bar (phone) */
.nav {
  position:fixed; inset-inline:0; bottom:0; z-index:30; display:flex; justify-content:space-around;
  background:rgba(255,255,255,.9); backdrop-filter:saturate(180%) blur(18px); -webkit-backdrop-filter:saturate(180%) blur(18px);
  border-top:1px solid var(--line); padding:5px 4px max(5px, env(safe-area-inset-bottom));
}
.nav button { flex:1; display:flex; flex-direction:column; align-items:center; gap:3px; min-height:50px; padding:6px 2px;
  background:none; border:0; border-radius:var(--r-xs); font-size:11px; font-weight:500; color:var(--muted); cursor:pointer;
  transition:color var(--fast); }
.nav button .i { width:21px; height:21px; flex:0 0 auto; }
/* A label longer than its ~48px of bar wraps, and because the buttons stretch, ONE long label sets
   the height of the whole bar: "Customers - all products" ran to three lines and took 95px of an
   844px phone (Shimi, 10/09/2026, with a photo). Two lines is the ceiling. */
/* ‏🔴 `break-word` does NOT count as a wrap opportunity when the browser computes a flex item's
   min-content width, so the tab kept asking for one long line and the label was cut instead of
   using the second line it is allowed: measured at 390px, „Configuración" rendered 69px of text
   inside a 58px tab. `anywhere` is the one that also shrinks the intrinsic width. Hebrew and
   English fit either way, which is why eight tabs looked fine for a year. */
.nav button span { display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
  line-height:1.15; text-align:center; overflow-wrap:anywhere; hyphens:auto; }
/* An equal split gives every tab the same ~47px whatever its label needs, which is what snapped
   "Customers" in half. Sizing from the content and letting the row shrink proportionally hands the
   long labels the room the short ones do not use. */
@media (max-width:767px) { .nav button { flex:1 1 auto; min-width:0; padding-inline:1px; letter-spacing:-.1px; } }
.nav button.on { color:var(--brand-deep); font-weight:600; }

/* phone: the bar carries the brand, the publish action and a way into history - nothing else */
@media (max-width:767px) {
  .sbar { flex-wrap:wrap; row-gap:8px; }
  .lockup { flex:1 1 auto; }
  .lockup .logo { height:30px; }
  .foot { flex:0 0 auto; margin-inline-start:auto; gap:6px; }
  .pub .ver .vt { display:none; }
  .switch { position:sticky; top:47px; z-index:29; }
}
@media (min-width:768px) {
  .app { display:grid; grid-template-columns:var(--side) 1fr; align-items:start; }
  .side { display:flex; flex-direction:column; gap:2px; position:sticky; top:0; height:100vh; padding:26px 12px 16px;
    background:var(--paper); border-inline-start:1px solid var(--line); overflow:auto; }
  .sbar { display:contents; }
  .side > .langs { order:0; margin:0 4px 14px; }
  .lockup { order:1; justify-content:center; padding:6px 8px 22px; }
  .lockup .logo { height:46px; }
  .nav { position:static; flex-direction:column; justify-content:flex-start; background:none; backdrop-filter:none;
    -webkit-backdrop-filter:none; border:0; padding:0; gap:2px; }
  .nav button { flex:0 0 auto; flex-direction:row; justify-content:flex-start; gap:11px; width:100%; min-height:38px;
    padding:7px 10px; border-radius:var(--r-sm); font-size:14.5px; color:var(--ink-2); }
  .nav button .i { width:19px; height:19px; color:var(--muted); transition:color var(--fast); }
  .nav button:hover { background:var(--wash-2); }
  .nav button.on { background:var(--brand-tint); color:var(--brand-deep); font-weight:600; box-shadow:inset 0 0 0 1px var(--brand-line); }
  .nav button.on .i { color:var(--brand-deep); }
  .cust { order:2; }
  .switch { order:3; flex-direction:column; align-items:stretch; gap:5px; padding:0 4px 14px; background:none; border-bottom:0; }
  .switch label { padding-inline-start:6px; }
  .nav { order:4; }
  .foot { order:5; margin-top:auto; flex-direction:column; align-items:stretch; gap:10px; padding-top:14px; border-top:1px solid var(--line); }
  .foot .pub { flex-direction:column; align-items:stretch; gap:8px; }
  .foot .pub .btn { width:100%; }
  .main { padding:14px 32px 48px; }
  .phead { padding:26px 0 20px; }
  .phead h1 { font-size:30px; }
}
/* ---------- surfaces ---------- */
.card { background:var(--paper); border:1px solid var(--line); border-radius:var(--r-lg); padding:16px 18px; margin-bottom:14px; }
.card h2 { font-size:17px; font-weight:600; letter-spacing:-.01em; margin-bottom:12px; }
.card h3 { font-size:14px; font-weight:600; color:var(--ink-2); margin:18px 0 9px; }
.card.tap { cursor:pointer; transition:border-color var(--fast), box-shadow var(--fast); }
.card.tap:hover { border-color:var(--line-2); box-shadow:var(--sh-1); }

.list-head { display:flex; justify-content:space-between; align-items:center; gap:10px; flex-wrap:wrap; margin:26px 0 12px; }
.list-head:first-child { margin-top:0; }
/* Layout presets, under the layouts list. Wraps on a phone rather than pushing the note off-screen. */
.preset-row { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin:10px 0 4px; }
/* Media folders: the chip row is also the drop target, so it has to look like somewhere a file lands. */
.folder-bar { display:flex; gap:8px; flex-wrap:wrap; margin:14px 0 10px; }
.folder-bar .chip { cursor:pointer; border:1px solid var(--line); background:var(--paper); padding:6px 12px; border-radius:999px; font-size:13.5px; }
.folder-bar .chip .n { margin-inline-start:7px; opacity:.55; font-variant-numeric:tabular-nums; }
.folder-bar .chip.on { background:var(--brand-tint); border-color:var(--brand-line); color:var(--brand-deep); font-weight:600; }
.folder-bar .chip.new { border-style:dashed; color:var(--muted); }
/* an action, not a folder: same pill, but it never looks like something you can drop files on */
.folder-bar .chip.act { color:var(--brand-deep); border-color:var(--brand-line); display:inline-flex; align-items:center; gap:5px; }
.folder-bar .chip.drop-on, .chip.drop-on { background:var(--brand-tint); border-color:var(--brand-deep); box-shadow:0 0 0 2px var(--brand-line); }
.pick-bar { display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin:14px 0 0; padding:10px 12px;
  background:var(--brand-tint); border:1px solid var(--brand-line); border-radius:var(--r-sm); font-size:14px; }
.media-item { position:relative; }
.media-item.picked { outline:2px solid var(--brand-deep); outline-offset:2px; }
.media-item.dragging { opacity:.45; }
/* The tick sits over the thumbnail, big enough for a finger on the phone he runs this from. */
.mpick { position:absolute; inset-block-start:6px; inset-inline-start:6px; z-index:2; display:grid; place-items:center;
  width:30px; height:30px; border-radius:8px; background:rgba(255,255,255,.92); border:1px solid var(--line); cursor:pointer; }
.mpick input { width:17px; height:17px; margin:0; cursor:pointer; }
.preset-row .meta { flex:1 1 12rem; min-width:0; }
.list-head h2 { font-size:20px; font-weight:600; letter-spacing:-.014em; }
.list-head .btns { display:flex; gap:7px; }
/* the licence is full: say so where the add button used to be, instead of hiding it silently */
.phead .acts .cap { max-width:22ch; text-align:start; line-height:1.35; }
/* Picture field: drop a file, click to pick one, or paste a URL underneath. */
.imgfield .imgdrop { display:flex; align-items:center; gap:12px; padding:10px 12px; margin-bottom:8px; cursor:pointer;
  border:1.5px dashed var(--line-2); border-radius:var(--r); background:var(--wash); transition:border-color var(--fast), background var(--fast); }
.imgfield .imgdrop:hover, .imgfield .imgdrop:focus-visible { border-color:var(--brand); background:var(--brand-tint); outline:none; }
.imgfield .imgdrop.over { border-color:var(--brand-deep); background:var(--brand-tint); }
.imgfield .imgdrop.busy { opacity:.6; pointer-events:none; }
/* A locked Save needs a reason on screen, or it reads as a broken button. The form says what it is
   waiting for while a picture is on its way up (Pablo, 15/09/2026 — he saved mid-upload and the old
   address was kept, silently). */
form.img-busy { position:relative; }
form.img-busy::after { content:attr(data-busy-note); display:block; margin-top:8px; font-size:13px;
  color:var(--muted); font-weight:600; }
.imgfield .imgprev { width:56px; height:56px; object-fit:cover; border-radius:var(--r-sm); background:var(--paper); border:1px solid var(--line); flex:0 0 auto; }
.imgfield .imghint { font-size:13px; color:var(--muted); line-height:1.4; }
/* the doctor's one control: three big targets, thumb-sized on a phone */
.statusbtns { display:flex; gap:10px; flex-wrap:wrap; }
.statusbtns .btn { flex:1 1 140px; min-height:52px; font-size:16px; }
.empty-state { text-align:center; color:var(--muted); padding:44px 18px; background:var(--paper); border:1px dashed var(--line-2); border-radius:var(--r-lg); font-size:15px; }
.empty-state b { display:block; color:var(--ink); font-size:16px; font-weight:600; margin-bottom:4px; }
.help { font-size:13.5px; line-height:1.55; color:var(--muted); background:var(--wash-2); border-radius:var(--r-sm); padding:10px 12px; margin:0 0 14px; }
.meta { font-size:14px; color:var(--muted); line-height:1.5; }
/* Numbers used to force direction:ltr + text-align:left, which pushed them to the opposite edge
   from their right-aligned headers and made every column look shifted by one. Digits already
   render left-to-right inside an RTL line, so alignment is all that was needed. */
.num { text-align:start; font-variant-numeric:tabular-nums; }
.err { color:var(--down); font-size:13.5px; min-height:19px; margin:6px 0; }
.ok { color:var(--live); font-size:13.5px; margin:6px 0; }

/* ---------- the screen panel: the one place the design is loud ---------- */
.group-head { display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; margin:26px 0 12px; }
.group-head h2 { font-size:16px; font-weight:600; letter-spacing:-.01em; }
.group-head .gmeta { font-size:13px; color:var(--muted); }
.group-head .sp { flex:1; }

/* ---------- chips & dots (used across the app) ---------- */
.chips { display:flex; gap:6px; flex-wrap:wrap; margin-top:7px; }
.chip { display:inline-flex; align-items:center; gap:4px; font-size:12px; font-weight:500; line-height:1.5; padding:2px 9px;
  border-radius:99px; background:var(--wash-2); color:var(--ink-2); border:1px solid transparent; }
.chip .i { width:13px; height:13px; }
.chip.ok { background:var(--live-tint); color:var(--live); border-color:var(--live-line); }
.chip.bad { background:var(--down-tint); color:var(--down); border-color:var(--down-line); }
.chip.warn { background:var(--wait-tint); color:var(--wait); border-color:var(--wait-line); }
.chip.rest { background:var(--rest-tint); color:var(--rest); border-color:var(--rest-line); }
.chip.src { background:transparent; color:var(--muted); border-color:var(--line-2); }
.mono { font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; font-size:13.5px; color:var(--ink-2); overflow-wrap:anywhere; user-select:all; }
.dot { display:inline-block; width:8px; height:8px; border-radius:50%; background:var(--faint); vertical-align:middle; margin-inline-end:6px; }
.dot.on { background:var(--live); box-shadow:0 0 0 3px rgba(28,127,71,.16); }
/* The same dot, told to carry a state. `.on` answers "is a device online"; a calendar is not
   online or offline but healthy, stale or broken, and without these three the dot stayed the
   default grey and the colour said nothing at all. Colour is never alone — the word is beside it. */
.dot.is-live { background:var(--live); box-shadow:0 0 0 3px rgba(24,108,60,.16); }
.dot.is-wait { background:var(--wait); box-shadow:0 0 0 3px rgba(147,100,26,.16); }
.dot.is-down { background:var(--down); box-shadow:0 0 0 3px rgba(178,59,50,.16); }

/* ---------- emergency broadcast: an operational alarm, not a card ---------- */
.bcast { background:var(--paper); border:1px solid var(--line); border-radius:var(--r-lg); margin-bottom:14px; overflow:hidden; }
.bcast > details > summary { display:flex; align-items:center; gap:10px; padding:13px 16px; cursor:pointer; list-style:none; font-size:14.5px; color:var(--ink-2); }
.bcast > details > summary::-webkit-details-marker { display:none; }
.bcast > details > summary .i { color:var(--down); }
.bcast > details > summary b { font-weight:600; color:var(--ink); }
.bcast > details > summary:hover { background:var(--wash); }
.bcast > details[open] > summary { border-bottom:1px solid var(--line); }
.bcast .inner { padding:14px 16px 16px; }
.bcast-on { border-color:var(--down-line); background:var(--down-tint); }
.bcast-row { display:flex; gap:12px; align-items:center; justify-content:space-between; flex-wrap:wrap; padding:12px 14px; }
.bcast-row .bmain { min-width:0; flex:1 1 240px; }
.bcast-row + .bcast-row { border-top:1px solid var(--down-line); }
.bcast-row .hd { display:flex; align-items:center; gap:8px; font-weight:600; color:var(--down); font-size:14.5px; }
.bcast-msg { margin:6px 0 2px; font-size:15px; color:var(--ink); }

/* ---------- pills / segmented control ---------- */
.pills { display:flex; gap:4px; flex-wrap:wrap; padding:3px; background:var(--wash-2); border-radius:var(--r-sm); }
.pills button { flex:1; min-height:34px; padding:0 12px; border:0; border-radius:var(--r-xs); background:transparent; color:var(--ink-2);
  font-size:14px; font-weight:500; cursor:pointer; transition:background var(--fast), color var(--fast); }
.pills button:hover { color:var(--ink); }
.pills button.on { background:var(--paper); color:var(--ink); font-weight:600; box-shadow:var(--sh-1); }
.pills.sm button { min-height:34px; font-size:13.5px; flex:0 0 auto; }
/* A choice a free demo licence does not include. DISABLED and still on screen: a choice that
   disappears teaches the customer the product cannot do it, a choice they can see but not take
   teaches them what upgrading opens. Dimmed rather than struck through — it is not an error. */
.pills button.locked { opacity:.42; cursor:not-allowed; }
.pills button.locked:hover { color:var(--muted); }
/* The sentence under the control. It borrows `.note` for its shape, and only the icon colour is
   changed: `.note .i` is amber because a note is usually a warning, and this is not one — nothing
   went wrong, the customer is simply on a smaller licence. */
.note.demo-lock .i { color:var(--muted); }

/* ---------- media library ---------- */
.media-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(158px, 1fr)); gap:12px; }
.media-item { background:var(--paper); border:1px solid var(--line); border-radius:var(--r); overflow:hidden; cursor:pointer;
  transition:border-color var(--fast), box-shadow var(--fast); }
.media-item:hover { border-color:var(--line-2); box-shadow:var(--sh-1); }
.media-item.sel { border-color:var(--brand-deep); box-shadow:0 0 0 2px rgba(138,101,34,.2); }
.media-item .th { height:104px; background:var(--panel-bg); display:flex; align-items:center; justify-content:center; color:#5c626c; overflow:hidden; }
.media-item .th img { width:100%; height:100%; object-fit:cover; }
.media-item .nm { font-size:12.5px; padding:8px 9px 2px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; direction:ltr; text-align:start; }
.media-item .in { font-size:11.5px; color:var(--muted); padding:0 9px 8px; display:flex; justify-content:space-between; gap:6px; }
.bar { height:6px; background:var(--wash-3); border-radius:99px; overflow:hidden; margin:8px 0; }
.bar > i { display:block; height:100%; background:var(--brand-deep); border-radius:99px; transition:width .3s ease; }
.bar.warn > i { background:var(--wait); }
.upl { display:flex; align-items:center; gap:12px; font-size:13.5px; padding:5px 0; }
.upl .bar { flex:1; margin:0; }

/* ---------- rows inside sheets ---------- */
.item-row { display:flex; gap:11px; align-items:center; padding:10px 0; border-top:1px solid var(--line); flex-wrap:wrap; }
.item-row .th { flex:0 0 62px; width:62px; height:39px; border-radius:var(--r-xs); background:var(--panel-bg); overflow:hidden;
  display:flex; align-items:center; justify-content:center; color:#5c626c; }
.item-row .th img { width:100%; height:100%; object-fit:cover; }
.item-row .nm { flex:1; min-width:120px; font-size:14.5px; }
.item-row .nm small { display:block; color:var(--muted); font-size:12.5px; }
.item-row input[type="number"] { width:78px; min-height:34px; padding:4px 8px; }
.item-row .ib { display:inline-flex; align-items:center; justify-content:center; background:var(--paper); border:1px solid var(--line-2);
  border-radius:var(--r-xs); min-width:34px; min-height:34px; color:var(--ink-2); cursor:pointer; transition:background var(--fast); }
.item-row .ib:hover { background:var(--wash); }
.item-row .adv { flex-basis:100%; display:flex; gap:10px; flex-wrap:wrap; align-items:end; padding:8px 0 2px; }
.item-row .adv > * { flex:1; min-width:110px; }
.item-row .adv .pills { flex-basis:100%; }
.zone-row { display:flex; gap:10px; align-items:center; padding:9px 0; border-top:1px solid var(--line); }
.zone-row .zn { flex:0 0 92px; font-weight:600; font-size:14px; }
.zone-row select { flex:1; }

/* ---------- stats & project cards ---------- */
.stats { display:grid; grid-template-columns:repeat(auto-fit, minmax(150px, 1fr)); gap:12px; margin-bottom:18px; }
.stat { background:var(--paper); border:1px solid var(--line); border-radius:var(--r-lg); padding:15px 16px; }
.stat b { display:block; font-size:28px; font-weight:600; letter-spacing:-.02em; line-height:1.1; font-variant-numeric:tabular-nums; }
.stat span { display:block; font-size:13px; color:var(--muted); margin-top:3px; }
.projgrid { display:grid; grid-template-columns:repeat(auto-fill, minmax(228px, 1fr)); gap:12px; }
.proj { display:flex; flex-direction:column; align-items:flex-start; gap:4px; text-align:start; padding:15px 16px; background:var(--paper);
  border:1px solid var(--line); border-radius:var(--r-lg); cursor:pointer; min-height:78px; transition:border-color var(--fast), box-shadow var(--fast); }
.proj:hover { border-color:var(--line-2); box-shadow:var(--sh-1); }
.proj b { font-size:15.5px; font-weight:600; }

/* ---------- tables ---------- */
table { width:100%; border-collapse:collapse; font-size:14px; }
th { font-size:13px; font-weight:600; color:var(--muted); }
td, th { padding:10px 8px; border-bottom:1px solid var(--line); text-align:start; vertical-align:middle; }
tr:last-child td { border-bottom:0; }
tr.tap { cursor:pointer; } tr.tap:hover { background:var(--wash); }

/* ---------- sheets, toast, login ---------- */
.sheet-bg { position:fixed; inset:0; z-index:60; display:flex; align-items:flex-end; justify-content:center;
  background:rgba(28,27,25,.36); backdrop-filter:blur(3px); -webkit-backdrop-filter:blur(3px); animation:fade .16s ease-out; }
.sheet { background:var(--wash); width:100%; max-width:780px; max-height:94vh; overflow:auto; border-radius:var(--r-xl) var(--r-xl) 0 0;
  padding:8px 16px 32px; box-shadow:var(--sh-3); animation:rise .22s cubic-bezier(.32,.72,0,1); }
.sheet-head { position:sticky; top:0; z-index:2; display:flex; justify-content:space-between; align-items:center; gap:10px;
  margin:0 -16px 12px; padding:12px 16px; background:rgba(246,245,243,.92); backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px);
  border-bottom:1px solid var(--line); }
.sheet-head h2 { font-size:19px; font-weight:600; letter-spacing:-.014em; }
.sheet-head button { display:inline-flex; align-items:center; justify-content:center; background:var(--wash-2); border:0; border-radius:50%;
  min-width:32px; min-height:32px; color:var(--muted); cursor:pointer; transition:background var(--fast), color var(--fast); }
.sheet-head button:hover { background:var(--wash-3); color:var(--ink); }
@keyframes rise { from { transform:translateY(14px); opacity:.4; } to { transform:none; opacity:1; } }
@keyframes fade { from { opacity:0; } to { opacity:1; } }
@media (min-width:720px) { .sheet-bg { align-items:center; padding:20px; } .sheet { border-radius:var(--r-xl); max-height:88vh; } }

.toast { position:fixed; inset-block-end:88px; inset-inline-start:50%; transform:translateX(50%); z-index:80; max-width:90vw;
  background:rgba(28,27,25,.94); color:#fff; padding:11px 18px; border-radius:99px; font-size:14px; font-weight:500;
  box-shadow:var(--sh-3); backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px); animation:rise .2s cubic-bezier(.32,.72,0,1); }
.toast.err { background:rgba(178,59,50,.96); }
@media (min-width:768px) { .toast { inset-block-end:28px; } }

.login { max-width:396px; margin:11vh auto; padding:30px 28px 26px; background:var(--paper); border:1px solid var(--line);
  border-radius:var(--r-xl); box-shadow:var(--sh-2); }
.login .lockup { display:flex; align-items:center; gap:11px; margin-bottom:22px; }
.login .lockup .nm { font-size:17px; font-weight:600; letter-spacing:-.014em; line-height:1.15; }
.login .lockup .nm span { display:block; font-size:11px; font-weight:500; color:var(--faint); letter-spacing:.09em; text-transform:uppercase; }
.login h1 { font-size:21px; font-weight:600; letter-spacing:-.016em; margin-bottom:4px; }
.login p { color:var(--muted); font-size:14px; margin-bottom:20px; line-height:1.5; }
.login .center { text-align:center; margin:16px 0 0; font-size:13.5px; }
/* The answer to „I pressed the fingerprint button and nothing happened". It is guidance, not a
   failure, so it must not wear the red of .err — the person did nothing wrong. */
.login .pk-hint { color:var(--muted); line-height:1.5; margin-top:10px; }
/* Grouped as „483 920 175” since the code went to nine digits — the gaps between groups do the
   separating, so the letter-spacing that used to carry six digits is dialled back, and the size
   gives way on a narrow card instead of running off it. */
.code-box { font-size:clamp(22px, 6.4vw, 31px); font-weight:600; letter-spacing:.1em; direction:ltr; text-align:center; font-variant-numeric:tabular-nums;
  background:var(--brand-tint); color:var(--brand-deep); border:1px solid var(--brand-line); border-radius:var(--r); padding:12px; margin:10px 0; }

.pv-wrap { background:var(--panel-bg); border-radius:var(--r); padding:9px; display:flex; justify-content:center; }
/* ‏🔴 A preview that is always 16:9 is how a customer designs a 6:1 wall blind — and it is how a
   clipped clock reached the JMEDICAL wall looking correct in the admin. --screen-ar carries the
   screen’s real shape when it has one; without it nothing changes. */
.pv { border:0; background:#000; width:100%; aspect-ratio:var(--screen-ar, 16/9); border-radius:var(--r-xs); }
.pv.portrait { width:auto; height:56vh; max-height:520px; aspect-ratio:var(--screen-ar, 9/16); }
.actions { display:flex; gap:9px; flex-wrap:wrap; margin-top:12px; }
.actions .btn { flex:1; }

details > summary { cursor:pointer; user-select:none; }
.hist-row { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:11px 0; border-top:1px solid var(--line); }
.hist-row:first-of-type { border-top:0; }
.hist-row.on { font-weight:600; }

/* ---------- screens toolbar: search, filter, view ---------- */
.toolbar { display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-bottom:16px; }
.tbrow { display:flex; align-items:center; gap:10px; flex:1 1 auto; min-width:0; }
.search { position:relative; flex:1 1 230px; min-width:180px; max-width:340px; display:flex; align-items:center; }
.search .i { position:absolute; inset-inline-start:11px; color:var(--faint); pointer-events:none; }
.search input { padding-inline-start:35px; min-height:38px; border-radius:var(--r-sm); }
.search input::-webkit-search-cancel-button { cursor:pointer; }
.pills.view { flex:0 0 auto; }
.filt-sel { display:none; }
.sel-btn { flex:0 0 auto; }
@media (max-width:660px) {
  .search { flex:1 1 100%; max-width:none; }
  .tbrow { gap:8px; }
  #scFilter { display:none; }
  .filt-sel { display:block; flex:1 1 auto; width:auto; min-height:38px; padding:6px 12px; padding-inline-end:30px;
    border-radius:var(--r-sm); font-size:14px; }
  .sel-btn span { display:none; }
  .sel-btn { min-width:38px; padding:5px 10px; }
  .pills.view button { min-width:36px; }
}
.pills.view button { min-width:38px; padding:0 9px; }
.pills.view button .i { width:17px; height:17px; }

/* selection bar for actions on several screens at once */
.bulk { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-bottom:14px; padding:9px 12px;
  background:var(--brand-tint); border:1px solid var(--brand-line); border-radius:var(--r); }
.bulk .cnt { font-size:14px; font-weight:600; color:var(--brand-deep); margin-inline-end:2px; }
.bulk .mv { display:inline-flex; align-items:center; gap:6px; color:var(--muted); }
.bulk .mv select { min-height:34px; width:auto; font-size:14px; padding:4px 10px; padding-inline-end:28px; border-radius:var(--r-xs); }

/* ---------- the screen panel ---------- */
.screens-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(min(100%, 236px), 1fr)); gap:14px; }
.panel { display:flex; flex-direction:column; text-align:start; background:var(--paper); border:1px solid var(--line);
  border-radius:var(--r-lg); overflow:hidden; cursor:pointer; transition:border-color var(--fast), box-shadow var(--fast), transform var(--fast); }
.panel:hover { border-color:var(--line-2); box-shadow:var(--sh-2); }
.panel:active { transform:scale(.995); }
.panel.picked { border-color:var(--brand); box-shadow:0 0 0 2px rgba(187,152,98,.35); }
/* every card is the same size; the picture inside keeps the screen's real proportion */
.panel .glass { position:relative; aspect-ratio:16/10; background:var(--panel-bg); display:flex; align-items:center; justify-content:center; overflow:hidden; }
.panel .fit { position:relative; width:100%; max-height:100%; aspect-ratio:var(--screen-ar, 16/9); background:#0b0c0f; overflow:hidden;
  display:flex; align-items:center; justify-content:center; box-shadow:0 0 0 1px rgba(255,255,255,.08); }
.panel .fit.portrait { width:auto; height:100%; max-width:100%; aspect-ratio:var(--screen-ar, 9/16); }
.panel .fit img { width:100%; height:100%; object-fit:cover; }
.panel .ph { display:flex; flex-direction:column; align-items:center; gap:7px; padding:8px; text-align:center;
  font-size:12.5px; line-height:1.35; color:#9aa2ad; }
.panel .ph .i { width:26px; height:26px; }
.panel.is-down .fit, .panel.is-rest .fit { filter:grayscale(1) brightness(.5); }

.panel .state { position:absolute; inset-block-start:8px; inset-inline-start:8px; display:inline-flex; align-items:center; gap:5px;
  padding:3px 9px 3px 7px; border-radius:99px; font-size:11.5px; font-weight:600; line-height:1.4;
  background:rgba(16,17,20,.74); color:#fff; backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px); }
.panel .state .i { width:13px; height:13px; stroke-width:2; }
.panel.is-live .state { color:#8ce4ab; } .panel.is-down .state { color:#ffaea5; }
.panel.is-wait .state { color:#f2cd84; } .panel.is-rest .state { color:#c0d0e0; }

.pick { position:absolute; inset-block-start:6px; inset-inline-end:6px; display:inline-flex; align-items:center; justify-content:center;
  width:32px; height:32px; border:0; border-radius:9px; background:rgba(16,17,20,.6); color:#fff; cursor:pointer;
  opacity:0; transition:opacity var(--fast), background var(--fast); backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px); }
/* the visible square is 32px; the tappable area is 44px, which is the number that matters */
.pick::after { content:''; position:absolute; inset:-6px; }
.panel:hover .pick, .panel.picked .pick, .pick:focus-visible, .picking .pick { opacity:1; }
.pick:hover { background:rgba(16,17,20,.85); }
.panel.picked .pick { background:var(--brand-deep); }
#scSelect[aria-pressed="true"] { background:var(--brand-tint); color:var(--brand-deep); }

.panel .body { padding:11px 13px 13px; display:flex; flex-direction:column; gap:2px; }
.panel .nm { font-size:15.5px; font-weight:600; letter-spacing:-.008em; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.panel .where { font-size:13.5px; color:var(--muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* facts wrap rather than clip - a battery reading cut to "1%" is worse than a second line.
   Cards in the same grid row still end level, because grid rows stretch to the tallest card. */
.panel .facts { display:flex; align-items:center; gap:6px 12px; flex-wrap:wrap; margin-top:9px; font-size:13px; color:var(--muted); }
.panel .body { flex:1; }
.panel .facts span { display:inline-flex; align-items:center; gap:4px; white-space:nowrap; }
.panel .facts .i { width:15px; height:15px; color:var(--faint); }
.panel .facts .low, .panel .facts .low .i { color:var(--down); }
.panel .warnrow { display:flex; align-items:center; gap:6px; margin-top:9px; padding-top:9px; border-top:1px solid var(--line);
  font-size:13px; font-weight:500; color:var(--wait); }
.panel .warnrow .i { width:15px; height:15px; }

/* ---------- the same screens as a compact list ---------- */
.srows { background:var(--paper); border:1px solid var(--line); border-radius:var(--r-lg); overflow:hidden; }
.srow { display:flex; align-items:center; gap:12px; padding:11px 14px; cursor:pointer; border-top:1px solid var(--line);
  transition:background var(--fast); }
.srow:first-child { border-top:0; }
.srow:hover { background:var(--wash); }
.srow.picked { background:var(--brand-tint); }
.srow .pick { position:static; opacity:1; width:26px; height:26px; background:transparent; color:var(--faint); border-radius:6px; }
.srow .pick:hover { background:var(--wash-2); color:var(--ink-2); }
.srow.picked .pick { background:transparent; color:var(--brand-deep); }
.srow.shead { padding:9px 14px; background:var(--wash-2); cursor:default; font-size:13px; font-weight:600; color:var(--muted); }
.srow.shead:hover { background:var(--wash-2); }
.srow.shead .nm, .srow.shead .st, .srow.shead .where, .srow.shead .detail, .srow.shead .right { font-size:13px; font-weight:600; color:var(--muted); }
.srow .pick-sp { flex:0 0 26px; }
.srow .st { flex:0 0 132px; display:inline-flex; align-items:center; gap:6px; font-size:13px; font-weight:600; }
.srow .st .i { width:15px; height:15px; }
.srow.is-live .st { color:var(--live); } .srow.is-down .st { color:var(--down); }
.srow.is-wait .st { color:var(--wait); } .srow.is-rest .st { color:var(--rest); }
.srow .nm { flex:1 1 130px; min-width:0; font-size:14.5px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.srow .where { flex:1 1 120px; min-width:0; font-size:13.5px; color:var(--muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.srow .detail { flex:0 1 190px; font-size:13.5px; color:var(--muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.srow .right { flex:0 0 74px; display:inline-flex; align-items:center; justify-content:flex-start; gap:6px; font-size:13.5px; color:var(--muted); font-variant-numeric:tabular-nums; }
@media (max-width:720px) { .srow .where, .srow .detail { display:none; } .srow .st { flex-basis:auto; } .srow .right { flex-basis:auto; } }

/* login lockup */
.login .logo { display:block; height:52px; width:auto; margin:0 0 20px; }
.help .i { vertical-align:-2px; color:var(--wait); margin-inline-end:2px; }
.note { display:flex; align-items:flex-start; gap:7px; margin-top:10px; font-size:13px; line-height:1.5; color:var(--muted); }
.note .i { flex:0 0 auto; margin-top:2px; color:var(--wait); }
/* "Saved" is not "on the screen": a signage change waits for publish. Said next to the Save button,
   because the banner at the top of the page is out of sight while a sheet is open. */
.draftnote { display:flex; align-items:center; gap:9px; flex-wrap:wrap; margin-top:12px; padding:10px 12px;
  border:1px solid var(--wait-line); background:var(--wait-tint); border-radius:var(--r-sm);
  font-size:13px; line-height:1.5; color:var(--ink-2); }
.draftnote .i { flex:0 0 auto; color:var(--wait); }
.draftnote span { flex:1 1 220px; }
.draftnote .btn { flex:0 0 auto; }
/* on a phone this is the action the notice exists for - give it a real tap target */
@media (max-width:660px) { .draftnote .btn { min-height:42px; width:100%; } }
.shot-full { display:block; width:100%; max-height:260px; object-fit:contain; background:var(--panel-bg);
  border-radius:var(--r-sm); margin-top:10px; }
.pv.portrait { height:44vh; }
.bcast-btn .i { color:var(--down); }
.bcast-btn:hover { border-color:var(--down-line); background:var(--down-tint); }

/* phone: the three header actions fit one row without dropping below a 40px tap target */
@media (max-width:660px) {
  .phead { padding:16px 0 12px; }
  .phead h1 { font-size:23px; }
  .phead .acts { gap:6px; }
  .phead .acts .btn { min-height:40px; padding:8px 11px; font-size:14px; gap:5px; }
}

/* language switch: two words, the current one marked - no flags, no dropdown */
/* wrap, not clip: the German for „meeting rooms" is nineteen characters and the row is 217px
   wide. Before 18/09/2026 the four product names were cut off mid-word — a segmented control
   that cannot wrap is a segmented control that lies about what it contains. */
.langs { display:flex; flex-wrap:wrap; gap:2px; padding:3px; background:var(--wash-2); border-radius:var(--r-sm); }
/* Seven languages do not fit one row of equal thirds. `wrap` lets the row become two lines where
   there is room for it (the login card, the settings card); the sidebar uses .lang-sel instead. */
.langs.wrap { flex-wrap:wrap; }
.langs.wrap button { flex:0 1 auto; }
/* The sidebar's language control: one line whatever the number of languages, and it looks like the
   quiet control it is rather than like a form field. */
.lang-sel { width:100%; min-height:34px; padding:5px 10px; padding-inline-end:28px; font-size:13.5px; font-weight:500;
  color:var(--ink-2); background-color:var(--wash-2); border-color:transparent; border-radius:var(--r-sm); }
.lang-sel:hover { color:var(--ink); }
.langs button { flex:1 1 auto; min-height:32px; padding:0 10px; border:0; border-radius:var(--r-xs); background:transparent;
  color:var(--muted); font-size:13.5px; font-weight:500; cursor:pointer; transition:background var(--fast), color var(--fast); }
.langs button:hover { color:var(--ink); }
.langs button.on { background:var(--paper); color:var(--ink); font-weight:600; box-shadow:var(--sh-1); }
.login .langs { margin-top:16px; }
@media (max-width:767px) { .sbar > .langs { display:none; } }   /* the phone bar is tight; the switch lives in settings there */
/* the install page belongs to the device, not to this admin - flag it as leaving */
.appbtn { justify-content:flex-start; width:100%; gap:9px; font-size:14px; color:var(--ink-2); }
.appbtn span { flex:1; text-align:start; }
.appbtn .i:last-child { width:14px; height:14px; color:var(--faint); }
.appbtn:hover { background:var(--wash-2); color:var(--ink); }
@media (max-width:767px) { .foot .appbtn span, .foot .appbtn .i:last-child { display:none; } .foot .appbtn { width:auto; padding:8px 10px; } }

/* content: one tile per item, with the icon saying what kind of thing it is */
.tiles { display:grid; grid-template-columns:repeat(auto-fill, minmax(min(100%, 260px), 1fr)); gap:12px; }
.tile { display:flex; align-items:center; gap:12px; text-align:start; padding:13px 14px; background:var(--paper);
  border:1px solid var(--line); border-radius:var(--r-lg); cursor:pointer; width:100%;
  transition:border-color var(--fast), box-shadow var(--fast); }
.tile:hover { border-color:var(--line-2); box-shadow:var(--sh-1); }
.tile .ti { display:grid; place-items:center; flex:0 0 auto; width:38px; height:38px; border-radius:11px;
  background:var(--brand-tint); border:1px solid var(--brand-line); color:var(--brand-deep); }
.tile .ti .i { width:19px; height:19px; }
.tile .tb { display:flex; flex-direction:column; gap:2px; min-width:0; }
.tile .tb b { font-size:15px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.tile .tb .meta { font-size:13px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }

/* forms and tables read better in a column than stretched across a wide screen */
@media (min-width:1000px) {
  .form-col { max-width:660px; }
}

/* the customer's own logo: their brand under ours, capped so it cannot dominate */
.cust { display:flex; align-items:center; justify-content:center; padding:0 10px 14px; }
.cust img { max-height:40px; max-width:100%; object-fit:contain; }
@media (max-width:767px) { .cust { display:none; } }

/* ---------- door signs: one card per door, answering "who is in that room right now" ---------- */
.doorgrid { display:grid; grid-template-columns:repeat(auto-fill, minmax(min(100%, 250px), 1fr)); gap:12px; margin-bottom:20px; }
.dcard { display:flex; flex-direction:column; align-items:stretch; gap:3px; text-align:start; padding:14px 16px 15px;
  background:var(--paper); border:1px solid var(--line); border-radius:var(--r-lg); cursor:pointer; font:inherit; color:inherit;
  transition:border-color var(--fast), box-shadow var(--fast), transform var(--fast); }
.dcard:hover { border-color:var(--line-2); box-shadow:var(--sh-2); }
.dcard:active { transform:scale(.995); }
.dc-top { display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:6px; }
.dc-room { display:inline-flex; align-items:center; gap:5px; font-size:13px; font-weight:600; color:var(--brand-deep);
  background:var(--brand-tint); border:1px solid var(--brand-line); border-radius:99px; padding:2px 10px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0; }
.dc-room .i { width:14px; height:14px; flex:0 0 auto; }
.dc-net { display:inline-flex; align-items:center; gap:4px; font-size:12.5px; font-weight:600; color:var(--muted); white-space:nowrap; }
.dc-net .i { width:14px; height:14px; }
.dcard.is-live .dc-net { color:var(--live); } .dcard.is-down .dc-net { color:var(--down); }
.dcard.is-wait .dc-net { color:var(--wait); } .dcard.is-rest .dc-net { color:var(--rest); }
.dc-who { font-size:18px; font-weight:600; letter-spacing:-.012em; line-height:1.25; }
.dc-who.empty { color:var(--muted); font-weight:500; }
.dc-sub { font-size:14px; color:var(--muted); }

/* the list of what a publish will push, and what each published version pushed */
.chg { list-style:none; margin:10px 0 0; }
.chg li { position:relative; padding:6px 0 6px 0; padding-inline-start:16px; font-size:14px; line-height:1.5; color:var(--ink-2); }
.chg li + li { border-top:1px solid var(--line); }
.chg li::before { content:""; position:absolute; inset-inline-start:0; top:14px; width:6px; height:6px; border-radius:50%; background:var(--muted); }
.chg li.chg-added::before { background:var(--live); }
.chg li.chg-removed::before { background:var(--down); }
.hist-row .chg { margin-top:6px; }
/* when a door went quiet — the date, under the room's line rather than beside the badge, so a long
   date never pushes the room name out of its own card */
.dc-seen { font-size:12.5px; color:var(--down); opacity:.85; font-variant-numeric:tabular-nums; }
.dc-line { margin-top:8px; font-size:13.5px; color:var(--ink-2); border-top:1px solid var(--line); padding-top:8px; }

/* the weekly rota: a short block per day, so an empty day takes no room at all */
.sday { margin-top:14px; }
.sday h4 { font-size:13px; font-weight:600; color:var(--muted); margin-bottom:5px; }
.srow-lite { display:flex; align-items:center; gap:10px; padding:8px 0; border-top:1px solid var(--line); font-size:14.5px; }
.srow-lite .tm { flex:0 0 108px; font-variant-numeric:tabular-nums; direction:ltr; text-align:start; color:var(--ink-2); }
.srow-lite .who { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.srow-lite .ib { display:inline-flex; align-items:center; justify-content:center; width:32px; height:32px; flex:0 0 auto;
  background:var(--paper); border:1px solid var(--line-2); border-radius:var(--r-xs); color:var(--muted); cursor:pointer; }
.srow-lite .ib:hover { background:var(--down-tint); border-color:var(--down-line); color:var(--down); }

/* who is signed in, and the way out - in the sidebar, where you look for it, not buried in settings */
.me { display:flex; align-items:center; gap:9px; min-width:0; }
.me .mi { display:grid; place-items:center; flex:0 0 auto; width:30px; height:30px; border-radius:50%;
  background:var(--brand-tint); border:1px solid var(--brand-line); color:var(--brand-deep); }
.me .mt { display:flex; flex-direction:column; min-width:0; line-height:1.25; }
.me .mt b { font-size:13.5px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* The role sits under the name and is now truncated the same way the name is: a longer sign-out
   label („Terminar sessão") squeezes this column, and „Proprietário" then spilled out of a 35px box. */
.me .mt > span { font-size:12px; color:var(--muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.me .out { display:inline-flex; align-items:center; justify-content:center; gap:5px; flex:0 0 auto; min-width:34px; height:34px;
  padding:0 8px; margin-inline-start:auto; border-radius:var(--r-xs); font-size:13px; font-weight:500; color:var(--muted);
  transition:background var(--fast), color var(--fast); }
.me .out span { display:none; }   /* the word appears where there is room for it */
@media (min-width:768px) { .me .out span { display:inline; } }
.me .out:hover { background:var(--wash-2); color:var(--down); }
/* the phone bar has room for one more icon, not for a name */
@media (max-width:767px) { .me .mi, .me .mt { display:none; } .me { flex:0 0 auto; } .me .out { margin-inline-start:0; } }
@media (min-width:768px) { .me { padding:2px 4px 10px; } }   /* first in the footer: identity, then the app link, then publish */

/* the world switch: same control as the language one, because it does the same kind of thing -
   it swaps the whole interface, not a setting inside it */
/* A product name can be one long compound — the German for meeting rooms is one 17-letter word,
   and a flex item cannot shrink below its longest word. Without this the 2x2 grid of worlds is
   wider than the sidebar and the last two are cut off (18/09/2026). `hyphens:auto` breaks it at a
   real syllable („Besprechungs-räume") using the engine's dictionary for the page's own lang;
   `manual` was tried first and broke „Besprechungsrä|ume" with no hyphen at all, which reads as a
   rendering fault. `overflow-wrap` is the guarantee for an engine with no dictionary. */
.langs.worlds button { gap:5px; overflow-wrap:anywhere; hyphens:auto; }
.langs.worlds .i { width:15px; height:15px; }
@media (min-width:768px) { .side > .langs.worlds { order:2; margin:0 4px 14px; } .cust { order:3; } .switch { order:4; } .nav { order:5; } .foot { order:6; } }

/* the clinic heading and its settings link read as one line, not as a stray button on the far side */
.group-head .gedit, .group-head .gadd { display:inline-flex; align-items:center; gap:5px; font-size:13px; color:var(--muted); padding:2px 6px; border-radius:var(--r-xs); }
/* adding a door is the point of the clinic heading, so it reads as the action, not as a note */
.group-head .gadd { color:var(--brand-deep); font-weight:600; }
.group-head .gedit:hover { background:var(--wash-2); color:var(--brand-deep); }

/* The welcome message, shown as it will arrive on the phone: wrapped, not a single long line. */
.pre-wrap { white-space:pre-wrap; word-break:break-word; font-family:inherit; font-size:13px; line-height:1.65;
  background:var(--wash); border:1px solid var(--line); border-radius:var(--r-sm); padding:10px 12px; margin-top:8px; color:var(--ink-2); }
/* The handover fields are read, copied and dictated — never typed into. Monospace-ish spacing keeps
   a temporary password legible over the phone, and the whole value selects on the first tap. */
.card input[readonly] { background:var(--wash-2); color:var(--ink); cursor:text; letter-spacing:.02em; }
/* "Stay signed in" sits between the password and the button, so it reads as part of the decision
   to log in rather than as a stray line under it.

   🔴 15/09/2026 — it was there all along and Shimi asked us to build it, which is the only review a
   control ever really gets. It was muted grey, 14px, pulled UP by -2px into the field above and
   with no space of its own: technically present, practically invisible. It now shares a row with
   "שכחתי סיסמה" (the two things you can do at this moment, side by side), sits on real ink, and the
   whole row is one tap target on a phone. */
.login .login-row { display:flex; align-items:center; justify-content:space-between; gap:12px;
  flex-wrap:wrap; margin:16px 0 14px; font-size:14px; }
/* `.err` reserves 19px + margins so the form does not jump when a message appears. Stacked under
   the new row that was a visible hole between "stay signed in" and the button — the reservation is
   only worth paying for once there is something to reserve for. */
.login .err:empty { min-height:0; margin:0; }
.login .login-row a { font-weight:500; white-space:nowrap; }
/* font-size is stated here, not inherited from .login-row: `label {font-size:13px}` is a global rule
   and an element's own rule beats anything it would otherwise inherit, so the row said 14px and the
   label quietly rendered 13px. */
.login .login-check { display:flex; align-items:center; margin:0; color:var(--ink-2); cursor:pointer;
  font-size:14px; font-weight:500; min-height:32px; }
.login .login-check input { flex:0 0 auto; }
.login .login-check span { user-select:none; }

/* ---------- show/hide password (שימי, 15/09/2026) ----------
   The eye sits INSIDE the field, so it reads as part of the input rather than as a stray button
   beside it.

   ⚠️ Geometry, because it is genuinely confusing here and I got it backwards once: the page is RTL,
   but every password input is dir="ltr" (passwords are typed in Latin). So the dots start at the
   LEFT edge of the box and grow rightwards — the free end is the RIGHT, and that is where the eye
   goes, with the matching padding on the right. Using inset-inline-end here would resolve against
   the RTL wrapper and park the button exactly on top of the first characters. Physical `right` is
   the correct property for this one case, not a lapse into non-logical CSS. */
.pw { position:relative; display:flex; align-items:center; }
.pw input { padding-right:44px; padding-left:12px; }
.pw-eye { position:absolute; right:4px; display:inline-flex; align-items:center; justify-content:center;
  width:36px; height:36px; padding:0; border:0; border-radius:50%; background:transparent; color:var(--faint); cursor:pointer; }
.pw-eye:hover { background:var(--wash-2); color:var(--ink); }
.pw-eye:focus-visible { outline:2px solid var(--brand-deep); outline-offset:1px; background:var(--wash-2); color:var(--ink); }
.pw-eye[aria-pressed="true"] { color:var(--brand-deep); }

/* 🖐️ Touch targets, from the audit on 15/09/2026. The eye measured 36×36, "שכחתי סיסמה" 84×20 and
   the checkbox row 32 tall — all fine for a mouse, all under the 44px a finger needs, on a screen
   whose whole point is that Shimi runs it from his phone. Widened only under `pointer: coarse`, so
   the desktop layout keeps its proportions and nothing grows where a cursor is doing the aiming. */
@media (pointer: coarse) {
  .pw-eye { width:44px; height:44px; }
  .pw input { padding-right:52px; }
  .login .login-row a { padding-block:12px; }
  .login .login-check { min-height:44px; }
}

/* Licences: one line per product — name, how many, what each costs. A flat row of number inputs
   made it impossible to tell which price belonged to which product (Pablo, 10/09/2026). */
.lic-grid { display:grid; grid-template-columns:1fr 90px 130px; gap:8px 10px; align-items:center; margin-bottom:12px; }
.lic-grid .lic-h { font-size:12px; font-weight:600; color:var(--muted); letter-spacing:.02em; }
.lic-grid .lic-name { font-size:14px; color:var(--ink); margin:0; }
.lic-grid input { margin:0; }
@media (max-width:560px) { .lic-grid { grid-template-columns:1fr 72px 96px; gap:6px 8px; } .lic-grid .lic-name { font-size:13px; } }

/* ---- worlds: a colour per product ----------------------------------------------
   Four products behind one switch, and until now all four tabs looked identical — the only clue to
   which one you were in was reading the menu below (Shimi, 10/09/2026). Each keeps a fixed pastel:
   the ink is the AA-contrast version of the same hue, so the words stay readable, and the active
   tab is filled and ringed rather than merely tinted. Colour is never the only signal — the tab
   also carries its icon, its label and aria-current. */
:root {
  --w-signage:#e8f0fb; --w-signage-ink:#1e4fa8; --w-signage-line:#c6dbf5;
  --w-doors:#e7f4ec;   --w-doors-ink:#186c3c;   --w-doors-line:#bfdfcd;
  --w-rooms:#fbf3e3;   --w-rooms-ink:#8a5c14;   --w-rooms-line:#ecdcb8;
  --w-queues:#efeafc;  --w-queues-ink:#5b21b6;  --w-queues-line:#dcd0f7;
}
.langs.worlds button.w-signage.on { background:var(--w-signage); color:var(--w-signage-ink); box-shadow:inset 0 0 0 1px var(--w-signage-line); }
.langs.worlds button.w-doors.on   { background:var(--w-doors);   color:var(--w-doors-ink);   box-shadow:inset 0 0 0 1px var(--w-doors-line); }
.langs.worlds button.w-rooms.on   { background:var(--w-rooms);   color:var(--w-rooms-ink);   box-shadow:inset 0 0 0 1px var(--w-rooms-line); }
.langs.worlds button.w-queues.on  { background:var(--w-queues);  color:var(--w-queues-ink);  box-shadow:inset 0 0 0 1px var(--w-queues-line); }
.langs.worlds button.on { font-weight:700; }
.langs.worlds button.on .i { color:currentColor; }
/* a hint of the same hue before it is chosen, so the four are told apart even inactive */
.langs.worlds button.w-signage:not(.on):hover { background:var(--w-signage); }
.langs.worlds button.w-doors:not(.on):hover   { background:var(--w-doors); }
.langs.worlds button.w-rooms:not(.on):hover   { background:var(--w-rooms); }
.langs.worlds button.w-queues:not(.on):hover  { background:var(--w-queues); }

/* the selected page picks up the world's colour too, so the menu belongs to the product above it */
@media (min-width:768px) {
  .nav[data-nav-world="signage"] button.on { background:var(--w-signage); color:var(--w-signage-ink); box-shadow:inset 0 0 0 1px var(--w-signage-line); }
  .nav[data-nav-world="doors"]   button.on { background:var(--w-doors);   color:var(--w-doors-ink);   box-shadow:inset 0 0 0 1px var(--w-doors-line); }
  .nav[data-nav-world="rooms"]   button.on { background:var(--w-rooms);   color:var(--w-rooms-ink);   box-shadow:inset 0 0 0 1px var(--w-rooms-line); }
  .nav[data-nav-world="queues"]  button.on { background:var(--w-queues);  color:var(--w-queues-ink);  box-shadow:inset 0 0 0 1px var(--w-queues-line); }
  .nav[data-nav-world] button.on .i { color:currentColor; }
  /* the account-wide pages drop to the bottom of the column, just above the sign-out block */
  .nav { flex:1 1 auto; }
  .nav-sep { margin-top:auto; padding-top:10px; border-top:1px solid var(--line); }
}
/* On a phone the menu is a bottom bar, so the separator turns on its side: the same grouping, as a
   hairline between the product pages and the account-wide ones. Hiding it is what made two adjacent
   tabs both reading "Customers" look like the same tab twice. */
@media (max-width:767px) {
  .nav-sep { flex:0 0 1px; align-self:center; width:1px; height:26px; margin:0 3px; background:var(--line); }
}

/* ---- the world switch is four items in a control built for two -----------------
   `.langs` is the language toggle: two words, side by side, flex:1 each. Four Hebrew product names
   in a 250px sidebar do not fit that: the labels wrapped mid-word and the last tab was clipped off
   the edge of the sidebar entirely (Shimi, 10/09/2026, with photos). Two by two gives every product
   a whole line, and lets the pastel fill wrap its label instead of sitting behind half of it. */
.langs.worlds { display:grid; grid-template-columns:1fr 1fr; gap:3px; }
/* the base control never made its buttons flex containers - without this the icon simply sits
   inline beside the label and neither the gap nor the column direction does anything */
.langs.worlds button { display:flex; flex:none; flex-direction:column; align-items:center; justify-content:center;
  gap:3px; min-height:46px; padding:6px 4px; font-size:12.5px; line-height:1.15; text-align:center; }
.langs.worlds .i { width:17px; height:17px; flex:0 0 auto; }
@media (max-width:767px) { .langs.worlds { margin:0 16px 8px; } }

/* ---- the free-layout editor -------------------------------------------------
   The preview is the point: four percentage boxes are unreadable as numbers and obvious as a
   picture, and the 16:9 frame is the same shape as the television they describe. */
.lprev { position:relative; width:100%; aspect-ratio:var(--screen-ar, 16/9); border-radius:var(--r-sm); overflow:hidden;
  box-shadow:inset 0 0 0 1px var(--line); }
.lprev.portrait { aspect-ratio:var(--screen-ar, 9/16); max-width:300px; margin-inline:auto; }
/* The label sits on a colour the user picked, which may be anything from black to pale blue, so it
   carries its own dark chip rather than trusting a text-shadow to save it. */
.lz { position:absolute; display:flex; flex-direction:column; align-items:center; justify-content:center;
  padding:2px; overflow:hidden; text-align:center; box-shadow:inset 0 0 0 1px rgba(255,255,255,.55);
  container-type:size; }
/* A 5%-tall strip is about 20px in this preview and the two-line chip is about 32, so the label was
   being sliced through the middle — in the preview whose entire job is to be believed. The zone is
   the container and the chips are its children, which is the one direction a container query works. */
@container (max-height: 34px) { .lz > small { display:none; } }
@container (max-height: 18px) { .lz > span { display:none; } }
.lz > span, .lz > small { color:#fff; background:rgba(17,24,39,.72); padding:1px 6px; max-width:100%;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.lz > span { font-size:12px; font-weight:600; line-height:1.35; border-radius:4px 4px 0 0; }
.lz > small { font-size:10px; font-variant-numeric:tabular-nums; border-radius:0 0 4px 4px; }
.lzrow { border:1px solid var(--line); border-radius:var(--r-sm); padding:10px 12px; margin-bottom:10px; background:var(--wash); }
.lzrow .field { margin-bottom:8px; }

/* ---------- publish state: the first thing in the work area, not the last thing in the sidebar ----------
   Shimi asked for it somewhere obvious (11/09/2026). Two voices: brass when the screens are behind what
   is on this page, one quiet hairline when they are not. Sticky, so scrolling a long list never hides it. */
.pubbar { position:sticky; top:0; z-index:30; display:flex; align-items:center; gap:12px;
  padding:11px clamp(14px, 2.2vw, 22px); border-block-end:1px solid var(--line); }
.pubbar .pi { display:inline-flex; flex:0 0 auto; }
.pubbar .pi .i { width:19px; height:19px; }
.pubbar .pt { display:flex; flex-direction:column; gap:1px; min-width:0; margin-inline-end:auto; }
/* ‏🔴 „veröffentlicht" is 88px of unbreakable word inside a 39px box on a phone, and with overflow
   visible it does not truncate — it runs UNDER the button beside it. Hebrew never showed this,
   because „לא פורסם" is short. Let the long word break rather than escape its box. */
.pubbar .pt b { font-size:14px; font-weight:700; letter-spacing:-.008em; overflow-wrap:anywhere; hyphens:auto; }
.pubbar .pt > span { font-size:12.5px; }
.pubbar .hist { flex:0 0 auto; font-size:12.5px; display:inline-flex; align-items:center; gap:6px; }
.pubbar .btn { flex:0 0 auto; }

/* work waiting to reach the screens */
.pubbar.act { background:var(--brand-deep); color:#fff; border-block-end-color:color-mix(in srgb, var(--brand-deep) 72%, #000); }
/* 🔴 1.4.3 contrast (AA), audit 17/09/2026: this sub-line measured 3.92:1 on the brass bar where
   12.5px text needs 4.5:1 — axe flagged it on every admin view. 78% → 92% white brings it to 4.78:1
   and keeps it secondary to the white line above it. The history link beside it is the same size on
   the same ground and was raised with it (it measured ~4.1:1; axe did not reach it because the
   integrator view this was scanned in does not render it). */
.pubbar.act .pt > span { color:color-mix(in srgb, #fff 92%, var(--brand-deep)); }
.pubbar.act .pi { color:#fff; }
.pubbar.act .hist { color:color-mix(in srgb, #fff 92%, var(--brand-deep)); }
.pubbar.act .hist:hover { color:#fff; }
.pubbar.act .btn.go { background:#fff; color:var(--brand-deep); border-color:#fff; font-weight:700;
  box-shadow:0 1px 2px rgba(0,0,0,.18), 0 6px 16px rgba(0,0,0,.14); }
.pubbar.act .btn.go:hover { background:color-mix(in srgb, #fff 92%, var(--brand)); color:var(--brand-deep); }
.pubbar.act .btn.go .i { color:var(--brand-deep); }

/* everything already on the screens: present, quiet, not shouting */
.pubbar.calm { background:var(--paper); color:var(--ink-2); }
.pubbar.calm .pi { color:var(--live); }
.pubbar.calm .pt > span { color:var(--muted); }
.pubbar.calm .hist { color:var(--muted); }
.pubbar.calm .hist:hover { color:var(--ink); }

@media (max-width: 780px) {
  .pubbar { gap:9px; padding:9px 14px; }
  .pubbar .pt > span { display:none; }          /* the headline alone carries it on a phone */
  .pubbar .hist span { display:none; }
}

/* A help note that is a caution: carried by a tint of its own hue and a hairline, not a bar down one side. */
.help.warn { background:var(--wait-tint); border:1px solid var(--wait-line); color:var(--ink-2); }
.help.warn b { color:var(--wait); }

/* The doctors list carries a face per row. Small enough not to turn a working list into a gallery,
   large enough that a missing one is obvious at a glance (Pablo, 14/09/2026). */
.ppl-photo { width: 46px; }
.ppl-photo img {
  width: 36px; height: 36px; object-fit: cover; border-radius: 50%;
  display: block; background: var(--wash);
}
.ppl-photo .chip.warn { white-space: nowrap; font-size: 11px; }
.toolbar .btn.on { background: var(--brand-deep); color: #fff; border-color: var(--brand-deep); }

/* integrator → customer chips (settings, staff only) */
.ichip { display: inline-block; padding: 2px 8px; margin: 2px 0; border: 1px solid var(--line, #d7dbe3); border-radius: 999px; font-size: .92em; white-space: nowrap; }
.ichip .linkish { padding: 0 2px; font-weight: 700; }

/* ---------- "or" divider + passkey button (שימי, 15/09/2026) ----------
   A rule with the word set into it, rather than a bare line: the passkey button below is a real
   alternative to the form above, not a second submit, and the eye needs to be told that before it
   reads the label. Built from one border on a pseudo-element per side so it needs no background
   colour to punch a hole in — the card is white today and may not be tomorrow. */
.login .or { display:flex; align-items:center; gap:10px; margin:14px 0 10px; color:var(--faint); font-size:13px; }
.login .or::before, .login .or::after { content:""; flex:1; border-top:1px solid var(--line); }
.login #pkLogin { display:flex; align-items:center; justify-content:center; gap:8px; }
/* The fingerprint is decoration beside a label that already says what the button does; keeping it
   from shrinking is the only thing it needs, and it must not steal the click. */
.login #pkLogin .i { flex:none; pointer-events:none; }

/* ---- a colour that can also be "no colour" -------------------------------------------------
   The swatch and its "transparent" box are one decision, so they share one bordered control
   instead of sitting in two neighbouring fields that happen to be adjacent. When transparency is
   on, the swatch greys out and the checkbox lights up: the state is legible across the room,
   which is the whole point — it was invisible before (Shimi 16/09/2026). */
.colorf .colorf-row {
  display:flex; align-items:stretch; gap:8px; padding:5px; border:1px solid var(--line-2);
  border-radius:var(--r-sm); background:var(--paper); transition:border-color var(--fast), background var(--fast);
}
.colorf .colorf-row input[type="color"] {
  flex:0 0 58px; width:58px; min-height:36px; height:auto; border-radius:var(--r-xs);
  transition:opacity var(--fast), filter var(--fast);
}
/* The colour stays submitted and stays chosen — only its authority is withdrawn, so unticking
   the box brings the same shade back rather than a default. */
.colorf.is-clear .colorf-row input[type="color"] { opacity:.32; filter:grayscale(1); }
.colorf.is-clear .colorf-row { background:var(--wash-2); border-color:var(--line-2); }
.colorf .cbx {
  flex:1 1 auto; display:flex; align-items:center; min-height:44px; padding:0 10px;
  border-radius:var(--r-xs); cursor:pointer; font-size:14px; line-height:1.3; color:var(--ink-2);
  font-weight:500; user-select:none; transition:background var(--fast), color var(--fast);
}
.colorf .cbx:hover { background:var(--wash); }
.colorf.is-clear .cbx { background:var(--brand-tint); color:var(--brand-deep); font-weight:600; }
.colorf .cbx input[type="checkbox"] { flex:0 0 auto; vertical-align:0; }
.colorf .colorf-row:focus-within { border-color:var(--brand-deep); box-shadow:0 0 0 3px rgba(138,101,34,.14); }
/* Colour rows top-align. The default bottom-alignment was fine while every field in the row was the
   same height; the moment one of them can grow a line of explanation, bottom-alignment drags the
   neighbour's INPUT down level with that explanation and away from its own label. */
.row.row-colors { align-items:flex-start; }
/* A shell with nothing but a swatch in it shrinks to the swatch. Left full width it reads as an
   empty text box — something to type into — which is the opposite of what it is. */
.colorf .colorf-row.solo { width:max-content; }
.colorf-hint { margin-top:6px; font-size:13px; }
/* The hint only earns its line while transparency is actually on — otherwise it is a warning about
   a state nobody is in, on every colour field in the product. */
.colorf:not(.is-clear) .colorf-hint { display:none; }

/* ── לוח שיבוצים (16/09/2026) ────────────────────────────────────────────────────────────────
   Rooms across, hours down. The grid is one CSS grid per room rather than one big table, because a
   shift has to span half-hours and a table cell cannot: `grid-row: start / end` says the same thing
   the rota does. On a phone the whole board scrolls sideways in its own box — the page itself never
   does, which is the rule everywhere else in this admin. */
.bd-bar { display:flex; align-items:center; gap:14px; flex-wrap:wrap; margin-bottom:12px; }
.bd-nav { display:flex; gap:6px; }
.bd-when { display:flex; flex-direction:column; line-height:1.2; }
.bd-when b { font-size:15px; }
.bd-when span { font-size:12px; color:var(--muted); }
.bd-legend { display:flex; gap:6px; flex-wrap:wrap; margin-inline-start:auto; }
.chip.fixed-k { background:#e7effb; color:#1f3f7a; border-color:#cddffa; }
.chip.once-k { background:#fdf0e3; color:#8a5312; border-color:#f6ddbf; }

.bd-wrap { display:flex; gap:8px; overflow-x:auto; padding-bottom:6px; --bd-slot:26px; }
.bd-hours { display:grid; grid-auto-rows:var(--bd-slot); flex:0 0 52px; padding-top:30px; }
.bd-hour { font-size:11px; color:var(--muted); text-align:start; line-height:1; }
.bd-cols { display:flex; gap:8px; flex:1 1 auto; min-width:0; }
.bd-col { flex:1 1 130px; min-width:130px; }
.bd-colhead { height:30px; display:flex; align-items:center; justify-content:center; font-size:13px; font-weight:600;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.bd-grid { display:grid; position:relative; border:1px solid var(--line); border-radius:var(--r-md); overflow:hidden; }
.bd-slot { grid-column:1; border-bottom:1px solid var(--line); background:var(--paper); }
.bd-slot:nth-child(2n) { background:color-mix(in srgb, var(--line) 22%, var(--paper)); }
.bd-block { grid-column:1; margin:1px 2px; border-radius:6px; padding:3px 6px; overflow:hidden;
  display:flex; flex-direction:column; justify-content:center; line-height:1.15; }
.bd-block b { font-size:12px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.bd-block span { font-size:11px; opacity:.75; }
.bd-block.fixed { background:#e7effb; color:#1f3f7a; border:1px solid #cddffa; }
.bd-block.once { background:#fdf0e3; color:#8a5312; border:1px solid #f6ddbf; }
/* a double-booked block: the same block, stated as a problem. The stripe reads at a glance on a
   board of twenty rooms, where a colour swap alone would just look like another category. */
.bd-block.clash { background:var(--down-tint); color:var(--down); border:1px solid var(--down-line);
  background-image:repeating-linear-gradient(135deg, transparent 0 6px, rgba(0,0,0,.05) 6px 12px); }
.bd-warn { display:flex; align-items:flex-start; gap:10px; margin:0 0 12px; padding:11px 13px;
  background:var(--down-tint); border:1px solid var(--down-line); border-radius:var(--r-sm); color:var(--down); }
.bd-warn b { font-size:14px; font-weight:600; display:block; }
.bd-warn ul { list-style:none; margin:6px 0 0; font-size:13.5px; color:var(--ink-2); }
.bd-warn li { padding:2px 0; }
.bd-warn .help { margin-top:6px; }
.bd-warn .i { flex:0 0 auto; margin-top:1px; }
.bd-col.free .bd-grid { border-style:dashed; }
.bd-freeflag { grid-column:1; grid-row:1 / -1; display:flex; align-items:center; justify-content:center;
  font-size:12px; color:var(--muted); pointer-events:none; }
@media (max-width:640px) { .bd-wrap { --bd-slot:22px; } .bd-col { flex:0 0 118px; min-width:118px; } .bd-legend { margin-inline-start:0; } }
/* The band sits ABOVE the hours grid, never inside it: a manual change has no hours, and drawn as
   a block it read as an 08:00 shift. Every column reserves the row so the hours stay aligned. */
.bd-wrap.has-band { --bd-band:34px; }
.bd-wrap.has-band .bd-hours { padding-top:calc(30px + var(--bd-band, 0px)); }
.bd-wrap.has-band .bd-col > .bd-grid { margin-top:0; }
.bd-band { height:30px; margin:0 0 4px; border-radius:6px; padding:2px 6px; display:flex; flex-direction:column;
  justify-content:center; line-height:1.1; overflow:hidden; }
.bd-band b { font-size:12px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.bd-band span { font-size:11px; opacity:.75; }
.bd-band.once { background:#fdf0e3; color:#8a5312; border:1px solid #f6ddbf; }
.bd-band.empty { border:1px solid transparent; }
/* A room with a default doctor is occupied at every hour no shift covers, so the whole column is
   tinted rather than a block being drawn at hours nobody chose. */
.chip.dflt-k { background:#eaf3ed; color:#2b5c3d; border-color:#cde2d4; }
.bd-band.dflt { background:#eaf3ed; color:#2b5c3d; border:1px solid #cde2d4; }
.bd-col.hasdefault .bd-slot { background:color-mix(in srgb, #2b5c3d 6%, var(--paper)); }
.bd-col.hasdefault .bd-slot:nth-child(2n) { background:color-mix(in srgb, #2b5c3d 10%, var(--paper)); }
