/* Claude update below */
:root {
  --accent: #0352a6;
  --border: #ddd;
  --danger: #b3261e;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: #f5f6f7;
  color: #1a1a1a;
}

.adminHeader {
  background: #1a1a1a;
  color: #fff;
  padding: 10px 20px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.adminHeader h1 { margin: 0; font-size: 17px; font-weight: 600; }

#userBox { display: flex; gap: 10px; align-items: center; font-size: 14px; }

/* Claude update below (Open Page, beside the site's name in the header:
   the page being edited is one thing every tab is about, so the way to
   look at it belongs where every tab can see it. Outlined rather than
   solid so it reads as a way out to the page, not as the primary action
   of whatever tab is open.) */
.headerLeft { display: flex; align-items: center; gap: 14px; }

.headerLink {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border: 1px solid rgba(255, 255, 255, 0.45);
  border-radius: 6px;
  color: #fff;
  text-decoration: none;
  font-size: 13px;
  white-space: nowrap;
}

.headerLink:hover { background: rgba(255, 255, 255, 0.14); }
/* Claude update end */

.panel {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 18px 20px;
  max-width: 1000px;
  margin: 18px auto;
}

/* Claude update below (a dialog carrying .panel inherited its 18px TOP margin,
   which is a fixed number rather than auto, so a dialog capped by max-height
   sat 18px from the top and put every remaining pixel underneath itself. That
   is the uneven gap: auto on both keeps them equal. #editorPanel already said
   this for itself; every other dialog needs it too.) */
dialog.panel { margin: auto; }

#loginView { max-width: 380px; }

h2 { margin: 0 0 14px; font-size: 18px; }

form label { display: block; margin-bottom: 12px; font-size: 14px; }

form label.row { display: flex; align-items: center; gap: 8px; }

input[type="text"], input[type="password"], input[type="url"],
input[type="date"], textarea {
  width: 100%;
  padding: 8px 10px;
  margin-top: 4px;
  border: 1px solid var(--border);
  border-radius: 5px;
  font-size: 14px;
  font-family: inherit;
}

label.row input { width: auto; margin: 0; }

button {
  padding: 8px 16px;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: #fff;
  font-size: 14px;
  cursor: pointer;
}

button:hover { background: #f0f0f0; }

button.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
button.primary:hover { background: #04407f; }

button.danger { color: var(--danger); border-color: var(--danger); }

.listHeader { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }

table { width: 100%; border-collapse: collapse; font-size: 14px; }

th, td { border-bottom: 1px solid var(--border); padding: 7px 8px; text-align: left; }

th { background: #fafafa; }

tr.hiddenRow td { color: #999; }

td .rowBtn { padding: 4px 10px; font-size: 13px; }

fieldset { border: 1px solid var(--border); border-radius: 6px; margin-bottom: 12px; }

.imageRow { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }

#imgPreview { max-height: 60px; max-width: 100px; border: 1px solid var(--border); }

/* Claude update below (Item 5: settings background-image preview must never
   overflow the panel/screen, however large the uploaded image is) */
#sImgPreview {
  display: block;
  /* Claude update below (fits inside the fixed frame that holds the space;
     the frame carries the border now) */
  max-width: 100%;
  max-height: 100%;
  /* Claude update end */
  width: auto;
  height: auto;
}
fieldset img { max-width: 100%; }
/* Claude update end */

.formButtons { display: flex; gap: 10px; margin-top: 6px; }

.error {
  background: #fdecea;
  border: 1px solid #f5c6c2;
  color: var(--danger);
  border-radius: 6px;
  padding: 8px 12px;
  font-size: 14px;
}

.hint { color: #777; font-size: 12px; }

code { background: #f0f0f0; padding: 1px 5px; border-radius: 3px; }

/* Claude update below (Item 2/3: users + settings panels) */
td .rowBtn.danger { color: var(--danger); border-color: var(--danger); }

.addUserForm { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; margin-top: 14px; }

.addUserForm label { margin-bottom: 0; flex: 1 1 160px; }

.addUserForm .error { flex-basis: 100%; }
/* Claude update end */

/* Claude update below (tab bar + Buttons/Useful Links editors) */
.tabBar {
  max-width: 1000px;
  margin: 18px auto 0;
  display: flex;
  gap: 6px;
  border-bottom: 2px solid var(--border);
}

.tabBtn {
  border: 1px solid var(--border);
  border-bottom: none;
  border-radius: 8px 8px 0 0;
  background: #ececec;
  padding: 9px 18px;
  font-size: 14px;
  color: #555;
}

.tabBtn:hover { background: #e2e2e2; }

.tabBtn.active {
  background: #fff;
  color: var(--accent);
  font-weight: 600;
  border-color: var(--border);
  position: relative;
  top: 2px;
  border-bottom: 2px solid #fff;
}

.tabPage > .panel:first-child { margin-top: 12px; }

.linkList { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }

.linkRow {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px;
  background: #fafafa;
}

.linkRow input[type="text"] { margin-top: 0; }
.linkRow .lrLabel { flex: 1 1 150px; }
.linkRow .lrUrl { flex: 2 1 240px; }
.linkRow .lrNewTab { margin-bottom: 0; white-space: nowrap; font-size: 13px; }
.lrControls { display: flex; gap: 4px; margin-left: auto; }
.lrControls .rowBtn { padding: 4px 8px; }
/* Claude update end */

/* Claude update below (image display select, gradient overlay controls,
   per-row useful-link images) */
select {
  width: 100%;
  padding: 8px 10px;
  margin-top: 4px;
  border: 1px solid var(--border);
  border-radius: 5px;
  font-size: 14px;
  font-family: inherit;
  background: #fff;
}

fieldset label.stacked { margin-top: 10px; }

.overlayRow {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: flex-end;
  margin-top: 10px;
}

.overlayRow .overlayTitle { flex-basis: 100%; font-size: 13px; font-weight: 600; }

.overlayRow label { margin-bottom: 0; font-size: 13px; }

.overlayRow input[type="color"] {
  display: block;
  margin-top: 4px;
  width: 52px;
  height: 30px;
  padding: 1px;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: #fff;
}

.overlayRow input[type="number"] { width: 80px; display: block; }
/* Claude update end */

/* Claude update below (banner color pickers, same shape as the overlay row) */
.colorRow {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: flex-end;
  margin: 0 0 14px;
}

.colorRow .colorRowTitle { flex-basis: 100%; font-size: 13px; font-weight: 600; }

.colorRow label { margin-bottom: 0; font-size: 13px; }

.colorRow label.row { align-self: center; white-space: nowrap; }

.colorRow input[type="color"] {
  display: block;
  margin-top: 4px;
  width: 52px;
  height: 30px;
  padding: 1px;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: #fff;
}

.colorRow label.disabled { opacity: 0.45; }
/* Claude update end */

/* Claude update below (Sort Date column always fits on one line;
   favicon preview kept small) */
th.colSortDate,
#sessionsTable td:nth-child(3),
#pastTable td:nth-child(3) { white-space: nowrap; }

/* Keep Preview and Edit on one line instead of stacking when the title
   column takes the width. */
#sessionsTable td:last-child,
#pastTable td:last-child,
#usersTable td:last-child { white-space: nowrap; text-align: right; }
#sessionsTable td:last-child .rowBtn,
#pastTable td:last-child .rowBtn,
#usersTable td:last-child .rowBtn { margin-left: 4px; }

#sFavPreview {
  max-height: 32px;
  max-width: 32px;
  border: 1px solid var(--border);
  border-radius: 4px;
}
/* Claude update end */

/* Claude update below (Webex SSO sign-in button + users table controls) */
a.ssoBtn {
  display: inline-block;
  padding: 0.5rem 0.9rem;
  border: 1px solid var(--accent);
  border-radius: 4px;
  background: var(--accent);
  color: #fff;
  text-decoration: none;
  font: inherit;
}
a.ssoBtn:hover { background: #04407f; }
#usersTable input[type="email"] { width: 15rem; max-width: 100%; }
#usersTable select { font: inherit; }
#usersTable button[disabled], #dashView button[disabled] { opacity: 0.5; cursor: not-allowed; }
/* Claude update end */

/* Claude update below (Add / Edit user dialog) */
#userDialog {
  border: 1px solid #ccc;
  border-radius: 8px;
  padding: 0;
  max-width: 34rem;
  width: calc(100% - 2rem);
}
#userDialog::backdrop { background: rgba(0, 0, 0, 0.35); }
#userDialog form { padding: 1.25rem; }
#userDialog h2 { margin: 0 0 0.75rem; }
#userDialog fieldset {
  border: 1px solid #ddd;
  border-radius: 6px;
  margin: 0 0 1rem;
  padding: 0.75rem 1rem 1rem;
}
/* Claude update below (the collapsible local account section, made to sit in
   the same row of boxes as the fieldsets on either side of it) */
#userDialog details.userSection {
  border: 1px solid #ddd;
  border-radius: 6px;
  margin: 0 0 1rem;
  padding: 0.75rem 1rem 1rem;
}
#userDialog details.userSection > summary {
  font-weight: 600;
  cursor: pointer;
  /* Closed, the box is only the summary line, so the padding below it would
     leave a gap under the text. */
  margin: -0.15rem 0 0;
}
#userDialog details.userSection:not([open]) { padding-bottom: 0.75rem; }
/* Claude update end */
#userDialog legend { font-weight: 600; padding: 0 0.35rem; }
#userDialog label { display: block; margin: 0.5rem 0; }
/* Claude update below (the two rules above are id selectors, so they beat the
   generic form label.row / #userDialog input and the checkbox would stack
   above its own text at full width instead of sitting beside it) */
#userDialog label.row { display: flex; align-items: center; gap: 8px; }
#userDialog label.row input[type="checkbox"] { display: inline-block; width: auto; margin: 0; }
/* Claude update end */
#userDialog input, #userDialog select {
  display: block;
  width: 100%;
  margin-top: 0.2rem;
  font: inherit;
  padding: 0.35rem;
  box-sizing: border-box;
}
#userDialog .hint { margin: 0 0 0.5rem; }
#userDialog menu {
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
  margin: 0;
  padding: 0;
}
/* Claude update end */

/* Claude update below (login page: Webex first, local account collapsed) */
#localLoginBox {
  margin-top: 1.25rem;
  border-top: 1px solid #e2e2e2;
  padding-top: 0.75rem;
}
#localLoginBox > summary {
  cursor: pointer;
  color: var(--accent);
  font-weight: 600;
  list-style-position: outside;
  padding: 0.25rem 0;
}
#localLoginBox > summary:hover { text-decoration: underline; }
#localLoginBox > form { margin-top: 0.75rem; }
#ssoBox { margin-bottom: 0.5rem; }
#userDialog menu .menuSpacer { flex: 1; }
#userDialog menu button.danger { margin-right: auto; }
/* Claude update end */

