/* ============================================================
   Ultra-Kiosk - front-end sign in
   Brand: dark gray #414042, green #016325.
   Self-contained so it looks right on whatever theme happens to
   be installed on the shared server.
   ============================================================ */

/* ============================================================
   Brand tokens.

   Defined on :root, not on a component. They were originally
   scoped to .uk-ed, which broke the moment a button rendered
   outside the editor: var(--uk-green) resolved to nothing, so
   the Save/New buttons became white text on no background —
   present, clickable, and completely invisible.
   ============================================================ */

:root {
  --uk-gray:   #414042;   /* UltraTech brand */
  --uk-green:  #016325;   /* UltraTech brand */
  --uk-green2: #0a7d33;
  --uk-line:   #dcdcdb;
  --uk-panel:  #ffffff;
  /* One step off the panel, for a block that has to read as a unit
     inside it - the open hotspot in the editor list. */
  --uk-panel-2: #f6f5f2;
  --uk-bg:     #f1f0ee;
  /* Behind the background image, and darker than the rest of the editor: the
     image is the thing being worked on, and a light surround let it bleed into
     the panel around it. */
  --uk-stage:  #cbc9c4;
  --uk-ink2:   #636266;
  --uk-aspect: 1.7778;

  /* One height for every control in the editor toolbar. */
  --uk-ctl-h:  42px;
}

.uk-login {
  display: flex;
  justify-content: center;
  padding: clamp(24px, 6vw, 72px) 18px;
  font-family: "Segoe UI", system-ui, -apple-system, Roboto, "Helvetica Neue", Arial, sans-serif;
  color: var(--uk-gray);
  box-sizing: border-box;
}

.uk-login * { box-sizing: border-box; }

.uk-login-card {
  width: 100%;
  max-width: 400px;
  padding: clamp(24px, 4vw, 38px);
  background: #fff;
  border: 1px solid var(--uk-line);
  border-radius: 12px;
  box-shadow: 0 14px 40px rgba(30, 30, 32, .10);
  text-align: center;
}

.uk-login-logo {
  display: block;
  width: auto;
  /* Wider than a square mark needs, because the logo is a lockup with the
     wordmark in it and a 190px cap made that unreadable. */
  max-width: 260px;
  height: auto;
  margin: 0 auto 14px;
}

/* Under the logo, and quiet. Every asset is cache-busted with this number, so
   it answers "which build am I looking at" without anybody having to ask. */
.uk-login-ver {
  margin: 0 0 18px;
  text-align: center;
  font-size: 11px;
  letter-spacing: .3px;
  color: #b3b2b6;
  font-variant-numeric: tabular-nums;
}

.uk-login-title {
  margin: 0 0 6px;
  font-size: clamp(20px, 2.4vw, 26px);
  font-weight: 700;
  letter-spacing: -.3px;
  color: var(--uk-gray);
}

.uk-login-intro {
  margin: 0 0 22px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--uk-ink2);
}

.uk-login-error {
  margin: 0 0 18px;
  padding: 10px 12px;
  border-radius: 6px;
  background: #fbe6e6;
  border: 1px solid #eccaca;
  color: #a12b2b;
  font-size: 13.5px;
  font-weight: 600;
  text-align: left;
}

.uk-login-field {
  display: block;
  margin-bottom: 14px;
  text-align: left;
}

.uk-login-field > span {
  display: block;
  margin-bottom: 5px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .9px;
  text-transform: uppercase;
  color: var(--uk-ink2);
}

.uk-login-field input {
  width: 100%;
  padding: 11px 12px;
  border: 1px solid var(--uk-line);
  border-radius: 6px;
  background: #fff;
  font: inherit;
  font-size: 15px;
  color: var(--uk-gray);
}

.uk-login-field input:focus {
  outline: 2px solid var(--uk-green);
  outline-offset: -1px;
  border-color: var(--uk-green);
}

.uk-login-check {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 4px 0 20px;
  font-size: 13.5px;
  color: var(--uk-ink2);
  text-align: left;
}

.uk-login-btn {
  display: block;
  width: 100%;
  padding: 13px 18px;
  border: 0;
  border-radius: 6px;
  background: var(--uk-green);
  color: #fff;
  font: inherit;
  font-size: 15px;
  font-weight: 700;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}