/* Claude update below (session editor as a modal + card preview popover) */
/* margin auto keeps the top and bottom gaps equal whether the content is
   short or the dialog is capped at max-height. */
#editorPanel {
  border: 1px solid #ccc;
  border-radius: 8px;
  padding: 1.25rem 1.25rem 0;
  max-width: 64rem;
  width: calc(100% - 3rem);
  max-height: 96vh;
  margin: auto;
  overflow: auto;
}
#editorPanel::backdrop { background: rgba(0, 0, 0, 0.35); }
.editorHead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.5rem;
}
.editorHead h2 { margin: 0; }

button.previewBtn { cursor: help; }

/* Hovering lifts the card off the page with a shadow only. The dimmed,
   blurred backdrop is reserved for a pinned preview, so a passing hover does
   not black out the whole screen. Matching the card's radius keeps the shadow
   off the square corners of the host box. */
#cardPreviewHost {
  position: fixed;
  z-index: 99999;
  display: none;
  overflow: auto;
  pointer-events: none;
  border-radius: 10px;
  box-shadow: 0px 0px 54px -4px rgba(0, 0, 0, 0.6);
}
#cardPreviewHost.visible { display: block; }
#cardPreviewHost.pinned { pointer-events: auto; }

#cardPreviewScrim {
  position: fixed;
  inset: 0;
  z-index: 99998;
  display: none;
  background: rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(2px);
  pointer-events: none;
}
#cardPreviewScrim.visible { display: block; }

/* Save / Cancel / Delete stay on screen instead of scrolling out of reach.
   Sticky needs the scroll container to have no bottom padding, otherwise the
   bar parks above it. */
.formButtons.stickyButtons {
  position: sticky;
  bottom: 0;
  gap: 10px;
  background: #fff;
  border-top: 1px solid var(--border);
  padding: 12px 0 16px;
  margin-top: 14px;
}
.formButtons .menuSpacer { flex: 1; }
/* Claude update end */

/* Claude update below (Top Cards / Useful Links: read-only rows + modal) */
.cardListTable { margin-bottom: 10px; table-layout: fixed; }
.cardListTable th, .cardListTable td { font-size: 13px; vertical-align: middle; }
/* Percentages must total 100 and there must be one per column: with
   table-layout fixed, a column with no width of its own is left to absorb
   whatever remains, and when the others already add up to 100 that is
   nothing. Adding the Visible column without a width here is exactly what
   squashed it under the buttons. */
.cardListTable th:nth-child(1) { width: 26%; }
.cardListTable th:nth-child(2) { width: 16%; }
.cardListTable th:nth-child(3) { width: 17%; }
.cardListTable th:nth-child(4) { width: 8%; }
.cardListTable th:nth-child(5) { width: 7%; }
/* Preview, Edit and the two arrows come to ~195px, so this column has to stay
   wide enough for them at the narrowest the panel gets, or they spill over the
   edge of their own cell. */