.uk-login-btn:hover,
.uk-login-btn:focus { background: var(--uk-green2); color: #fff; }

.uk-login-note {
  margin: 18px 0 0;
  font-size: 12.5px;
  line-height: 1.55;
  color: #8d8c90;
}

.uk-login-alt {
  margin: 16px 0 0;
  font-size: 13.5px;
}

.uk-login-alt a { color: var(--uk-green); }

/* ============================================================
   Ultra-Kiosk - editor UI
   Brand: dark gray #414042, green #016325.
   Written to work inside wp-admin but to depend on none of it,
   so the editor also runs in a bare page for development.
   ============================================================ */

/* Load-bearing: several nodes below set `display`, which beats the UA rule
   for the `hidden` attribute and leaves them stuck on screen. Scoped to the
   editor so it cannot affect the rest of wp-admin. */
.uk-ed [hidden] { display: none !important; }
/* Scoped to .uk-ed on purpose, but mind the edge: anything appended to the
   body - the busy notice, the preview sheet, a toast - falls outside this and
   the hidden attribute will lose to any display of its own. Out there, hide
   with a class. The busy notice learned that the hard way. */

.uk-ed {
  /* Tokens come from :root. Only the aspect is per-editor, because it
     follows the kiosk's orientation. */
  --uk-aspect: 1.7778;

  display: flex;
  flex-direction: column;
  height: calc(100vh - 120px);
  min-height: 520px;
  background: var(--uk-bg);
  border: 1px solid var(--uk-line);
  border-radius: 8px;
  overflow: hidden;
  font-family: "Segoe UI", system-ui, -apple-system, Roboto, Arial, sans-serif;
  color: var(--uk-gray);
}

/* ---------------- toolbar ---------------- */

.uk-ed-bar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  /* Wraps onto a second row rather than running off the edge.

     The editor clips its own overflow, so anything past the right-hand edge
     was not merely off screen - it was unreachable, with nothing to scroll.
     This row has been growing all along (background, orientation, preview,
     export, publish, stop sharing, add hotspot, save) and on a narrower window
     or at a larger browser zoom the first controls simply vanished.

     Wrapping the ROW is not the wrapping that was a problem before: that was
     labels breaking inside their own buttons, which the nowrap below still
     prevents. */
  flex-wrap: wrap;
  gap: 8px 12px;
  padding: 12px 14px;
  background: var(--uk-panel);
  border-bottom: 1px solid var(--uk-line);
}

/* The theme's stylesheet still loads on the app page — only the TEMPLATE is
   bypassed, not the theme's CSS. Page builders commonly set `select,input
   { width: 100% }`, which stretched the orientation picker across the bar and
   squeezed the buttons until their labels wrapped. So every control here
   states its own width and refuses to wrap. */
.uk-ed-bar select,
.uk-ed-bar input,
.uk-ed-bar button {
  width: auto;
  max-width: none;
  /* One fixed height for every control, rather than letting each one work it
     out from its own padding and line-height. Theme CSS reaches these elements
     and pads them unevenly, which is why Preview Kiosk and Add Hotspot came
     out different heights. An explicit height cannot drift. */
  height: var(--uk-ctl-h);
  min-height: var(--uk-ctl-h);
  box-sizing: border-box;
}

/* Centre the label inside that fixed height. */
.uk-ed-bar .uk-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding-top: 0;
  padding-bottom: 0;
}

.uk-ed-spacer { flex: 1 1 0; min-width: 0; }

.uk-ed-title {
  /* Gives up width before the buttons do, so the row wraps later. */
  flex: 1 1 180px;
  width: 260px;
  max-width: 320px;
  min-width: 0;
  padding: 0 10px;
  border: 1px solid var(--uk-line);
  border-radius: 5px;
  font-size: 15px;
  font-weight: 650;
  color: var(--uk-gray);
}

.uk-ed-orient {
  width: 330px;
  /* Room on the right for the chevron. */
  padding: 0 34px 0 12px;
  border: 1px solid var(--uk-line);
  border-radius: 5px;
  font: inherit;
  font-size: 13.5px;
  color: var(--uk-gray);
  cursor: pointer;

  /* Our own chevron rather than the platform one. The native arrow varies by
     OS and browser and a theme can strip it entirely with `appearance: none`,
     which leaves a box that does not look like a menu at all. Drawn inline as
     a data URI, so it stays a local asset like everything else here. */
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  background-color: #fff;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' fill='none' stroke='%23414042' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 12px 8px;
}

.uk-ed-orient::-ms-expand { display: none; }