.cardListTable th:last-child { width: 26%; }

/* The address is a link to the thing it points at, opened in a new tab so the
   admin is never navigated away from. */
td.cardCellClip a { color: var(--accent); }

/* Long descriptions and URLs would otherwise stretch the row out of the
   panel. The full value is on the cell's title attribute. */
td.cardCellClip {
  max-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Claude update below (the row that was just reordered, so it is obvious
   which entry moved and where it ended up. On the td rather than the tr,
   because a tr background is painted under its cells and would not show.) */
tr.cardRowMoved > td { background: aliceblue; }
/* Claude update end */
td.cardRowControls { white-space: nowrap; text-align: right; }
td.cardRowControls .rowBtn { margin-left: 4px; }
td.cardRowControls .rowBtn[disabled] { opacity: 0.4; cursor: not-allowed; }

/* Wider than it was (34rem) so the four buttons in the Image row have space
   to sit across, rather than the row wrapping. */
#cardDialog {
  border: 1px solid #ccc;
  border-radius: 8px;
  padding: 1.25rem 1.25rem 0;
  max-width: 42rem;
  width: calc(100% - 2rem);
  max-height: 92vh;
  overflow: auto;
}
#cardDialog::backdrop { background: rgba(0, 0, 0, 0.35); }
#cardDialog label { display: block; margin-bottom: 12px; font-size: 14px; }
#cardDialog label.row { display: flex; align-items: center; gap: 8px; }
#cImgPreview { max-height: 100px; max-width: 160px; border: 1px solid var(--border); }
/* Claude update end */

/* Claude update below (custom file pickers, image gallery, toast) */
.hiddenFileInput {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.fileRow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

/* Claude update below (Upload File / Pick from Gallery / Edit Image / Remove
   image have to sit on one line. At the shared 14px they came to more than
   the narrowest dialog could hold and wrapped onto a second row, which reads
   as two groups of buttons rather than one. Smaller here only: these four are
   a row of equals, not the form's own Save and Cancel.) */
.fileRow .rowBtn {
  font-size: 13px;
  padding: 6px 10px;
  white-space: nowrap;
}

.fileHint { margin: 6px 0 2px; }

.galleryActions { display: flex; gap: 8px; align-items: center; }

.galleryGrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 12px;
  margin-top: 10px;
}

.galleryTile {
  margin: 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px;
  background: #fafafa;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.galleryTile img {
  width: 100%;
  height: 110px;
  object-fit: contain;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 4px;
}

.galleryTile figcaption { display: flex; flex-direction: column; gap: 2px; min-width: 0; }

.galleryName {
  font-size: 12px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.galleryFoot { display: flex; flex-direction: column; gap: 4px; margin-top: auto; }

.galleryUsed {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.galleryTile.pickable { cursor: pointer; }
.galleryTile.pickable:hover { border-color: var(--accent); background: #eef4fb; }

/* Claude update below (one picture's details, opened from a tile's Edit
   button. The destructive actions live in here rather than on the tiles, so
   the gallery reads as a wall of pictures instead of a wall of buttons.) */
#galleryFileDialog { max-width: 34rem; width: 92vw; }

.galleryFileBody {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  flex-wrap: wrap;
}

#galleryFileImg {
  width: 180px;
  height: 140px;
  object-fit: contain;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 6px;
  flex: 0 0 auto;
}

.galleryFileFacts {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 4px 12px;
  margin: 0;
  font-size: 13px;
  flex: 1 1 14rem;
  min-width: 0;
}

.galleryFileFacts dt { color: #555; }

/* Claude update below (the image dialog dims what is behind it, the way the
   card preview does, so it reads as a layer over the page rather than a panel
   sitting on it) */
#galleryFileDialog::backdrop, #msgDialog::backdrop {
  background: rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(2px);
}

/* Claude update below (how much of the audit log is on screen, and the rest) */
.auditMore {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 10px;
}

.auditMore p { margin: 0; }
/* Claude update end */

/* Claude update below (alertDialog / confirmDialog) */
#msgDialog { max-width: 30rem; width: 92vw; }

/* The messages carry their own line breaks, from back when they were
   browser alerts. */
#msgDialogText { white-space: pre-line; margin: 0 0 4px; line-height: 1.5; }

.msgDialogButtons { justify-content: flex-end; }
/* Claude update end */

/* An action that cannot run right now looks dead but stays clickable, so the
   click can explain itself rather than being swallowed. */
button.btnBlocked, button.btnBlocked:hover {
  background: #e4e4e4;
  color: #767676;
  border-color: #cfcfcf;
  cursor: not-allowed;
}

.galleryFileFacts dd {
  margin: 0;
  /* A long filename or a list of six sessions must wrap rather than push the
     dialog wider than the viewport. */
  overflow-wrap: anywhere;
}
/* Claude update end */

#galleryPickDialog {
  max-width: 52rem;
  width: calc(100% - 3rem);
  max-height: 90vh;
  margin: auto;
  overflow: auto;
}
#galleryPickDialog::backdrop { background: rgba(0, 0, 0, 0.35); }

#toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translate(-50%, 12px);
  z-index: 100000;
  background: #1a1a1a;
  color: #fff;
  padding: 10px 18px;
  border-radius: 6px;
  font-size: 14px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
  cursor: pointer;
  opacity: 0;
  /* Only the slide is animated. Fading the opacity looked marginally nicer
     but left the toast stuck at 0 wherever transitions do not get frames,
     which reads as the toast never appearing at all. */
  transition: transform 0.15s;
}
#toast.visible { opacity: 1; transform: translate(-50%, 0); }

/* Claude update below (a toast parked just above the button that caused it.
   left/top are set inline from the button's own box; the translate lifts it
   clear of the button rather than covering it.) */
#toast.anchored { bottom: auto; transform: translate(-50%, calc(-100% + 8px)); }
#toast.anchored.visible { transform: translate(-50%, -100%); }
/* Claude update end */
/* Claude update end */

/* Claude update below (Audit Log / Restore, and the inherited Date text) */
#auditTable { table-layout: fixed; }
#auditTable th.colAuditWhen { width: 12rem; }
#auditTable th.colAuditUser { width: 11rem; }
/* Wide enough for Preview and Restore side by side. The table is
   table-layout: fixed, so a column that is too narrow does not grow: the
   buttons spill out of the panel instead. */
#auditTable th:last-child { width: 12.5rem; }
#auditTable td { vertical-align: top; }

/* The action can be several changes joined together. Wrap it rather than
   pushing the Restore button off the panel. */
td.auditAction { overflow-wrap: anywhere; }

td.auditControls { text-align: right; white-space: nowrap; }

/* The Preview control is a link so the browser opens the tab itself and the
   address can be copied, but the button look comes from the `button` element
   selector, so it has to be restated here. */
a.rowBtn {
  display: inline-block;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: #fff;
  color: #1a1a1a;
  text-decoration: none;
  cursor: pointer;
}