.uk-btn {
  padding: 10px 16px;
  border: 1px solid var(--uk-line);
  border-radius: 5px;
  background: #fff;
  color: var(--uk-gray);
  font: inherit;
  font-size: 13.5px;
  font-weight: 650;
  cursor: pointer;
  line-height: 1.2;
  /* Labels are short on purpose; wrapping one is always a layout fault
     somewhere else, so forbid it and let the fault show as overflow. */
  white-space: nowrap;
}
.uk-btn:hover { background: #f6f6f5; }
.uk-btn--primary {
  background: var(--uk-gray); border-color: var(--uk-gray); color: #fff;
  /* Fixed width: this button swaps its label when place mode is armed, and a
     button that resizes on click reflows the toolbar and shifts the canvas
     under the cursor. */
  min-width: 165px;
}
.uk-btn--primary:hover { background: #55545a; }
.uk-btn--save { background: var(--uk-green); border-color: var(--uk-green); color: #fff; }
.uk-btn--save:hover { background: var(--uk-green2); }
.uk-btn--danger { border-color: #d8c2c2; color: #a12b2b; background: #fff; }

/* ---------------- body ---------------- */

.uk-ed-body {
  flex: 1 1 auto;
  display: flex;
  min-height: 0;
}

.uk-ed-stagewrap {
  position: relative;
  flex: 1 1 auto;
  background: var(--uk-stage);
  display: grid;
  place-items: center;
  padding: 18px;
  min-width: 0;
  overflow: hidden;
}

/* Magnified, the image is bigger than the window it sits in, so dragging it
   is how you reach the rest. At fit there is nowhere to go and the cursor
   should not suggest otherwise. */
.uk-ed-stagewrap.is-zoomed .uk-ed-stage { cursor: grab; }
.uk-ed-stagewrap.is-panning .uk-ed-stage { cursor: grabbing; }
.uk-ed-stagewrap.is-panning { user-select: none; }

/* ---------------- zoom control ---------------- */

.uk-ed-zoom {
  position: absolute;
  left: 18px;
  bottom: 18px;
  z-index: 5;
  display: flex;
  align-items: stretch;
  border-radius: 7px;
  overflow: hidden;
  background: #fff;
  border: 1px solid var(--uk-line);
  box-shadow: 0 3px 12px rgba(30, 30, 32, .16);
}

.uk-ed-zoombtn,
.uk-ed-zoomnow {
  height: 30px;
  border: 0;
  background: none;
  color: var(--uk-gray);
  font: 600 14px/1 inherit;
  cursor: pointer;
}

.uk-ed-zoombtn {
  width: 32px;
  padding: 0;
  display: grid;
  place-items: center;
}

.uk-ed-zoombtn svg {
  width: 15px;
  height: 15px;
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
}
.uk-ed-zoomnow {
  min-width: 56px;
  padding: 0 8px;
  font-size: 12px;
  border-left: 1px solid var(--uk-line);
  border-right: 1px solid var(--uk-line);
}

.uk-ed-zoombtn:hover,
.uk-ed-zoomnow:hover { background: #f1efeb; }
.uk-ed-zoombtn:focus-visible,
.uk-ed-zoomnow:focus-visible { outline: 2px solid var(--uk-green); outline-offset: -2px; }


/* The stage locks to the chosen orientation so what you are looking
   at is the shape of the actual panel, not the shape of the browser. */
.uk-ed-stage {
  position: relative;
  width: 100%;
  max-width: calc((100vh - 260px) * var(--uk-aspect));
  aspect-ratio: var(--uk-aspect);
  background: #fff;
  border: 1px solid var(--uk-line);
  border-radius: 6px;
  overflow: hidden;
  box-shadow: 0 6px 20px rgba(30,30,32,.10);
}

.uk-ed-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  user-select: none;
  -webkit-user-drag: none;
}

.uk-ed-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

.uk-ed-empty {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: #97969a;
  font-size: 14px;
}

.uk-ed.is-placing .uk-ed-stage { cursor: crosshair; }
.uk-ed.is-placing .uk-ed-layer { pointer-events: none; }

/* ---------------- markers ---------------- */

.uk-mk-leader { stroke: var(--uk-gray); stroke-width: 3; opacity: .8; }
.uk-mk-target { fill: none; stroke: var(--uk-gray); stroke-width: 3; }

.uk-mk-dot {
  fill: var(--uk-green);
  stroke: #fff;
  stroke-width: 4;
}
.uk-mk.is-on .uk-mk-dot { fill: var(--uk-green2); stroke-width: 6; }

.uk-mk-num {
  fill: #fff;
  font-family: inherit;
  font-weight: 700;
  text-anchor: middle;
  pointer-events: none;
}

.uk-mk-hit {
  fill: transparent;
  cursor: grab;
  touch-action: none;
}
.uk-mk-hit:active { cursor: grabbing; }

/* Locked: the cursor must stop offering a grab it will not honour. Still a
   pointer, because a tap still selects the hotspot for editing. */
.uk-mk-hit.is-locked,
.uk-mk-hit.is-locked:active { cursor: pointer; }

/* The lock on a hotspot row. Quiet until it matters: an outline that only
   fills in once the hotspot is actually held, so a list of eight rows does not
   read as a column of buttons. */
.uk-ed-lock {
  /* .uk-ed-pick beside it is flex: 1 1 auto, so this lands hard right. */
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--uk-gray-3, #6b6b70);
  display: grid;
  place-items: center;
  cursor: pointer;
}

.uk-ed-lock svg { width: 19px; height: 19px; display: block; }

.uk-ed-lock:hover { background: #f1efeb; color: var(--uk-gray); }

/* Red, and the editor's own red - the one on Delete, the character counter
   and error toasts - rather than a new colour.

   Green was too quiet for a shackle two pixels tall: at a glance down eight
   rows the shape of an open padlock and a closed one is nearly the same mark,
   so the state has to be carried by colour and weight, not by geometry. */
.uk-ed-lock.is-locked { color: #a12b2b; }
.uk-ed-lock.is-locked svg { stroke-width: 2.2; }

.uk-ed-lock:focus-visible {
  outline: 2px solid var(--uk-green);
  outline-offset: -2px;
}

/* ---------------- side panel ---------------- */

.uk-ed-panel {
  flex: 0 0 340px;
  overflow-y: auto;
  /* No top padding. A sticky child pins to the PADDING box, not the border
     box — with 16px here, the header stuck 16px down and form fields scrolled
     past in full view in the gap above it. The sticky header carries that
     padding itself instead. */
  padding: 0 16px 16px;
  background: var(--uk-panel);
  border-left: 1px solid var(--uk-line);
}

/* Sticky: which hotspot you are editing must stay visible while the form
   is scrolled, along with the way out of it. */
.uk-ed-panelhead {
  position: sticky;
  top: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 0 -16px 14px;
  padding: 14px 16px 12px;
  background: var(--uk-panel);
  border-bottom: 1px solid var(--uk-line);
  /* Opaque plus a soft edge, so anything passing underneath reads as behind
     it rather than colliding with it. */
  box-shadow: 0 6px 10px -6px rgba(30, 30, 32, .22);
  font-size: 15px;
}

.uk-ed-panelnum {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
}

.uk-ed-panelbadge {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--uk-green);
  color: #fff;
  font-size: 12.5px;
  font-weight: 700;
}

.uk-ed-panelname {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 650;
}

.uk-ed-paneltools { display: flex; gap: 8px; flex: 0 0 auto; }

/* Its own top space. The panel has no top padding on purpose - a sticky child
   pins to the padding box, and 16px there let form fields scroll through in
   full view above the header - so anything that sits at the very top of the
   panel has to bring its own. */
.uk-ed-hint {
  margin: 0;
  padding: 18px 0 0;
  color: #97969a;
  font-size: 13px;
  line-height: 1.5;
}

/* Section headings break a long flat list of inputs into the three things
   a visitor actually sees: the marker, the popup, the detail page. */
.uk-f-section {
  margin: 26px 0 2px;
  padding-top: 16px;
  border-top: 2px solid var(--uk-green);
  /* Deliberately a size and weight above .uk-f-label. When both were 11px
     uppercase, the sections read as just more field labels and the grouping
     did no work. */
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .4px;
  text-transform: none;
  color: var(--uk-green);
}
.uk-f-section:first-child { margin-top: 0; padding-top: 0; border-top: 0; }

.uk-f-sectionhint {
  margin: 0 0 14px;
  font-size: 12px;
  line-height: 1.5;
  color: #97969a;
}

.uk-f { display: block; margin-bottom: 14px; }
.uk-f-label {
  display: block;
  margin-bottom: 3px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .8px;
  text-transform: uppercase;
  color: var(--uk-ink2);
}

/* Always visible rather than a tooltip. A hover tooltip is undiscoverable,
   and this is used a few times a year by people who will not remember what
   "Legend name" meant last time. */
.uk-f-help {
  display: block;
  margin-bottom: 6px;
  font-size: 11.5px;
  line-height: 1.45;
  color: #97969a;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}
.uk-f-input {
  width: 100%;
  padding: 7px 9px;
  border: 1px solid var(--uk-line);
  border-radius: 5px;
  font: inherit;
  font-size: 13px;
  color: var(--uk-gray);
  background: #fff;
}
/* Twice what it was. At 62px an intro showed two lines of a paragraph that
   can run to 700 characters, so the box was mostly a scrollbar and you were
   editing through a slot. Still resizable, for anyone who wants more. */
textarea.uk-f-input { min-height: 124px; resize: vertical; line-height: 1.5; }
/* Three fixed slots rather than an open box: the popup has exactly three,
   and the shape of the control should say so. */
.uk-chips { display: flex; flex-direction: column; gap: 8px; }
.uk-chipline { display: flex; align-items: center; gap: 8px; }
.uk-chip { flex: 1 1 auto; min-width: 0; font-size: 12.5px; }
.uk-chipcount { flex: 0 0 auto; margin-top: 0; width: 44px; }

.uk-f-count {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  font-weight: 600;
  text-align: right;
  color: #b4b3b7;
  letter-spacing: 0;
  text-transform: none;
}
.uk-f-count.is-warn { color: #9a7b00; }
.uk-f-count.is-full { color: #a12b2b; }

textarea.uk-f-input--tall { min-height: 220px; font-family: ui-monospace, Consolas, monospace; font-size: 12px; }
.uk-f-input:focus { outline: 2px solid var(--uk-green); outline-offset: -1px; border-color: var(--uk-green); }

/* ---------------- preflight strip ---------------- */

.uk-ed-issues {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 8px 14px;
  background: var(--uk-panel);
  border-top: 1px solid var(--uk-line);
  min-height: 38px;
  max-height: 118px;
  overflow-y: auto;
  align-items: center;
}

.uk-issue {
  /* Some of these are <button> now, so reset what a button brings with it. */
  border: 0;
  font: inherit;
  text-align: left;
  padding: 4px 10px;
  border-radius: 4px;
  font-size: 12px;
  line-height: 1.45;
  background: #f1f0ee;
  color: var(--uk-ink2);
  /* Wrap inside the chip. These messages are sentences, and a chip that
     refuses to wrap would push the strip wider than the panel. */
  max-width: 100%;
}
.uk-issue--ok    { background: #e6f0e9; color: var(--uk-green); font-weight: 650; }
.uk-issue--info  { background: #e7edf3; color: #3f5b73; }

/* Actionable issues take you to the thing they are about. */
.uk-issue.is-go { cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.uk-issue.is-go:hover { filter: brightness(0.95); }
.uk-issue.is-go:focus-visible { outline: 2px solid var(--uk-green); outline-offset: 1px; }
.uk-issue--warn  { background: #fdf3d8; color: #7a5c00; }
.uk-issue--error { background: #fbe6e6; color: #a12b2b; font-weight: 650; }

/* ============================================================
   App shell — the chrome around the list and the editor.

   The theme is bypassed on this page (templates/app.php), so
   these are the only styles in play. That is deliberate: a
   kiosk editor cannot be at the mercy of whichever theme
   happens to be installed on this server.
   ============================================================ */

html, body.uk-body {
  margin: 0;
  padding: 0;
  min-height: 100%;
  background: #f1f0ee;
  color: #414042;
  font-family: "Segoe UI", system-ui, -apple-system, Roboto, "Helvetica Neue", Arial, sans-serif;
}

body.uk-body * { box-sizing: border-box; }

/* The editor fills the window and does its own scrolling inside the panel and
   the list. There is nothing below it worth reaching, and letting the page
   scroll there just gave anything that moved focus somewhere to throw you. */
html:has(body.uk-body--editor),
body.uk-body--editor { height: 100%; overflow: hidden; }

/* ---------------- page header ---------------- */

/* Three columns, not space-between. The sides are different widths - a back
   link on one, a status pill and a sign-out on the other - and anything that
   shares out the leftover space puts the middle wherever the sides happen to
   end. 1fr / auto / 1fr puts the brand in the middle of the bar whatever is
   beside it. */
.uk-top {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 16px;
  padding: 10px clamp(14px, 3vw, 30px);
  background: #fff;
  border-bottom: 1px solid #dcdcdb;
}

.uk-top-left {
  justify-self: start;
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
}

/* Version beside the logo, not under it. Stacked, the version was spending
   about thirteen pixels of bar height that the logo needed more: this is a
   wide lockup, so its width is set by how tall the bar lets it be, and at 30px
   it came out barely seventy pixels across. */
.uk-top-brand {
  justify-self: center;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 9px;
  text-decoration: none;
  color: #414042;
  min-width: 0;
}

/* Tall enough that a wordmark inside a lockup is still readable. Width is
   left alone: a lockup is wide, a bare mark is square, and both are fine. */
/* As tall as the bar will take, because a 2.5:1 lockup is only ever as wide as
   its height allows. At 46px this comes out around 115px across; at the 30px
   it used to be, seventy-five. */
.uk-top-logo {
  height: clamp(34px, 3.4vw, 46px);
  width: auto;
  max-width: 260px;
  display: block;
}

/* Present for a screen reader, not drawn. The header uses this for the app
   name when the logo already contains it. */
.uk-quiet {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.uk-top-name { font-size: 16px; font-weight: 700; letter-spacing: -.2px; }

.uk-top-right { justify-self: end; display: flex; align-items: center; gap: 14px; }
.uk-top-user { font-size: 13px; color: #8d8c90; }

/* Deliberately faint. It is there to be found when somebody is wondering which
   build they are looking at, not to be read on the way past. */
.uk-top-ver {
  font-size: 10.5px;
  line-height: 1;
  letter-spacing: .3px;
  color: #b3b2b6;
  font-variant-numeric: tabular-nums;
}

.uk-top-out,
.uk-top-back {
  font-size: 13.5px;
  font-weight: 600;
  color: #016325;
  text-decoration: none;
}
.uk-top-out:hover,
.uk-top-back:hover { text-decoration: underline; }

.uk-top--editor .uk-top-back { display: inline-flex; align-items: center; gap: 7px; }

/* ---------------- pages ---------------- */

.uk-page { padding: clamp(16px, 3vw, 32px); }
.uk-page--editor { padding: clamp(10px, 1.6vw, 20px); }

.uk-page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
}
.uk-page-head h1 {
  margin: 0;
  font-size: clamp(20px, 2.4vw, 28px);
  font-weight: 700;
  letter-spacing: -.4px;
}

/* ---------------- kiosk list ---------------- */

.uk-list {
  display: grid;
  /* 320, not 260: a card carries five actions along its bottom edge, and at
     260 they never fitted on one line. */
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 16px;
  padding: 0;
  margin: 0;
  list-style: none;
}

.uk-card {
  margin: 0;
  background: #fff;
  border: 1px solid #dcdcdb;
  border-radius: 10px;
  overflow: hidden;
}
.uk-card:hover {
  border-color: #016325;
  box-shadow: 0 6px 18px rgba(30, 30, 32, .08);
}

.uk-card-open {
  display: block;
  text-decoration: none;
  color: #414042;
}

/* Actions sit outside the link, so clicking Delete cannot also
   navigate into the kiosk. */
.uk-card-actions {
  display: flex;
  flex-wrap: wrap;
  /* Row gap first: five actions do not fit one line on a narrow card, and
     without wrapping they broke mid-label - "Stop / Sharing" on two lines,
     shoving everything out of alignment. They flow to a second line now, and
     each one stays in one piece. */
  gap: 8px 16px;
  padding: 10px 16px 12px;
  border-top: 1px solid #eceae6;
}

.uk-card-actions .uk-link,
.uk-card-export { white-space: nowrap; }

/* The export action is a real <form> so the browser can handle the download.
   It must not become a box in the middle of the action row. */
.uk-card-export { margin: 0; padding: 0; border: 0; display: contents; }

.uk-link {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: #016325;
  cursor: pointer;
}
.uk-link:hover { text-decoration: underline; }
.uk-link--danger { color: #a12b2b; margin-left: auto; }

/* ---------------- empty state ---------------- */

.uk-blank {
  max-width: 460px;
  margin: clamp(30px, 8vh, 80px) auto;
  padding: clamp(26px, 4vw, 40px);
  background: #fff;
  border: 1px solid #dcdcdb;
  border-radius: 12px;
  text-align: center;
}
.uk-blank h2 {
  margin: 0 0 10px;
  font-size: 21px;
  font-weight: 700;
}
.uk-blank p {
  margin: 0 0 22px;
  font-size: 14px;
  line-height: 1.6;
  color: #636266;
}

/* ---------------- toast ---------------- */

.uk-toast {
  /* Middle of the screen, not the bottom edge. A notice at the foot of a tall
     editor is below where anyone is looking. */
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, calc(-50% + 14px));
  z-index: 9999;
  padding: 12px 22px;
  /* 22px is exactly half the height of a single-line toast, so a short one is
     still a pill; a message long enough to wrap becomes a rounded card instead
     of a very wide lozenge. */
  border-radius: 22px;
  background: var(--uk-gray);
  color: #fff;
  font-size: 14px;
  font-weight: 650;
  line-height: 1.4;
  text-align: center;
  text-wrap: balance;
  max-width: min(520px, calc(100vw - 48px));
  box-shadow: 0 12px 30px rgba(30, 30, 32, .22);
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s ease, transform .2s ease;
}
/* Clickable only while it is up, so it can be dismissed but never swallows a
   click aimed at the page underneath once it has faded. */
.uk-toast.is-on { opacity: 1; transform: translate(-50%, -50%); pointer-events: auto; cursor: pointer; }
.uk-toast--error { background: #a12b2b; }

/* The running state chip in the page header. */
.uk-ed-status:empty { display: none; }

/* ---------------- busy ---------------- */

body.uk-busy { cursor: progress; }
body.uk-busy .uk-btn,
body.uk-busy .uk-link { pointer-events: none; opacity: .55; }

.uk-card-thumb {
  display: block;
  aspect-ratio: 16 / 9;
  background: #eceae6;
  overflow: hidden;
}
.uk-card-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

.uk-card-nothumb {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  font-size: 12.5px;
  color: #a3a2a6;
}

.uk-card-body { display: block; padding: 14px 16px 16px; }
.uk-card-title { display: block; font-size: 15.5px; font-weight: 650; margin-bottom: 4px; }
.uk-card-meta { display: block; font-size: 12.5px; color: #8d8c90; }

.uk-empty { color: #8d8c90; }

/* The editor fills whatever is left below the page header. */
/* Height is set in script, from a measurement. This is only the floor for the
   moment before that runs, and for anywhere script does not. */
body.uk-body .uk-ed { height: auto; }

/* ============================================================
   Preview overlays

   Two of them, sharing one chrome: a single hotspot (popup and
   the page it leads to), and the whole kiosk with working taps.
   Styled to resemble the kiosk rather than the editor, because
   the point is to show what the visitor gets.
   ============================================================ */

.uk-pv {
  position: fixed;
  inset: 0;
  z-index: 9998;
  display: grid;
  place-items: center;
  padding: clamp(12px, 3vw, 34px);
  background: rgba(30, 30, 32, .55);
}

.uk-pv,
.uk-pv-sheet {
  /* On the body, outside .uk-ed, so a theme's own body font would otherwise
     come through. */
  font-family: "Segoe UI", system-ui, -apple-system, Roboto, "Helvetica Neue", Arial, sans-serif;
}

.uk-pv-sheet {
  width: min(560px, 100%);
  max-height: 92vh;
  display: flex;
  flex-direction: column;
  background: var(--uk-bg);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(20, 20, 22, .35);
}
.uk-pv-sheet--wide { width: min(1200px, 100%); }

.uk-pv-bar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 12px 16px;
  background: #fff;
  border-bottom: 1px solid var(--uk-line);
  font-size: 14px;
}

.uk-pv-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 18px;
}

@media (max-width: 900px) {
}

/* ============================================================
   Arriving from a preflight issue

   Clicking an issue selects the hotspot, scrolls to the field and
   focuses it — but a focus ring alone is easy to miss halfway down
   a long panel, and the marker may be anywhere on the image. Both
   get a brief, self-cancelling highlight.
   ============================================================ */

.uk-f.is-target .uk-f-input {
  border-color: var(--uk-green);
  box-shadow: 0 0 0 3px rgba(1, 99, 37, .18);
}
.uk-f.is-target .uk-f-label { color: var(--uk-green); }

.uk-mk.is-flash .uk-mk-dot {
  animation: uk-flash 1.6s ease-out;
}

@keyframes uk-flash {
  0%, 100% { stroke: #fff; stroke-width: 4; }
  20%, 60% { stroke: #ffd166; stroke-width: 12; }
}

@media (prefers-reduced-motion: reduce) {
  .uk-mk.is-flash .uk-mk-dot { animation: none; stroke: #ffd166; stroke-width: 10; }
}

/* ---------------- kiosk preview ---------------- */

/* There is no preview stylesheet any more. The preview is an iframe running
   player/index.html with the player's own CSS, so what is styled here is the
   window it sits in and nothing inside it. Roughly seventy lines of
   preview-only rules used to live here, quietly disagreeing with the ones
   that ship. */
.uk-pv-frame {
  display: block;
  height: min(72vh, 900px);
  aspect-ratio: var(--uk-pv-aspect, 16 / 9);
  max-width: 100%;
  margin: 0 auto;
  border: 0;
  border-radius: 10px;
  background: #eceae6;
  box-shadow: 0 8px 30px rgba(30, 30, 32, .16);
}

.uk-pv-note {
  margin: 12px 0 0;
  color: var(--uk-gray-3, #6b6b70);
  font-size: 12.5px;
  text-align: center;
}
.uk-pv-note--bad { color: #a12b2b; font-weight: 650; }

/* ---------------- on/off switch ---------------- */

.uk-switchrow {
  /* Positioned, so the real checkbox inside it has something to be absolute
     against. Without this it resolved against the page, and clicking the
     label focused an input the browser then scrolled to - which threw you
     down to whatever is below the editor. */
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  user-select: none;
}

/* The real checkbox stays in the accessibility tree and keeps the keyboard
   behaviour; the track and knob are what gets drawn. */
/* The real checkbox, invisible but exactly where the switch is.

   It used to be the standard one-pixel clipped trick, which puts the input
   somewhere that is not where it looks like it is. Clicking the label focuses
   it, and a browser scrolls a newly focused element into view - so a tap on a
   switch scrolled the page to the input's actual position. Laying it over the
   whole row instead means focusing it moves nothing, and it stays a real
   checkbox for the keyboard and for screen readers. */
.uk-switch {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  cursor: pointer;
}

.uk-switchtrack {
  position: relative;
  flex: 0 0 auto;
  width: 40px;
  height: var(--uk-switch-h, 23px);
  border-radius: 999px;
  background: #cfcdc8;
  transition: background .16s ease;
}

.uk-switchknob {
  position: absolute;
  top: 3px; left: 3px;
  width: 17px; height: 17px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(30, 30, 32, .3);
  transition: transform .16s ease;
}

.uk-switch:checked + .uk-switchtrack { background: var(--uk-green); }
.uk-switch:checked + .uk-switchtrack .uk-switchknob { transform: translateX(17px); }
.uk-switch:focus-visible + .uk-switchtrack { outline: 2px solid var(--uk-green); outline-offset: 2px; }

.uk-switchlabel { font-size: 13px; font-weight: 600; color: var(--uk-gray); }

/* A published kiosk's button reads "Copy Web Link". The dot says the link is
   live without spending width on the word. */
.uk-btn.is-live::before {
  content: "";
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 7px;
  border-radius: 50%;
  background: var(--uk-green);
  vertical-align: middle;
}

/* ---------------- something is happening ---------------- */

/* Centre of the screen, and it covers the page: the work takes a moment, and
   pressing the button again while it runs would start a second one. */
.uk-working {
  /* Hidden by a class rather than by the hidden attribute: this element lives
     on the body, outside .uk-ed, where the stylesheet's [hidden] override does
     not reach - and a display of its own beats the attribute every time. */
  display: none;
  position: fixed;
  inset: 0;
  z-index: 10000;
  place-items: center;
  background: rgba(30, 30, 32, .34);
}

.uk-working.is-on { display: grid; }

.uk-working-card {
  display: flex;
  align-items: center;
  gap: 14px;
  max-width: min(420px, calc(100vw - 48px));
  padding: 20px 26px;
  border-radius: 12px;
  background: var(--uk-gray);
  color: #fff;
  font-size: 14.5px;
  font-weight: 650;
  line-height: 1.45;
  box-shadow: 0 18px 44px rgba(30, 30, 32, .3);
}

.uk-working-spin {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  border: 2.5px solid rgba(255, 255, 255, .3);
  border-top-color: #fff;
  border-radius: 50%;
  animation: uk-spin .8s linear infinite;
}

@keyframes uk-spin { to { transform: rotate(360deg); } }

/* Someone who has asked for less movement gets a steady ring rather than none
   at all, so the notice still reads as busy. */
@media (prefers-reduced-motion: reduce) {
  .uk-working-spin { animation: none; border-top-color: rgba(255, 255, 255, .75); }
}

/* A quieter button, for an action that is available but rarely wanted. */
.uk-btn--quiet { color: var(--uk-gray-3, #6b6b70); }
.uk-btn--quiet:hover { color: #a12b2b; border-color: #e3c9c9; }

/* ---------------- hotspot list ---------------- */

/* The panel lists every hotspot the way the kiosk's own legend does, and the
   selected one opens in place. Reaching a hotspot used to mean finding its
   marker on the image, which is fine with three of them and unworkable with
   twelve. */
.uk-ed-list { padding-top: 12px; }

.uk-ed-item + .uk-ed-item { border-top: 1px solid var(--uk-line); }

/* The open one is a block, not a row followed by some fields.

   With only a hairline under the last field, a form ran straight into the next
   hotspot's name and there was no telling where one ended and the next began -
   particularly at the bottom of a long form, which is exactly where you are
   least sure. So it gets its own ground, a green edge down the side marking
   how far it extends, and air beneath it. */
.uk-ed-item.is-open {
  margin: 12px -16px;
  padding: 0 16px 6px;
  background: var(--uk-panel-2);
  border-top: 1px solid var(--uk-line);
  border-bottom: 1px solid var(--uk-line);
  box-shadow: inset 3px 0 0 var(--uk-green);
}

.uk-ed-item.is-open + .uk-ed-item { border-top: 0; }

.uk-ed-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* The open row is the header that stays put while its form scrolls past. It
   was a header above a single form before; same job, done by the row that is
   already there. Tinted to match its block, so it does not read as a separate
   strip floating over one. */
.uk-ed-row.is-open {
  position: sticky;
  top: 0;
  z-index: 3;
  margin: 0 -16px;
  padding: 12px 16px;
  background: var(--uk-panel-2);
  border-bottom: 1px solid var(--uk-line);
  box-shadow: 0 6px 10px -8px rgba(30, 30, 32, .22);
}

.uk-ed-pick {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  padding: 10px 0;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
}
.uk-ed-row.is-open .uk-ed-pick { padding: 0; }

.uk-ed-rownum {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--uk-green);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
}

.uk-ed-rowtext { display: flex; flex-direction: column; min-width: 0; }

.uk-ed-rowlabel {
  font-size: 13.5px;
  font-weight: 650;
  color: var(--uk-gray);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.uk-ed-rowshort {
  font-size: 12px;
  color: var(--uk-green);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.uk-ed-pick:hover .uk-ed-rowlabel { color: var(--uk-green); }
.uk-ed-pick:focus-visible { outline: 2px solid var(--uk-green); outline-offset: 2px; border-radius: 6px; }

.uk-ed-rowdel { flex: 0 0 auto; }

/* A rule and a wide gap at the end of the fields, so the block visibly closes
   before the next hotspot's name arrives. */
.uk-ed-form { padding-bottom: 20px; }

.uk-ed-form::after {
  content: "";
  display: block;
  height: 1px;
  margin-top: 20px;
  background: var(--uk-line);
}

/* Offered when a preview will not load, so a blank frame is never the end of
   the story. */
.uk-ed-retry { margin-left: 8px; height: 28px; padding: 0 12px; font-size: 12px; }

/* ---------------- hotspot photo ---------------- */

.uk-imgrow { display: flex; align-items: center; gap: 12px; }

.uk-imgthumb {
  flex: 0 0 auto;
  width: 72px;
  height: 72px;
  border-radius: 6px;
  object-fit: cover;
  background: #eceae6;
  border: 1px solid var(--uk-line);
}

.uk-imgthumb--none {
  display: grid;
  place-items: center;
  font-size: 11px;
  color: #97969a;
}

.uk-imgbtns { display: flex; flex-wrap: wrap; gap: 8px; }

/* ---------------- too narrow for the editor ---------------- */

/* Shown instead of the editor under 820px, which is roughly the panel plus a
   stage worth looking at. Overridable, because somebody who insists probably
   has a reason. */
.uk-narrow { display: none; }

@media (max-width: 819px) {
  body:not(.uk-anyway) .uk-narrow {
    display: block;
    /* min(), not a flat 460: on a 390px phone a 460px card is the very
       overflow the notice is about. */
    max-width: min(460px, 100%);
    margin: 8vh auto;
    padding: 26px 24px 28px;
    border-radius: 10px;
    background: var(--uk-panel);
    border: 1px solid var(--uk-line);
    text-align: center;
  }

  body:not(.uk-anyway) .uk-editor { display: none; }

  .uk-narrow h2 {
    margin: 0 0 12px;
    font-size: 20px;
    font-weight: 700;
    color: var(--uk-gray);
  }

  .uk-narrow p {
    margin: 0 0 12px;
    font-size: 14px;
    line-height: 1.55;
    color: #6b6b70;
  }

    /* The way back is a link wearing a button; without this it wears an
     underline too. */
  .uk-narrow-acts .uk-btn { text-decoration: none; }

  .uk-narrow-acts {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px;
    margin-top: 20px;
  }
}

/* Import sits beside New Kiosk, quieter: making one is the everyday act and
   bringing one in from elsewhere is not. */
.uk-page-acts { display: flex; flex-wrap: wrap; gap: 10px; }