a.rowBtn:hover { background: #f0f0f0; }

td.auditControls a.rowBtn { margin-right: 6px; }

/* The icon comes from cardRender.js with no size of its own; public.css sizes
   it for the public page and the admin has to do the same. */
.newTabIcon {
  width: 0.85em;
  height: 0.85em;
  margin-left: 5px;
  vertical-align: -0.08em;
}

#auditRetention { margin-top: 0; }

/* A Date text that was not typed in but taken from the Sort Date. */
td.inheritedValue { font-style: italic; color: #777; }
/* Claude update end */

/* Claude update below (Admin Settings tab + the idle timeout warning) */
input[type="number"].adminNumber {
  width: 90px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 5px;
  font-size: 14px;
  font-family: inherit;
}

/* One grid per row, all with the same columns, so every box lines up down
   the tab no matter how long the wording to its left is. */
.adminRow {
  display: grid;
  grid-template-columns: 14rem auto 1fr;
  align-items: center;
  gap: 10px;
  margin-bottom: 4px;
  font-size: 14px;
}

.adminRow > label { margin: 0; }

.adminRow input[type="checkbox"] {
  width: auto;
  margin: 0;
  justify-self: start;
}

.adminUnit { color: inherit; }

.fieldRange { color: #777; font-size: 12px; }

/* What the site is using on disk. Reads as a note rather than a setting, so
   it is boxed off from the form below it. */
.storageLine {
  margin: 0 0 18px;
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: #fafafa;
  font-size: 13px;
  color: #444;
}

.storageLine .storageLow {
  color: #b00020;
  font-weight: 600;
}

#adminSettingsForm .hint { margin: 0 0 18px; }

@media (max-width: 640px) {
  .adminRow { grid-template-columns: 1fr auto; }
  .adminRow .adminUnit { grid-column: 1 / -1; }
}

#idleDialog { max-width: 420px; }

/* The timed refresh, in the top right under the header. Quieter than the
   main toast on purpose: it reports something the page did on its own, not
   an answer to anything the user asked for. */
#refreshToast {
  position: fixed;
  top: 68px;
  right: 20px;
  z-index: 99999;
  background: #fff;
  color: #444;
  border: 1px solid var(--border);
  padding: 7px 13px;
  border-radius: 6px;
  font-size: 13px;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.12);
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 0.2s, transform 0.2s;
  pointer-events: none;
}

#refreshToast.visible { opacity: 1; transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
  #refreshToast { transition: none; }
}
/* Claude update end */

/* Claude update below (background image: the picture beside a scaled preview
   of the real public page, and the full size version of the same thing) */
.bgPreviewCols {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 10px;
}

.bgPreviewCol {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.bgPreviewTitle { font-size: 12px; color: #777; }

/* The picture sits in a frame the same size as the preview beside it, kept
   even when there is no picture, so the preview never moves about depending
   on whether one is set. */
.bgImageFrame {
  width: 380px;
  height: 285px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: #fafafa;
  overflow: hidden;
}

#sImgEmpty { color: #999; font-size: 13px; }

/* An icon button: square, and the glyph carries the meaning, so the label is
   on title/aria-label instead. */
button.iconBtn {
  padding: 4px 0;
  width: 30px;
  font-size: 17px;
  line-height: 1;
}

button.iconBtn:disabled { opacity: 0.4; cursor: default; }
button.iconBtn:disabled:hover { background: #fff; }

.bgPreviewCol #sImgName { font-size: 13px; word-break: break-all; }

/* A 1024x768 screen shown at 380px wide. The iframe is laid out at the real
   size and scaled, so the image crop, the gradient and the text all land
   exactly where they would on that screen rather than being approximated. */
.heroPreviewViewport {
  width: 380px;
  height: 285px;
  overflow: hidden;
  position: relative;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: #fff;
}

.heroPreviewViewport iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 1024px;
  height: 768px;
  border: 0;
  /* 380 / 1024 */
  transform: scale(0.37109375);
  transform-origin: top left;
  /* A picture of the page, not something to interact with. */
  pointer-events: none;
}

/* Sits at the right hand end of the preview it opens, and smaller than the
   form's own buttons so it does not read as one of them. */
#btnHeroPreviewFull {
  align-self: flex-end;
  padding: 4px 10px;
  font-size: 12px;
}

.pendingNote {
  margin: 6px 0 0;
  padding: 7px 10px;
  border: 1px solid #e6d9a8;
  border-radius: 5px;
  background: #fdf8e6;
  font-size: 13px;
  color: #6b5a17;
}

/* Never a bare display on the dialog itself: that would override the UA's
   display:none for a closed one and leave it on screen. */
#heroPreviewDialog[open] {
  display: flex;
  flex-direction: column;
  width: 90vw;
  height: 90vh;
  max-width: 90vw;
  max-height: 90vh;
  padding: 14px 16px;
  overflow: hidden;
}

.heroPreviewHead {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: start;
  gap: 10px;
  margin-bottom: 10px;
}

.heroPreviewHead h2 { margin: 0; grid-column: 1; }
.heroPreviewHead .hint { margin: 4px 0 0; grid-column: 1; }
#heroPreviewClose { grid-column: 2; grid-row: 1 / span 2; width: auto; padding: 0 14px; }

.heroPreviewStage {
  flex: 1;
  position: relative;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 4px;
  /* A 4:3 screen in a wider dialog leaves space at the sides. Grey rather
     than white, so it reads as being outside the simulated screen instead of
     as part of the page. */
  background: #e9eaec;
}

#heroPreviewBigFrame {
  position: absolute;
  top: 0;
  left: 0;
  width: 1024px;
  height: 768px;
  border: 0;
  background: #fff;
  transform-origin: top left;
}
/* Claude update end */

/* Claude update below (Pages tab + editor) */
/* Five columns instead of the card lists' six, and the controls cell holds
   Edit, Copy Markdown Link and Delete, so it needs the widest share. */
.pagesTable th:nth-child(1) { width: 24%; }
.pagesTable th:nth-child(2) { width: 21%; }
.pagesTable th:nth-child(3) { width: 10%; }
.pagesTable th:nth-child(4) { width: 7%; }
.pagesTable th:last-child { width: 38%; }

#pageDialog {
  width: min(60rem, 96vw);
  max-height: 94vh;
  overflow: auto;
  padding-bottom: 0;
}
#pageDialog::backdrop { background: rgba(0, 0, 0, 0.35); }
#pageDialog .editorHead { gap: 8px; }
#pageDialog .editorHead .rowBtn { font-size: 13px; padding: 4px 10px; }

.pageMetaCols { display: flex; gap: 16px; flex-wrap: wrap; }
.pageMetaCols > label { flex: 1 1 240px; }
.pageVisibleRow { align-self: end; margin-bottom: 14px; }

.slugRow { display: flex; align-items: center; gap: 2px; }
.slugRow .slugFixed { color: #777; font-size: 14px; }
.slugRow input { flex: 1; min-width: 0; }

.wysiwygBar {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  align-items: center;
  border: 1px solid var(--border);
  border-bottom: 0;
  border-radius: 6px 6px 0 0;
  background: #f7f8fa;
  padding: 6px 8px;
  margin-top: 10px;
}
.wysiwygBar button {
  padding: 4px 9px;
  font-size: 13px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 4px;
  cursor: pointer;
}
.wysiwygBar button:hover { background: #eef3fa; border-color: var(--accent); }
.wysiwygSep { width: 1px; height: 20px; background: var(--border); margin: 0 4px; }

/* The editing surface previews the page's own typography closely enough to
   trust: headings, lists, quotes, tables and pictures read as they will. */
.pageBodyEdit {
  border: 1px solid var(--border);
  border-radius: 0 0 6px 6px;
  min-height: 320px;
  max-height: 55vh;
  overflow-y: auto;
  padding: 14px 16px;
  background: #fff;
  line-height: 1.6;
  overflow-wrap: break-word;
}
.pageBodyEdit:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
.pageBodyEdit h1 { font-size: 26px; margin: 0.9em 0 0.4em; }
.pageBodyEdit h2 { font-size: 22px; margin: 0.9em 0 0.4em; }
.pageBodyEdit h3 { font-size: 18px; margin: 0.9em 0 0.4em; }
.pageBodyEdit p { margin: 0.6em 0; }
.pageBodyEdit ul, .pageBodyEdit ol { margin: 0.6em 0; padding-left: 28px; }
.pageBodyEdit img { max-width: 100%; height: auto; }
.pageBodyEdit blockquote {
  margin: 0.8em 0;
  padding: 2px 14px;
  border-left: 4px solid var(--accent);
  background: #f6f8fb;
}
.pageBodyEdit table { border-collapse: collapse; margin: 0.8em 0; }
.pageBodyEdit th, .pageBodyEdit td {
  border: 1px solid #ccc;
  padding: 4px 8px;
}
.pageBodyEdit a { color: var(--accent); }

#pageLinkDialog { width: min(28rem, 94vw); }
/* Claude update end */
