/* An icon + translated text label is common throughout this app
   (form-label, several buttons). Under dir="rtl", relying on bidi
   reordering of that mixed content is unpredictable, since an icon glyph
   isn't actual directional text - flex packs icon/text as one adjacent
   unit from the flex-start edge (the right, for rtl) instead, same fix
   already used for the icml-field labels in atex-edit.js. */
.form-label {
    display: flex;
    align-items: center;
    gap: 4px;
}

/* ─── Queue drop target ──────────────────────────────────────────────────── */
.folder[data-queue-id] {
    transition: background 0.15s, color 0.15s;
}
.folder.queue-drag-over {
    background: #0d6efd;
    color: #fff;
    border-radius: 3px;
    padding: 1px 4px;
}

/* ─── Mandatory field validation error ───────────────────────────────────── */
.meta-mandatory-error {
    outline: 2px solid red !important;
    animation: meta-shake 0.3s ease;
}
@keyframes meta-shake {
    0%,100% { transform: translateX(0); }
    25%      { transform: translateX(-4px); }
    75%      { transform: translateX(4px); }
}

/* ─── List field chips ───────────────────────────────────────────────────── */
.meta-list-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.meta-list-chip {
    opacity: 0.45;
    transition: opacity 0.15s, outline 0.15s;
}
.meta-list-chip--selected {
    opacity: 1;
}

/* ─── Thumbs grid view ────────────────────────────────────────────────────── */
/* view-toggle-btn/hide-assigned-btn (built in updateResultsToolbar(),
   atex-entries.js) share the same low-contrast ".toolbar-btn" ghost style as
   the edit-article banner and preview panel header for their "off" look -
   one fewer button style in the app. Their "on" state deliberately does NOT
   reuse .toolbar-btn.active's subtle blue tint though: whether images-view
   or hide-assigned is active changes what's on screen more than those other
   toolbars' own active states do, so it needs to read as unmistakably "on"
   rather than blend in - same vivid pink accent already used elsewhere for
   an active/attention state (e.g. the pinned-preview icon). Scoped to just
   this toolbar so it doesn't also recolor .toolbar-btn.active elsewhere. */
.results-view-toolbar {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 6px;
    padding: 8px 4px;
}
.results-view-toolbar .toolbar-btn.active {
    background: #ff69b4;
    color: #fff;
}
.results-view-toolbar .toolbar-btn.active:hover {
    background: #ff4fa8;
    color: #fff;
}
/* "New items available" banner - see _showNewItemsBanner() in
   atex-entries.js. Hidden by default; only inserted/shown once the
   background poll actually finds something newer than what's on screen. */
.new-items-banner {
    display: none;
    cursor: pointer;
    background-color: #e8f0fe;
    border: 1px solid #a9c6f7;
    color: #154b9e;
    border-radius: 6px;
    padding: 8px 14px;
    margin: 0 4px 10px;
    font-size: 13px;
    font-weight: 500;
    text-align: center;
}
.new-items-banner:hover {
    background-color: #dbe7fd;
}
.page-zoom-toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 15px 0 15px;
}
.page-zoom-toolbar input[type="range"] {
    width: 140px;
}
/* Row View toggle (#zone-row-toggle-btn) - same "changes what's on screen
   more than a subtle tint should convey" reasoning as .results-view-toolbar
   .toolbar-btn.active, so it gets the same vivid accent rather than
   .toolbar-btn.active's default quiet blue. */
.page-zoom-toolbar .toolbar-btn {
    margin-left: auto;
}
.page-zoom-toolbar .toolbar-btn.active {
    background: #ff69b4;
    color: #fff;
}
.page-zoom-toolbar .toolbar-btn.active:hover {
    background: #ff4fa8;
    color: #fff;
}
.thumbs-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: 12px;
    padding: 8px 4px 16px;
}
.thumb-card {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    border: 2px solid transparent;
    border-radius: 6px;
    padding: 6px;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s;
}
.thumb-card:hover {
    border-color: #4a90e2;
    background: rgba(74, 144, 226, 0.06);
}
.thumb-card.highlighted {
    border-color: #4a90e2;
    background: rgba(74, 144, 226, 0.12);
}
.thumb-img-wrap {
    position: relative;
    width: 100%;
    aspect-ratio: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    border-radius: 4px;
    background: #f4f4f4;
}
/* overflow:hidden on the wrap would clip the small icon-corner overhang, so
   the dot sits fully inside here instead, sized up a little for the bigger thumbnail */
.thumb-img-wrap .assigned-dot {
    bottom: 5px;
    right: 5px;
    width: 10px;
    height: 10px;
}
.thumb-img-wrap img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.thumb-placeholder {
    font-size: 36px;
    color: #ccc;
}
.thumb-label {
    font-size: 11px;
    color: #555;
    margin-top: 5px;
    text-align: center;
    word-break: break-all;
    max-width: 100%;
}

/* ─── Editor tabs ─────────────────────────────────────────────────────────── */
.editor-tabs {
    display: flex;
    gap: 0;
    border-bottom: none;
    margin-top: 24px;
}
.editor-tab {
    padding: 8px 20px;
    font-size: 13px;
    font-weight: 500;
    color: #6b7280;
    background: #f1f5f9;
    border: 1px solid #e2e8f0;
    border-bottom: none;
    border-radius: 6px 6px 0 0;
    cursor: pointer;
    margin-right: 4px;
    transition: background .15s, color .15s;
    outline: none;
}
.editor-tab:hover {
    background: #e8eef6;
    color: #374151;
}
.editor-tab--active {
    background: #fff;
    color: #1e40af;
    border-color: #e2e8f0;
    border-bottom-color: #fff;
    z-index: 1;
    position: relative;
}
.editor-tab-panel {
    border: 1px solid #e2e8f0;
    border-radius: 0 6px 6px 6px;
}

/* ─── Images panel ────────────────────────────────────────────────────────── */
/* ─── Regenerate headline button ─────────────────────────────────────────── */
.regen-headline-btn {
    margin-left: 10px;
    padding: 2px 8px;
    font-size: 11px;
    color: #6366f1;
    background: #eef2ff;
    border: 1px solid #c7d2fe;
    border-radius: 4px;
    cursor: pointer;
    vertical-align: middle;
    transition: background .15s, color .15s;
}
.regen-headline-btn:hover {
    background: #e0e7ff;
    color: #4338ca;
}

.image-upload-area {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 18px;
}
.image-upload-btn {
    padding: 7px 16px;
    font-size: 13px;
    font-weight: 500;
    color: #374151;
    background: #f8fafc;
    border: 1px dashed #94a3b8;
    border-radius: 5px;
    cursor: pointer;
    transition: background .15s, border-color .15s;
}
.image-upload-btn:hover {
    background: #f1f5f9;
    border-color: #64748b;
}
.image-upload-status {
    font-size: 12px;
    color: #6b7280;
}
#article-images {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    padding: 4px 0 18px 0;
    margin-bottom: 18px;
    border-bottom: 1px solid #e2e8f0;
    border-radius: 6px;
    transition: outline .15s, background .15s;
}
#article-images:empty {
    padding: 0;
    margin-bottom: 0;
    border-bottom: none;
}
#article-images.drag-over {
    outline: 2px dashed #0d6efd;
    outline-offset: 4px;
    background: rgba(13, 110, 253, 0.06);
}
.article-image-card img {
    height: 140px;
    width: auto;
    max-width: 220px;
    object-fit: cover;
    border-radius: 5px;
    border: 1px solid #e2e8f0;
    display: block;
}

.image-search-panel {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin: 10px 0;
    padding: 8px 10px;
    background: #f8fafc;
    border: 1px solid #e2e8f0;
    border-radius: 6px;
}
.image-search-input {
    flex: 1 1 200px;
    padding: 5px 8px;
    border: 1px solid #cbd5e1;
    border-radius: 4px;
}
.image-search-fields {
    display: flex;
    gap: 10px;
    font-size: 12px;
    color: #475569;
    white-space: nowrap;
}
.image-search-btn {
    padding: 5px 12px;
    border: 1px solid #94a3b8;
    background: #fff;
    border-radius: 5px;
    cursor: pointer;
}
.image-search-btn:hover {
    background: #f1f5f9;
}
.image-search-body {
    display: flex;
    align-items: flex-start;
    gap: 0;
}
#image-search-results {
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    gap: 10px;
    padding: 4px 0;
    margin-bottom: 4px;
    flex: 1 1 auto;
    min-width: 0;
}
#image-search-results:empty {
    margin-bottom: 0;
}
.image-search-empty {
    font-size: 12px;
    color: #6b7280;
}
.image-search-result-card {
    cursor: grab;
    width: 100px;
}
.image-search-result-thumb {
    position: relative;
    width: 100px;
    height: 100px;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    border-radius: 5px;
    border: 1px solid #e2e8f0;
    background: #f4f4f4;
}
.image-search-result-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
/* overflow:hidden on the wrap would clip the dot's default corner offset,
   same fix as .thumb-img-wrap .assigned-dot */
.image-search-result-thumb .assigned-dot {
    bottom: 5px;
    right: 5px;
}
.image-search-result-add {
    position: absolute;
    top: 5px;
    right: 5px;
    width: 20px;
    height: 20px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.55);
    color: #fff;
    font-size: 11px;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.15s, background 0.15s;
}
.image-search-result-card:hover .image-search-result-add {
    opacity: 1;
}
.image-search-result-add:hover {
    background: #0d6efd;
}
.image-search-result-add:disabled {
    cursor: default;
    opacity: 0.5;
}
.image-search-result-card.dragging {
    opacity: 0.5;
}
.image-search-result-card.selected .image-search-result-thumb {
    outline: 2px solid #0d6efd;
    outline-offset: 2px;
}
.image-search-result-card:focus {
    outline: none;
}

/* Slides open (width 0 -> auto-ish fixed width) only once a result is
   selected - scoped to this search area, not the page-level preview panel. */
.image-search-detail {
    flex: 0 0 auto;
    width: 0;
    max-width: 0;
    opacity: 0;
    overflow: hidden;
    padding: 0;
    margin-left: 0;
    border-left: 0 solid #e2e8f0;
    transition: width .2s ease, max-width .2s ease, opacity .15s ease, padding .2s ease, margin-left .2s ease;
}
.image-search-detail.open {
    width: 220px;
    max-width: 220px;
    opacity: 1;
    padding: 0 0 0 14px;
    margin-left: 14px;
    border-left: 1px solid #e2e8f0;
}
.image-search-detail img {
    width: 100%;
    height: auto;
    border-radius: 5px;
    border: 1px solid #e2e8f0;
    display: block;
    margin-bottom: 8px;
}
.image-search-detail-title {
    font-size: 12px;
    font-weight: 600;
    color: #334155;
    margin-bottom: 6px;
    word-break: break-word;
}
.image-search-detail-loading,
.image-search-detail-empty {
    font-size: 12px;
    color: #94a3b8;
}
.image-search-match-field {
    font-size: 11px;
    line-height: 1.4;
    word-break: break-word;
}
.image-search-match-field + .image-search-match-field {
    margin-top: 6px;
}

html, body {
	/* A native/system font stack, not a single hardcoded family - "Segoe UI"
	   only exists on Windows, so every other platform (iOS/macOS Safari,
	   Android Chrome) was silently falling through to the next name in the
	   list, Arial - not that platform's own modern system font (San
	   Francisco on iOS/macOS, Roboto on Android), and visibly not what a
	   phone user expects a well-built site to look like next to its native
	   apps. -apple-system/BlinkMacSystemFont pick up San Francisco on
	   Safari/Chrome respectively; Windows still gets exactly the same Segoe
	   UI as before, since those two names simply don't resolve to anything
	   there and it falls through unchanged. */
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
	font-size: 14px;
	background-color: #f4f4f4;
	margin: 0;
	padding: 0;
}
hr {
  border: none;
  height: 1px;
  border-radius: 10px;
  background: pink;
  margin: 20px 0;  /* Space above and below */
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);  /* Subtle shadow */
}

.container {
	max-width: 1500px;
	margin: 20px auto;
	padding: 20px;
	width: 100%; /* Ensure it adapts to smaller screens */
	box-sizing: border-box;
}

.story-card {
	background: white;
	padding: 15px;
	border-radius: 8px;
	box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
	width: 100%; /* Ensure cards don't exceed the container */
	max-width: 1500px;
	margin: 20px auto;
	transition: transform 0.2s;
	display: flex;
	flex-direction: column;
	position: relative;
	overflow: hidden;
	box-sizing: border-box; /* Prevents width issues */
}

h1 {
	text-align: left;
	color: #333;
	font-size: 32 px;
}



.search-container {
	position: relative;
	max-width: 1500px;
	margin: 0px auto;
	border: 0px;
	top:20px;
	padding-bottom: 20px;
}

.search-input {
	width: 100%;
	font-size: 14px;
	border: 1px solid #ccc;
	border-radius: 4px;
	box-sizing: border-box;
	max-width: 1500px;
	min-width: 400px;
	margin: 0px auto;
	padding: 10px;
	padding-left: 40px;
}

/* Pale highlight while a search term is actually typed in - :placeholder-shown
   only matches an empty input, so this needs no JS to track the value.
   #f8f9fa (the story preview's own text box background) was too close to
   white/the banner's own #f5f5f5 to actually notice, so this uses the same
   pale blue already used elsewhere for an "active" highlight (e.g. the
   history modal's active tab/row) instead. The border+glow match the
   brighter look the browser's own native focus ring gives it while actually
   focused - previously that brighter ring disappeared the moment focus moved
   elsewhere (e.g. clicking a different queue), leaving a duller highlight
   behind; this keeps the same brightness for as long as the field actually
   has a term in it, not just while it's focused. */
.search-input:not(:placeholder-shown) {
	background: #eef4ff;
	border-color: #3b82f6;
	box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.25);
}

.text-pink { color: #ff69b4 !important; } /* Hot pink */
.search-icon {
	position: absolute;
	left: 10px; /* Position the icon to the left inside the input */
	/* Fixed offset, not a percentage of .search-container's own height -
	   .search-input always starts flush with the container's top edge in
	   both layouts, so this centers on the input's ~38px height
	   regardless of how much (if any) trailing padding-bottom the
	   container adds below it. A percentage here previously centered
	   correctly only by coincidence, tuned against desktop's specific
	   padding-bottom - the mobile banner layout (.banner .search-container
	   below) drops that padding, shrinking the container down to just the
	   input's own height and leaving the same percentage pointing several
	   pixels above center instead. */
	top: 19px;
	transform: translateY(-50%);
	font-size: 18px; /* Icon size */
	color: #ccc; /* Icon color */
	pointer-events: none; /* Ensure the icon doesn't interfere with typing */
}

.stories-container {
	margin: 0 auto;
}



.story-title {
	font-size: 18px;
	font-weight: bold;
	color: #333;
	margin-bottom: 8px;
}

.story-meta {
	font-size: 14px;
	color: #777;
	margin-bottom: 8px;
}

.story-id {
	font-size: 12px;
	color: #aaa;
}

.story-actions {
	margin-top: auto;
	display: flex;
	justify-content: space-between;
}

.btn {
	padding: 8px 12px;
	background: #007bff;
	color: white;
	text-decoration: none;
	border-radius: 5px;
	font-size: 14px;
	transition: background 0.3s;
}

.btn:hover {
	background: #0056b3;
}

/* Vertical Status Bar */
.status-bar {
	position: absolute;
	top: 0;
	right: 0;
	width: 8px;
	height: 100%;
	border-radius: 0 8px 8px 0;
	cursor: pointer;
}

/* Tooltip */
.story-card:hover::after {
	content: attr(data-status);
	position: absolute;
	right: 17px;
	top: 30px;
	background-color: rgba(0, 0, 0, 0.8);
	color: white;
	padding: 5px 10px;
	border-radius: 5px;
	font-size: 12px;
	white-space: nowrap;
	z-index: 10;
}

/* Status List */
.status-list {
	margin-top: 5px;
	padding: 5px;
	background: #f9f9f9;
	border-radius: 5px;
	display: none;
	background-color: #fff;
	box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
	font-size: 11px;
}

.status-list p {
	margin: 5px 0;
}
.status-item:hover {
	opacity: 1 !important;
	transition: opacity 0.3s ease;
}

.banner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 20px;
	background-color: #f5f5f5; /* Light background */
	border-bottom: 2px solid #ddd; /* Subtle border */
	position: sticky;
	top: 0;
	z-index: 500;
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
}

.logo {
	height: 50px; /* Adjust as needed */
}

.lock-banner {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 10px 0;
	padding: 10px 14px;
	background: #fff3cd;
	border: 1px solid #ffe69c;
	border-radius: 6px;
	color: #664d03;
	font-size: 14px;
}
.lock-banner i {
	color: #b45309;
}

.icons {
	display: flex;
	align-items: center;
	gap: 14px; /* Space between icons/groups */
}

.icon-divider {
	width: 1px;
	height: 22px;
	background: #d0d0d0;
	flex-shrink: 0;
}

.icon-item {
	font-size: 24px; /* Icon size */
	color: #333; /* Default color */
	text-decoration: none; /* Remove underline */
	transition: color 0.3s ease-in-out; /* Smooth transition */
}

.icon-item:hover {
	color: #007bff; /* Highlight color on hover */
}

/* Quiet toolbar action buttons - used in the edit-article banner and the
   preview panel header. One accent-filled ".toolbar-btn--primary" per view
   (Save); everything else stays a low-contrast ghost button so it doesn't
   compete with it - tooltips (title attr) carry the label instead of text. */
.toolbar-btn {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	background: transparent;
	border: none;
	border-radius: 8px;
	padding: 6px 10px;
	color: #5f6876;
	font-size: 13px;
	font-weight: 500;
	cursor: pointer;
	text-decoration: none;
	line-height: 1.2;
	transition: background-color 0.15s ease-out, color 0.15s ease-out;
}

.toolbar-btn i {
	font-size: 16px;
}

.toolbar-btn:hover {
	background: #eef0f4;
	color: #021f51;
}

.toolbar-btn.active {
	background: #e3ebfe;
	color: #0053e2;
}

.toolbar-btn--primary {
	background: #3b73f5;
	color: #fff;
}

.toolbar-btn--primary:hover {
	background: #0053e2;
	color: #fff;
}

.toolbar-btn--primary:disabled {
	opacity: 0.5;
	cursor: not-allowed;
	background: #3b73f5;
	color: #fff;
}

.toolbar-btn--secondary {
	background: #e9ecef;
	color: #495057;
}

.toolbar-btn--secondary:hover {
	background: #dee2e6;
	color: #21262c;
}

.preview-container {
	position: fixed;
	top: 0;
	right: -350px; /* Start offscreen */
	width: 320px;
	height: 100%;
	background: white;
	box-shadow: -2px 0 5px rgba(0, 0, 0, 0.2);
	transition: right 0.3s ease-in-out;
	overflow: hidden;
	z-index: 1000;
	border-left: 2px solid #ccc;
}

.preview-container.open {
	right: 0; /* Slide into view */
}

.preview-container .close-button {
	position: absolute;
	top: 10px;
	right: 15px;
	background: #f44336;
	color: white;
	border: none;
	border-radius: 50%;
	width: 20px;
	height: 20px;
	font-size: 18px;
	text-align: top;
	line-height: 0px;
	cursor: pointer;
	z-index: 1001; /* Higher than the preview container */
}

.story-preview-icons {
	position: absolute;
	top: -1px; /* Moves icons higher */
	right: 12px; /* Aligns icons to the right */
	display: flex;
	gap: 5px; /* Space between icons */
}

.story-preview-icons i {
	cursor: pointer;
	font-size: 18px;
	color: #666666;
	padding: 5px;
	border-radius: 3px;
	transition: background 0.2s ease-in-out, color 0.2s ease-in-out;
}

.story-preview-icons i:hover {
	color: #fff;
	background: rgba(0, 0, 0, 0.5);
}

/* Lower Layout */
.lower-container {
display: flex;
margin-top: 0px;
margin-right: 0px;
/* Fill whatever's left below .banner - flex (see .main-container:has(.lower-container)
   below), not a hardcoded "100vh - 60px" like this used to be: the banner's
   real rendered height is ~100px on desktop and taller still once it wraps
   to multiple lines on mobile (see the max-width:640px rule), so a fixed
   60px was always wrong and silently overflowed the viewport by the
   difference - overflow that had nowhere to go but the whole document,
   making html/body scroll and dragging the banner and #results-toolbar
   out of view along with it, instead of only the intended inner
   #search-results-container scrolling. */
flex: 1 1 auto;
min-height: 0;
overflow: hidden;
background-color: #f9f9f9;

}

/* Main Layout */
.main-container {
margin-right: 0px;
}

/* Scoped to :has(.lower-container) so this only ever applies to entries.html's
   layout (banner + lower-container) - edit.html/edit-image.html also use
   .main-container but with different children, and are unaffected. */
.main-container:has(.lower-container) {
display: flex;
flex-direction: column;
height: 100vh;
}

/* When the slide-out panel is visible, change the margin-right */
.main-container.panel-visible {
	margin-right: 400px; /* Adjust the margin to make space for the panel */
}

.main-container.shrink {
    margin-right: 750px; /* Shrink by the same width as the preview panel (.preview-panel) */
}

/* Sidebar xx*/
.sidebar-container {
	/* No explicit width - sizes itself to its two children's combined width
	   (.sidebar-rail + .sidebar-panel) instead of a hardcoded number that
	   silently goes stale (and clips/overlaps the content area) every time
	   either child's own width changes, which is exactly what happened here. */
	flex: none;
	background-color: #f4f4f4;
	display: flex;
	transition: width 0.2s ease-out, transform 0.3s ease-in-out;
	border-right: 1px solid #ddd;
}

/* Collapsing hides just .sidebar-panel's width, leaving the rail itself
   always visible/clickable - a separate, desktop-usable concept from
   toggleMobileSidebar()'s full slide-away drawer below 680px. */
.sidebar-container.panel-collapsed {
	width: 42px;
}

.sidebar-header {
	background-color: #ddd;
	padding: 0px;
	text-align: center;
}



/* Vertical rail: always visible regardless of .sidebar-panel's collapsed
   state, so every panel (and the collapse control) stays reachable in one
   click no matter what's currently showing. */
.sidebar-rail {
	width: 42px;
	flex: none;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 4px;
	padding: 8px 0;
	background-color: #eeeeee;
	border-right: 1px solid #ddd;
}

.rail-btn, .rail-collapse-btn {
	width: 32px;
	height: 32px;
	border: none;
	border-radius: 6px;
	background-color: transparent;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 15px;
	color: #5f666d;
	transition: background-color 0.15s, color 0.15s;
}

.rail-btn:hover, .rail-collapse-btn:hover {
	background-color: #e0e0e0;
}

.rail-btn.is-active {
	background-color: #dce8fc;
	color: #1e5fe0;
}

.rail-spacer {
	flex: 1;
}

.rail-collapse-btn {
	height: 26px;
	font-size: 12px;
	color: #9aa0a7;
}

.rail-collapse-btn i {
	transition: transform 0.18s ease-out;
}

.sidebar-container.panel-collapsed .rail-collapse-btn i {
	transform: rotate(180deg);
}

/* The part of the sidebar that actually collapses - the rail above stays put. */
.sidebar-panel {
	width: 242px;
	min-width: 0; /* flex items default to min-width:auto, letting content's
	                 intrinsic size override the explicit width above -
	                 browsers can disagree on the result, so pin it. */
	flex: none;
	overflow-y: auto;
	overflow-x: hidden;
	transition: opacity 0.15s ease-out;
}

.sidebar-container.panel-collapsed .sidebar-panel {
	width: 0;
	opacity: 0;
	pointer-events: none;
}



.sidebar {
	padding: 25px 15px 15px 10px;
}
.sidebar-searches {
	padding: 25px 25px 25px 10px;
	line-height: 28px;
}

.sidebar-searches a {
	text-decoration: none;
	color: black;
}

.global-search-panel {
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.global-search-input {
    width: 100%;
    padding: 7px 10px;
    border: 1px solid #ccc;
    border-radius: 4px;
    font-size: 14px;
    box-sizing: border-box;
}

.global-search-section-label {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    color: #888;
    margin-top: 4px;
}

.global-search-fields,
.global-search-types {
    display: flex;
    flex-direction: column;
    gap: 5px;
    font-size: 14px;
}

.global-search-fields label,
.global-search-types label {
    display: flex;
    align-items: center;
    gap: 7px;
    cursor: pointer;
}

.global-search-types label:has(input:disabled) {
    color: #bbb;
    cursor: default;
}

.global-search-btn {
    margin-top: 6px;
    padding: 8px;
    background-color: #333;
    color: #fff;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 14px;
    width: 100%;
}

.global-search-btn:hover {
    background-color: #555;
}


/* Collapsed Sidebar */
.sidebar-container.collapsed {
	transform: translateX(-100%);
}

/* Content Section */
.content-container {
	flex: 1;
	/* Without this, a flex item's default min-width is "auto" (its content's
	   own min-content size, not 0) - #results-table can be very wide, and
	   that width demand bubbles up through this now-flex-column container to
	   .lower-container's own flex row, squeezing .sidebar-container below
	   its set 250px instead of letting this container's own overflow-x:auto
	   (on .stories-container) handle the excess width like it's meant to. */
	min-width: 0;
	padding: 0px;
	/* #page-data and #search-results-container (below) used to size
	   themselves via a hardcoded "height: calc(100% - 60px)" guess at how
	   tall #results-toolbar + the rest above them was - wrong in the same
	   way .lower-container's old banner-height guess was wrong, and for the
	   same reason: it silently overflowed THIS container by the difference,
	   making it independently scrollable too and carrying #results-toolbar
	   out of view right along with whichever of those two the user was
	   scrolling. display:flex + flex:1 on each of them (they're toggled via
	   display:none/block so only one is ever actually competing for space)
	   replaces the guess - overflow-y:auto moves to them individually so
	   only the intended inner content scrolls, not this container itself. */
	display: flex;
	flex-direction: column;
}




/* Stories */
.stories-container {
	background-color: #f9f9f9;
	padding: 5px 25px 25px 25px;
	border: 0px solid #ddd;
	border-radius: 5px;
	flex: 1 1 auto;
	min-height: 0;
	/* Overrides the harmless-until-now ".stories-container { margin: 0 auto; }"
	   rule above (kept for the .story-title/.story-meta users elsewhere) -
	   that never did anything visible while this was a plain block (already
	   full-width, so centering was a no-op), but a flex item with an auto
	   margin on the cross axis stops stretching to fill it and gets
	   symmetric leftover space instead (a CSS flexbox rule, not a bug in
	   this file) - which is exactly the "big gaps, not filling the area"
	   the user saw once .content-container became a flex container above. */
	margin: 0;
	overflow-y: auto;
	/* #results-table is wider than this container once there are enough
	   columns, and previously had no overflow-x here to catch that - the
	   excess just silently rendered past this container's edge with nothing
	   clipping or scrolling it, so opening the slide-out panel (which
	   shrinks .main-container via margin-right, not this container's own
	   width) didn't reflow the table at all; it just let the panel's own
	   opaque background visually cover whatever of the table fell in its
	   zone, including the action icons. A real scrollbar here fixes that -
	   and gives .script-action-cell's sticky positioning (below) an actual
	   scroll viewport to stick within. */
	overflow-x: auto;
	/* Stop horizontal scroll from chaining into the page once this
	   container hits either end of its own scrollable content - otherwise
	   a drag that continues past the table's real last column keeps going
	   into the surrounding page (see the html/body overscroll-behavior-x
	   rule in the mobile block, which this backs up at the source). */
	overscroll-behavior-x: contain;
}



.page-container {
	background-color: #f9f9f9;
	padding: 15px;
	border: 0px solid #ddd;
	border-radius: 5px;
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
}




/* Tree container */
.tree {
	padding: 0;
	margin: 0;
}

/* Recently visited queues dropdown, reachable from the banner regardless of
   which sidebar panel or view is active - so a pinned page doesn't force a
   re-hunt through the tree to get back to a queue's article list. */
.recent-queues-dropdown {
	position: fixed;
	z-index: 9999;
	background: #fff;
	border: 1px solid #ccc;
	border-radius: 5px;
	box-shadow: 2px 2px 10px rgba(0,0,0,0.2);
	min-width: 180px;
	max-width: 280px;
	padding: 4px 0;
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
	font-size: 13px;
}
.recent-queues-dropdown-item {
	padding: 6px 14px;
	cursor: pointer;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.recent-queues-dropdown-item:hover {
	background: #f0f0f0;
}
.recent-queues-dropdown-empty {
	padding: 2px 14px 8px;
	color: #888;
}
.recent-queues-dropdown-label {
	padding: 6px 14px 2px;
	font-size: 11px;
	text-transform: uppercase;
	letter-spacing: 0.03em;
	color: #888;
}
.recent-queues-dropdown-label:not(:first-child) {
	border-top: 1px solid #eee;
	margin-top: 4px;
}
.recent-queues-dropdown-clear {
	margin-top: 4px;
	padding: 8px 14px;
	border-top: 1px solid #eee;
	cursor: pointer;
	color: #888;
	text-align: center;
}
.recent-queues-dropdown-clear i {
	font-size: 21px;
}
.recent-queues-dropdown-clear:hover {
	background: #f0f0f0;
}

/* Folder item (folders and subfolders) */
.folder-item {
	display: block;  /* Ensure folders stack vertically */
	line-height: 28px;
	position: relative;
}

/* Row of toggle-icon + name for one queue level, kept separate from
   .folder-item itself so deeply-nested .children (a block sibling below)
   don't get pulled into this flex row too. min-width:0 is what actually lets
   .folder shrink below its text's natural width - a flex item's default
   min-width is auto (= content size), which silently defeats text-overflow. */
.folder-row {
	display: flex;
	align-items: center;
	gap: 4px; /* flex swallows the whitespace between .toggle and .folder that a plain inline layout rendered as a space */
	min-width: 0;
}

/* Without flex-shrink:0, deep nesting (very little width left in the row)
   was shrinking .toggle itself below the combined width of its two icons -
   forcing them to wrap onto their own line inside it instead of .folder
   being the only thing that gives way. */
.folder-row .toggle {
	flex-shrink: 0;
}

/* Folder name */
.folder {
	cursor: pointer;
}

/* Single line with an ellipsis instead of wrapping, since at deep nesting
   levels .folder-row's cumulative padding-left (via .folder-item) leaves
   little room and a wrapped name collided with the next row's fixed
   line-height. Full name still available via the title attribute (see
   render_queue() macro). Scoped to .folder-row's own .folder (the queues
   tree) rather than the base .folder class, which the separate Publication/
   Edition/Zone book-search tree also uses without this flex wrapper. */
.folder-row .folder {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}

.fa-chevron-toggle {
    transition: transform 0.2s ease;
    font-size: 0.75em;
    margin-right: 2px;
}

.fa-chevron-toggle.open {
    transform: rotate(90deg);
}

/* Leaf folders (no children) still render the chevron icon, just invisible -
   visibility:hidden keeps its layout space reserved so the folder icon next
   to it lines up with every other row's folder icon, whether or not that
   row happens to have a chevron. */
.fa-chevron-toggle--spacer {
    visibility: hidden;
}

/* Full Book search icon - sits at the right edge of an edition/zone row,
   hidden until that row is hovered, so the tree stays uncluttered at rest
   (replaces a permanently-visible "Search Full Books" button that used to
   sit at the bottom of the sidebar regardless of what's selected). */
.folder-book-search-icon {
    display: inline-block;
    visibility: hidden;
    opacity: 0;
    position: absolute;
    right: 8px;
    top: 0;
    color: #5f6876;
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 6px;
    transition: background-color 0.15s ease-out, color 0.15s ease-out;
}
/* visibility/opacity instead of display:none<->inline-block - Firefox was
   showing a hairline rendering artifact next to hovered publication-tree
   rows, which that display toggle (on an absolutely-positioned,
   border-radius'd element) is a known trigger for; Chrome never showed it,
   which is why this needed reporting rather than being caught by testing
   here. */
.folder-item:hover > .folder-book-search-icon {
    visibility: visible;
    opacity: 1;
}
.folder-book-search-icon:hover {
    background: #eef0f4;
    color: #0053e2;
}

/* Subfolders */
.children {
	display: none;  /* Hide by default */
	/* This is now the only source of per-level indentation (.folder-item's
	   own padding-left, which used to combine with this margin for a ~15px
	   step, was removed to pull the top level left) - matches that original
	   ~15px step on its own so nested levels don't go visually flat. */
	margin-left: 15px;
}

/* Collapsed state - hide children by default */
	.collapsed .children {
	display: none;
}



.loading-spinner {
	position: fixed;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	font-size: 48px;
	color: pink;
}

/* Status card for multi-second waits (_showBusyCard() in atex-entries.js):
   spinner and message together in one place instead of a big bare spinner
   with a small detached caption under it. */
.busy-card {
	position: fixed;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	z-index: 10000;
	display: flex;
	align-items: center;
	gap: 14px;
	padding: 16px 22px 16px 18px;
	background: #fff;
	border-radius: 10px;
	box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
	max-width: calc(100vw - 32px);
}
.busy-card-spinner {
	font-size: 34px;
	color: pink;
	flex: 0 0 auto;
}
.busy-card-msg {
	font-size: 15px;
	font-weight: 600;
	color: #222;
}
.busy-card-elapsed {
	font-size: 12px;
	color: #777;
	margin-top: 2px;
	font-variant-numeric: tabular-nums;
}

.no-stories {
	text-align: left;
	color: #888;
	font-size: 14px;
	padding: 20px;
	font-style: italic;
}

/* Modern table styling */
#results-table {
	width: 100%;
	border-collapse: separate; /* Allows spacing between rows */
	border-spacing: 0 3px; /* Adds spacing between rows */
	border-radius: 12px;
	/* Was overflow:hidden (just for the rounded corners) - but that also
	   makes this table itself the nearest "scrolling box" ancestor for any
	   sticky-positioned cell inside it (its content already fits its own
	   box, so nothing ever visibly scrolls here) - confirmed live that this
	   pre-empted .script-action-cell's position:sticky from ever reaching
	   .stories-container (the real overflow-x:auto ancestor, added
	   alongside sticky for exactly this), silently making it act as if
	   plain static. Removed rather than kept "just in case" since the
	   rounded corners were barely visible anyway once individual rows got
	   their own border+spacing styling below. */
	background-color: #f9f9f9; /* Light background */
	box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); /* Adds a subtle shadow */
}

#results-table thead {
	background-color: #f9f9f9; 
	color: black;
}

#results-table tbody tr {
	background-color: white; /* White rows */
	transition: background-color 0.2s ease-in-out; /* Smooth hover effect */
	border: 1px solid #ddd; /* Fine border around rows */
}

#results-table tbody tr:hover {
	background-color: #f2f2f2; /* Light grey on hover */
}

#results-table tbody tr td:first-child {
	text-align: center; /* Center-align the icon column */
	width: 50px; /* Narrow icon column */
}

#results-table tbody tr td {
	border-bottom: 1px solid #ddd; /* Add horizontal lines between rows */
}

/* Prevent text wrapping in table cells */
#results-table th, #results-table td {
	text-align: left;
	padding: 6px 6px;
	white-space: nowrap; /* Prevent text wrapping */
}

/* For longer text, allow truncation with ellipsis */
#results-table td {
	overflow: hidden; /* Hide text overflow */
	text-overflow: ellipsis; /* Show ellipsis for overflowed text */
	max-width: 200px; /* Optional: Adjust the max-width as needed */
}

#results-table .text-primary {
	color: #666666; /* Primary color for icons */
}

/* Increase icon size for story, image, etc. */
#results-table td i {
	font-size: 20px; /* Adjust the size as needed */
}






#slide-out-panel {
	position: fixed;
	top: 0;
	right: -400px; /* Initially hidden */
	width: 400px;
	height: 100%;
	background: #f9f9f9;
	box-shadow: -3px 0 5px rgba(0, 0, 0, 0.2);
	transition: right 0.3s ease;
	overflow-y: auto;
	overflow-x: hidden;
	z-index: 1000;
}

#slide-out-panel.visible {
	right: 0; /* Show the panel */
}

/* User-toggled show/hide (toggleSlideOutPanelVisibility(), atex-entries.js) -
   layered on top of .visible/.panel-visible rather than replacing them, same
   approach as edit.html's body.hide-preview-panel. Higher specificity than
   the plain rules above (an extra ancestor class) wins without !important. */
body.hide-slide-out-panel #slide-out-panel.visible {
	right: -400px;
}
body.hide-slide-out-panel .main-container.panel-visible {
	margin-right: 0;
}

/* Always-visible handle attached to the slide-out panel's left edge - see
   #slide-out-panel-handle in entries.html. Sits outside #slide-out-panel so
   the panel's own slide transform never carries it off-screen; tracks the
   panel's own right offset (400px open, 0 hidden) so it always hugs
   whichever edge is currently showing. Same pattern as edit.html's
   #preview-panel-handle. */
#slide-out-panel-handle {
	/* Unlike edit.html's preview panel (populated automatically as soon as
	   the editor loads), this panel only ever shows something once the user
	   actually selects an item - most of the time nothing is selected at
	   all, and a handle offering to "reveal" an empty panel would be pure
	   clutter. Stays hidden until a sibling #slide-out-panel actually has
	   .visible (below), which - unlike its on-screen position - this hide
	   toggle deliberately never removes, precisely so this selector keeps
	   working while hidden. */
	display: none;
	position: fixed;
	top: 50%;
	transform: translateY(-50%);
	right: 400px;
	width: 22px;
	height: 64px;
	align-items: center;
	justify-content: center;
	background: #e9ecef;
	border: none;
	border-radius: 6px 0 0 6px;
	color: #495057;
	cursor: pointer;
	z-index: 1001; /* above #slide-out-panel's 1000 */
	box-shadow: -2px 0 5px rgba(0, 0, 0, 0.15);
	transition: right 0.3s ease-in-out, background-color 0.15s ease-out;
}
#slide-out-panel.visible ~ #slide-out-panel-handle {
	display: flex;
}
#slide-out-panel-handle:hover {
	background: #dee2e6;
	color: #21262c;
}
#slide-out-panel-handle i {
	transition: transform 0.18s ease-out;
}
body.hide-slide-out-panel #slide-out-panel-handle {
	right: 0;
}
body.hide-slide-out-panel #slide-out-panel-handle i {
	transform: rotate(180deg);
}

/* Desktop closes the panel via the edge handle above; shown only under the
   640px mobile override below, where that handle is hidden instead. */
#mobile-close-slide-out-btn {
	display: none;
}

/* Bottom-sheet drag handle, the inline status dot+icons, and the
   preview's "Show details" toggle - all mobile-only, see the 640px
   override below for their real styling. */
#slide-out-sheet-handle {
	display: none;
}
#preview-status-inline {
	display: none;
}
.preview-details-toggle {
	display: none;
}

.page-preview-spinner-badge {
	position: absolute;
	/* Just below the corner's page-number/buttons row (.page-card-tools), so
	   neither hides the other - and above the box overlays (9999) and that
	   row's full-screen layer (10003). Click-through, so it blocks nothing. */
	top: 38px;
	left: 8px;
	z-index: 10004;
	width: 34px;
	height: 34px;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(255, 255, 255, 0.85);
	border-radius: 50%;
	box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
	pointer-events: none;
}

.page-preview-spinner-badge i {
	font-size: 18px;
	color: #ff69b4;
}

#slide-out-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding-left: 15px;
	padding-right: 15px;
	padding-top: 0px;
	padding-bottom: 0px;
	background: #f4f4f4;
	color: black;
	font-size: 13 px;
	font-weight: bold;
	/* Stay at its own natural size within .preview-panel's column flex (see
	   .preview-panel) - it must not shrink or grow, so #preview-content's
	   flex:1 gets exactly "everything else" to work with. Inert on the
	   entries/queue page's own #slide-out-header, whose parent isn't a flex
	   container. */
	flex: 0 0 auto;
}

#slide-out-content {
	padding: 20px;
	font-size: 12px;
	line-height: 1.5;
}

/* Stories/Images/On Page assignment lists - match the results-table's own
   text size (html, body font-size above) rather than the rest of the
   preview panel's smaller 12px. */
.assignments-list-panel {
	font-size: 14px;
}
/* One line per name, truncated with an ellipsis, instead of wrapping onto a
   second line - #slide-out-panel is a fixed 400px with overflow-x:hidden,
   so a plain nowrap+ellipsis (needs block-level display, li defaults to
   list-item) is enough without a hardcoded max-width. */
.assignments-list-panel li {
	display: block;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}

/* Icon-only, no visible label - but same grey pill look as the editor's own
   "Close" button (.toolbar-btn--secondary) rather than a stark black X. */
#close-panel-btn {
	background: #e9ecef;
	border: none;
	border-radius: 8px;
	color: #495057;
	font-size: 16px;
	cursor: pointer;
	transition: background-color 0.15s ease-out, color 0.15s ease-out;
}

#close-panel-btn:hover {
	background: #dee2e6;
	color: #21262c;
}

.dataTables_filter {
	display: none !important;
}



/* Container for images */
.image-gallery {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
	gap: 16px;
	padding: 20px;
	max-width: 1200px;
	margin: auto;
}

/* Image wrapper */
.image-card {
	position: relative;
	overflow: hidden;
	border-radius: 12px;
	box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
	transition: transform 0.3s ease, box-shadow 0.3s ease;
}

/* Image itself */
.image-card img {
	width: 100%;
	height: auto;
	display: block;
	border-radius: 12px;
	transition: transform 0.3s ease, filter 0.3s ease;
}

/* Hover effects */
.image-card:hover {
	transform: translateY(-5px);
	box-shadow: 0 12px 24px rgba(0, 0, 0, 0.2);
}

.image-card:hover img {
	filter: brightness(90%);
	transform: scale(1.05);
}

/* Overlay effect */
.image-overlay {
	position: absolute;
	bottom: 0;
	left: 0;
	width: 100%;
	background: rgba(0, 0, 0, 0.6);
	color: white;
	padding: 10px 15px; /* Added padding for spacing */
	text-align: left; /* Keep it aligned properly */
	font-size: 14px;
	opacity: 0;
	transform: translateY(10px);
	transition: opacity 0.3s ease, transform 0.3s ease;
	box-sizing: border-box; /* Ensures padding doesn't make the element wider */
}

/* dir="auto" resolves Hebrew/Arabic captions RTL - text-align: left above
   would otherwise leave RTL text reading right-to-left but stuck flush left */
.image-overlay:dir(rtl) {
	text-align: right;
}

/* dir="auto" on the login username/password fields correctly flips whatever
   is actually TYPED to RTL, but an empty field has nothing for "auto" to
   read - browsers don't fall back to the placeholder text for that, so a
   Hebrew placeholder still rendered left-aligned. Scoped to ::placeholder
   only, so the real typed value's own direction (still governed by
   dir="auto" on the input itself) is untouched. */
.rtl-placeholder::placeholder {
	direction: rtl;
	text-align: right;
}

.image-card:hover .image-overlay {
	opacity: 1;
	transform: translateY(0);
}


/* Page wrapper */
.page-card {
	position: relative;
	overflow: hidden;
	border-radius: 12px;
	box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
	transition: transform 0.3s ease, box-shadow 0.3s ease;
}

/* Page itself */
.page-card img {
	width: 100%;
	height: auto;
	display: block;
	border-radius: 12px;
	transition: transform 0.3s ease, filter 0.3s ease;
}


.page-preview {
	position: relative; /* or static */
	z-index: 1; /* Lower than the overlay */
}

.page-preview-container {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	pointer-events: none; /* Prevent interference with image interactions */
}

/* Page-number badge + (full screen only) overlay toggle, side by side in
   the page card's top-left corner. */
.page-card-tools {
	position: absolute;
	top: 8px;
	left: 8px;
	z-index: 15; /* above the page image, below .box (9999) / .area-box (9000) */
	display: flex;
	align-items: center;
	gap: 4px;
	pointer-events: none;
}
.page-card-tools .page-number-badge {
	position: static;
}
.page-overlay-toggle {
	display: none;
}
#page-fullscreen .page-card-tools {
	z-index: 10003; /* the toggle must stay clickable above the box overlays */
}
#page-fullscreen .page-overlay-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	pointer-events: auto;
	border: none;
	cursor: pointer;
	background: rgba(0, 0, 0, 0.65);
	color: #fff;
	font-size: 12px;
	line-height: 1;
	padding: 4px 7px;
	border-radius: 4px;
}
#page-fullscreen .page-overlay-toggle:hover {
	background: rgba(0, 0, 0, 0.85);
}
.page-number-badge {
	position: absolute;
	top: 8px;
	left: 8px;
	z-index: 15; /* above the page image, below .box (9999) / .area-box (9000) */
	background: rgba(0, 0, 0, 0.65);
	color: #fff;
	font-size: 12px;
	font-weight: bold;
	line-height: 1;
	padding: 4px 8px;
	border-radius: 4px;
	pointer-events: none;
}

/* Two or more pages sharing the same page number in the same zone render as
   one card with a couple of offset "pages" peeking out behind it, cycled
   with Ctrl+Shift+click (see _cycleStackedPageCard) - the badge's own
   "(n/total)" suffix (_applyStackVisual) is the more precise indicator,
   this is just the at-a-glance visual. */
.clickable-page.page-stack img.page-card {
	box-shadow:
		4px 4px 0 0 #fff,
		4px 4px 0 1px #bbb,
		8px 8px 0 0 #fff,
		8px 8px 0 1px #999;
}

.box {
	pointer-events: auto !important; /* Ensure hovering works */
	z-index: 9999 !important; /* Ensure it's above everything */
	position: absolute;
	border: 1px pink;
	background: rgba(164, 196, 0, 0.2); /* default/fits - also the fallback for Image boxes and anything fit_state couldn't be fetched for */
}

/* Story copyfit state (hnj_depth) - see _ensureFitStatesForPage() in
   atex-entries.js. Only ever applied on top of the default green above, for
   boxes fit_state actually came back for. */
.box.box--fits-overset {
	background: rgba(220, 53, 69, 0.15);
}
.box.box--fits-underset {
	background: rgba(13, 110, 253, 0.12);
}

/* Toggled by #toggle-overlay-btn (toggleBoxOverlay() in atex-entries.js) -
   hides just the tint, not the box itself, so drag/drop targeting and the
   name/type/coords tooltip keep working while it's off. */
#slide-out-panel.overlay-hidden .box {
	background: transparent;
}

/* Page preview zoom - see _pzApply() etc. in atex-entries.js. The layer
   holding the image + box overlay is scaled/panned by a transform; the
   .page-card (overflow:hidden) clips it. */
.page-zoom-layer {
	position: relative;
	transform-origin: 0 0;
}
.page-card.pz-zoomed {
	cursor: grab;
}
.page-card.pz-zoomed.pz-dragging {
	cursor: grabbing;
}
.page-zoom-controls {
	display: inline-flex;
	align-items: center;
	gap: 1px;
	border: 1px solid #ccc;
	border-radius: 6px;
	background: #fff;
	padding: 1px;
}
.page-zoom-controls button {
	border: none;
	background: none;
	color: #333;
	cursor: pointer;
	padding: 3px 6px;
	font-size: 13px;
	line-height: 1;
	border-radius: 4px;
}
.page-zoom-controls button:hover {
	background: #eef2f7;
}
.page-zoom-controls .page-zoom-pct {
	min-width: 44px;
	font-size: 12px;
	color: #555;
	font-variant-numeric: tabular-nums;
}

/* Full-screen page view (openPageFullscreen()). Just above the preview panel
   and its handle (1000-1001) and below everything that can open from inside
   it - dialogs like the headline pick-list (2000), popups/toasts (9999) and
   the busy card (10000). At 5000 it hid the headline pick-list. */
#page-fullscreen {
	position: fixed;
	inset: 0;
	z-index: 1500;
	background: rgba(20, 24, 31, 0.88);
	display: flex;
	flex-direction: column;
}
#page-fullscreen .page-fs-body {
	flex: 1 1 auto;
	overflow: auto;
	padding: 24px;
}
/* Page(s) + toolbar side by side, centred together */
#page-fullscreen .page-fs-stage {
	display: flex;
	justify-content: center;
	align-items: flex-start;
	gap: 12px;
	min-width: min-content;
}
/* Slim vertical toolbar on the page's right - stays in view while a
   zoomed page scrolls */
/* Toolbar + the page's assignments list under it, as one column */
#page-fullscreen .page-fs-side {
	position: sticky;
	top: 0;
	flex: 0 0 auto;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 8px;
}
#page-fullscreen .page-fs-toolbar {
	flex: 0 0 auto;
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: 2px;
	padding: 4px;
	background: #fff;
	border-radius: 8px;
	box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
}
#page-fullscreen .page-fs-toolbar button {
	border: none;
	background: none;
	color: #333;
	cursor: pointer;
	padding: 7px 6px;
	font-size: 14px;
	line-height: 1;
	border-radius: 5px;
}
#page-fullscreen .page-fs-toolbar button:hover {
	background: #eef2f7;
}
#page-fullscreen .page-fs-toolbar .page-fs-close {
	font-size: 18px; /* the toolbar's only button now - full screen has no zoom */
}
#page-fullscreen .page-fs-toolbar .page-zoom-pct {
	font-size: 11px;
	color: #555;
	font-variant-numeric: tabular-nums;
	min-width: 40px;
}
/* Content palette on the page's left: icon rail + fold-out queue/search
   list (see _pageFsPaletteHtml in atex-entries.js). Same white card look as
   the toolbar; the panel's fixed width keeps _pageFsFitCards predictable. */
#page-fullscreen .page-fs-palette {
	position: sticky;
	top: 0;
	flex: 0 0 auto;
	display: flex;
	align-items: stretch;
	background: #fff;
	border-radius: 8px;
	box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
	overflow: hidden;
	max-height: calc(100vh - 48px);
}
#page-fullscreen .pfp-rail {
	display: flex;
	flex-direction: column;
	gap: 2px;
	padding: 4px;
}
#page-fullscreen .pfp-rail-btn {
	border: none;
	background: none;
	color: #333;
	cursor: pointer;
	width: 32px;
	height: 32px;
	font-size: 14px;
	border-radius: 5px;
}
#page-fullscreen .pfp-rail-btn:hover {
	background: #eef2f7;
}
#page-fullscreen .pfp-rail-btn[aria-pressed="true"] {
	background: #e7f0ff;
	color: #084298;
}
#page-fullscreen .pfp-panel:not([hidden]) {
	width: 250px;
	display: flex;
	flex-direction: column;
	min-height: 0;
	border-left: 1px solid #e3e3e3;
}
#page-fullscreen .pfp-head {
	display: flex;
	flex-direction: column;
	gap: 6px;
	padding: 8px 10px 6px;
	border-bottom: 1px solid #e3e3e3;
}
#page-fullscreen .pfp-source,
#page-fullscreen .pfp-filter {
	width: 100%;
	box-sizing: border-box;
	font: inherit;
	font-size: 13px;
	padding: 4px 6px;
	border: 1px solid #ccd3dc;
	border-radius: 5px;
	background: #fff;
	color: #212529;
}
#page-fullscreen .pfp-tools {
	display: flex;
	align-items: center;
	gap: 4px;
}
#page-fullscreen .pfp-tgl {
	width: 30px;
	height: 26px;
	border: 1px solid #ccd3dc;
	border-radius: 5px;
	background: #fff;
	color: #555;
	cursor: pointer;
	font-size: 13px;
}
#page-fullscreen .pfp-tgl:hover {
	background: #eef2f7;
}
#page-fullscreen .pfp-tgl[aria-pressed="true"] {
	background: #e83e8c;
	border-color: #e83e8c;
	color: #fff;
}
#page-fullscreen .pfp-length-chip:not([hidden]) {
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 3px 4px 3px 8px;
	border-radius: 12px;
	background: #e7f0ff;
	color: #084298;
	font-size: 13px; /* same as the palette list */
	font-variant-numeric: tabular-nums;
}
#page-fullscreen .pfp-length-text {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}
#page-fullscreen .pfp-length-clear {
	flex: 0 0 auto;
	border: none;
	background: none;
	color: #084298;
	cursor: pointer;
	padding: 0 4px;
	font-size: 12px;
}
#page-fullscreen .pfp-count {
	margin-left: auto;
	font-size: 13px; /* same as the palette list */
	color: #6c757d;
	font-variant-numeric: tabular-nums;
}
#page-fullscreen .pfp-list {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	padding: 4px;
	font-size: 13px;
}
#page-fullscreen .pfp-row {
	display: flex;
	align-items: center;
	gap: 7px;
	padding: 4px 6px;
	border-radius: 5px;
	cursor: grab;
}
#page-fullscreen .pfp-row:hover {
	background: #eef2f7;
}
#page-fullscreen .pfp-icon {
	flex: 0 0 14px;
	color: #888;
	text-align: center;
}
#page-fullscreen .pfp-name {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}
#page-fullscreen .pfp-dot {
	position: static;
	flex: 0 0 auto;
	display: inline-block;
	width: 7px;
	height: 7px;
	border-radius: 50%;
}
/* Similar-length filter's spotlight (_pfpApplySpotlight): a clear window
   over the selected story/area whose huge shadow greys the rest of the page
   (clipped by .page-card's overflow:hidden). Above the box overlays but
   click-through, so hovering, dropping and the bin keep working. */
#page-fullscreen .pfp-spotlight {
	position: absolute;
	z-index: 10002;
	pointer-events: none;
	border-radius: 4px;
	box-shadow: 0 0 0 100000px rgba(20, 24, 31, 0.55);
}
#page-fullscreen .pfp-spotlight.pfp-spotlight-full {
	inset: 0;
	border-radius: 0;
	box-shadow: none;
	outline: none;
	background: rgba(20, 24, 31, 0.55);
}
/* Results list's associated-pictures diamond, inline in a palette row
   rather than pinned to an icon's corner. */
#page-fullscreen .pfp-row .pfp-assoc {
	position: static;
	flex: 0 0 auto;
	width: 7px;
	height: 7px;
	margin: 0;
	box-shadow: none;
	pointer-events: auto; /* so its tooltip shows */
}
/* The row's two right-hand icon columns (pictures diamond, on-a-page dot):
   fixed width even when empty, so names all end at the same point. */
#page-fullscreen .pfp-row .pfp-slot {
	flex: 0 0 11px;
	display: flex;
	align-items: center;
	justify-content: center;
}
#page-fullscreen .pfp-list.pfp-grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	/* Rows keep their full height and the list scrolls - without this a long
	   queue squashed every card into a thin strip to fit the panel's height
	   (a grid item with overflow:hidden has no automatic minimum height). */
	grid-auto-rows: max-content;
	gap: 6px;
	padding: 6px;
	align-content: start;
}
#page-fullscreen .pfp-thumb {
	position: relative;
	display: flex;
	flex-direction: column;
	border-radius: 5px;
	overflow: hidden;
	background: #f4f5f7;
	cursor: grab;
}
#page-fullscreen .pfp-thumb img,
#page-fullscreen .pfp-thumb > i {
	flex: 0 0 82px; /* never shrink inside the card's flex column */
	min-height: 82px;
	width: 100%;
	height: 82px;
	object-fit: cover;
	display: block;
}
#page-fullscreen .pfp-thumb > i {
	display: grid;
	place-items: center;
	font-size: 24px;
	color: #aaa;
}
#page-fullscreen .pfp-thumb .pfp-name {
	flex: 0 0 auto;
	padding: 3px 5px;
	font-size: 11px;
}
#page-fullscreen .pfp-thumb .pfp-dot {
	position: absolute;
	right: 5px;
	top: 70px;
	width: 9px;
	height: 9px;
	border: 1px solid #fff;
}
#page-fullscreen .pfp-thumb:hover {
	outline: 2px solid #0d6efd;
}
#page-fullscreen .pfp-empty {
	padding: 14px 8px;
	color: #6c757d;
	font-size: 12px;
	text-align: center;
}
#page-fullscreen .pfp-peek {
	position: fixed;
	z-index: 20000; /* above the page's .box overlays (9999); still inside the overlay's own 1500 */
	width: 240px;
	padding: 10px 12px;
	background: #fff;
	border-radius: 8px;
	box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
	font-size: 12px;
	line-height: 1.4;
	color: #212529;
	pointer-events: none;
}
#page-fullscreen .pfp-peek strong {
	display: block;
	font-size: 13px;
	margin-bottom: 4px;
}
#page-fullscreen .pfp-peek img {
	display: block;
	width: 100%;
	max-height: 150px;
	object-fit: contain;
	margin-top: 4px;
	border-radius: 4px;
}
#page-fullscreen .pfp-peek p {
	margin: 0;
	color: #444;
}
#page-fullscreen .pfp-peek .pfp-peek-caption {
	margin-top: 6px;
	max-height: 7.2em;
	overflow: hidden;
}
#page-fullscreen .pfp-peek .pfp-peek-words {
	margin-top: 6px;
	font-size: 11px;
	color: #6c757d;
	font-variant-numeric: tabular-nums;
}
@media (max-width: 640px) {
	#page-fullscreen .page-fs-palette { display: none; }
}
/* Copy of the panel's .assignments-list-panel - fixed width so the page fit
   (_pageFsFitCards) is predictable, own scroll for long lists. */
#page-fullscreen .page-fs-assignments {
	width: 220px;
	max-height: calc(100vh - 220px);
	overflow-y: auto;
	padding: 6px 10px 8px;
	background: #fff;
	border-radius: 8px;
	box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
	font-size: 13px;
}
#page-fullscreen .page-fs-assignments .assignments-list-panel {
	font-size: 13px;
}
#page-fullscreen .page-fs-assignments strong {
	display: block;
	margin: 6px 0 3px;
}
/* A line's space between the Stories and Images groups */
#page-fullscreen .page-fs-assignments ul + strong {
	margin-top: 1.2em;
}
#page-fullscreen .page-fs-assignments ul {
	margin: 0;
	padding: 0;
	list-style: none;
}
#page-fullscreen .page-fs-assignments li {
	padding: 2px 5px;
	border-radius: 4px;
	cursor: default;
}
#page-fullscreen .page-fs-assignments li[draggable="true"] {
	cursor: grab;
}
#page-fullscreen .page-fs-assignments li.assignment-list-hl {
	background: #fff5d6;
}
#page-fullscreen .box.box--list-hl {
	background: rgba(255, 245, 157, 0.45) !important;
}
@media (max-width: 640px) {
	#page-fullscreen .page-fs-assignments { display: none; }
}
#page-fullscreen .image-gallery {
	max-width: none;
	padding: 0;
	margin: 0; /* base rule's margin:auto would push the toolbar away */
	display: flex;
	flex-wrap: nowrap; /* spread pages side by side, sized to fit by _pageFsFitCards() */
	flex: 0 0 auto;
	justify-content: center;
	align-items: flex-start;
	gap: 24px;
}
#page-fullscreen .page-card {
	flex: 0 0 auto;
	background: #fff;
}
/* 3+ page item: spreads, one under the other (see _pageFsFitCards - each
   card is given grid-column 1 = left page / 2 = right page). */
#page-fullscreen .image-gallery.pfs-spreads {
	display: grid;
	grid-template-columns: auto auto;
	column-gap: 8px;  /* the spine - also in _pageFsFitCards' width sum */
	row-gap: 32px;    /* between spreads */
	justify-content: center;
	align-items: start;
}
#page-fullscreen.overlay-hidden .box {
	background: transparent;
}

/* Unassign-from-page bin at the top-left of a placed story's group of
   boxes - see _addStoryUnassignButtons() in atex-entries.js. Above the
   .box overlays (9999) so it stays clickable over them. Its container
   (.page-preview-container) is pointer-events:none, so like .box it has
   to opt back in or clicks fall straight through it. */
.story-unassign-btn {
	pointer-events: auto !important;
	position: absolute;
	z-index: 10001;
	display: none;
	transform: translate(2px, 2px);
	background: rgba(0, 0, 0, 0.6);
	color: #fff;
	border: none;
	border-radius: 3px;
	/* Same size as the headline wand (updateBoxes: 1em, padding 3px 7px) -
	   both inherit the page overlay container's font size. */
	padding: 3px 7px;
	font-size: 1em;
	line-height: normal; /* as the wand */
	cursor: pointer;
}
.story-unassign-btn.visible {
	display: block;
}
.story-unassign-btn:hover {
	background: #dc3545;
}
.story-unassign-btn:disabled {
	opacity: 0.5;
	cursor: wait;
}

/* "Similar length" beside the bin, and on an empty area - full screen
   only, where the content palette it filters lives. */
.story-unassign-btn.story-length-btn,
.story-unassign-btn.story-length-btn.visible,
.area-length-btn {
	display: none;
}
#page-fullscreen .story-unassign-btn.story-length-btn.visible {
	display: block;
}
/* Right-aligned at the story's top-right, beside the headline wand: its
   `left` (see _addStoryUnassignButtons) is where its right edge sits. */
#page-fullscreen .story-unassign-btn.story-length-btn {
	transform: translate(-100%, 2px);
}
/* In full screen the similar-length button owns the corner, so the headline
   wand (inline-styled right:2px in updateBoxes) sits just to its left. */
#page-fullscreen .headline-wand {
	right: 36px !important;
}
#page-fullscreen .story-unassign-btn.story-length-btn:hover {
	background: #0d6efd;
}
#page-fullscreen .area-length-btn {
	display: block;
	position: absolute;
	top: 2px;
	right: 2px;
	z-index: 2; /* above the area's own sub-boxes and label */
	pointer-events: auto;
	background: rgba(0, 0, 0, 0.6);
	color: #fff;
	border: none;
	border-radius: 3px;
	padding: 3px 7px; /* same size as the headline wand */
	font-size: 1em;
	line-height: normal;
	cursor: pointer;
}
#page-fullscreen .area-length-btn:hover {
	background: #0d6efd;
}

.area-box {
	pointer-events: auto !important;
	z-index: 9000 !important; /* below placed-story .box overlays (9999) */
	position: absolute;
	border: 2px dashed #0d6efd;
	background: rgba(13, 110, 253, 0.08);
	box-sizing: border-box;
	display: flex;
	align-items: flex-start;
	justify-content: flex-start;
}

.area-box.area-box-drag-over {
	background: rgba(13, 110, 253, 0.25);
	border-color: #084298;
}

/* Double-click-to-create-story in progress (create-story-in-area + real
   placement + poll, before navigating to the new story's editor) - dims the
   slot and blocks further clicks so a second double-click can't fire a
   second create while the first is still in flight. */
.area-box.area-box-creating {
	pointer-events: none !important;
	opacity: 0.45;
	cursor: wait;
}

/* Area broken down into its individual boxes (manifest areaLayouts) - the
   area itself becomes a faint outline (still the drop / double-click target)
   and each box inside is drawn on its own, picture boxes with a CM-style X. */
.area-box.area-box-has-layouts {
	border: 1px dotted rgba(13, 110, 253, 0.6);
	background: transparent;
}

.area-box.area-box-has-layouts.area-box-drag-over {
	background: rgba(13, 110, 253, 0.15);
	border-color: #084298;
}

/* Empty picture box inside an area that already has content - sits above the
   placed story's .box overlays (9999), whose text frame usually wraps round
   the picture and would otherwise swallow the drop as a story replace. */
.area-box.area-picture-slot {
	z-index: 10000 !important;
	border: none;
}

/* Unfilled text box of an area that already has content (e.g. only its
   picture filled) - hover info only, kept below placed-story .box overlays. */
.area-sub-box.area-text-slot {
	pointer-events: auto !important;
	z-index: 9000 !important;
}

.area-sub-box.area-text-slot.area-box-drag-over {
	background: rgba(13, 110, 253, 0.25);
	border-color: #084298;
	border-style: solid;
}

.area-sub-box {
	position: absolute;
	box-sizing: border-box;
	border: 1px dashed #0d6efd;
	background: rgba(13, 110, 253, 0.08);
}

.area-sub-box:hover {
	background: rgba(13, 110, 253, 0.22);
	border-style: solid;
}

.area-sub-box-image {
	border-color: #6f42c1;
	background-color: rgba(111, 66, 193, 0.06);
	background-image:
		linear-gradient(to top right, transparent calc(50% - 0.75px), rgba(111, 66, 193, 0.7) 50%, transparent calc(50% + 0.75px)),
		linear-gradient(to bottom right, transparent calc(50% - 0.75px), rgba(111, 66, 193, 0.7) 50%, transparent calc(50% + 0.75px));
}

.area-sub-box-image:hover {
	background-color: rgba(111, 66, 193, 0.2);
}

.area-sub-box-filled {
	border-style: solid;
	opacity: 0.6;
}

.area-box-label {
	position: relative; /* above the sub-boxes */
	z-index: 1;
	pointer-events: none;
	font-size: 11px;
	color: #084298;
	background: rgba(255, 255, 255, 0.85);
	padding: 1px 5px;
	border-radius: 3px;
	margin: 3px;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	max-width: calc(100% - 6px);
}






#preview-content {
	background: #f8f9fa;
	padding: 15px;
	border-radius: 8px;
	box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.1);
	max-width: 700px;
	margin: 10px auto;
	text-align: left;
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
	position: relative;
	overflow: hidden;
}

/* #preview-content is reused with the same id on the entries/queue page's
   slide-out (text/pre story preview, appended under #slide-out-content) -
   this file is shared by both pages, so the rule below is scoped to
   #preview-container (the edit page's own image/page-preview panel) and must
   NOT be added to the bare #preview-content rule above, or it'd also hijack
   the queue page's unrelated text preview.
   flex:1 (with min-height:0, required for a flex item to shrink below its
   content's size) makes this fill whatever space .preview-panel's flex
   layout actually leaves after #slide-out-header - real layout, not a
   guessed pixel budget. _syncPreviewContainerHeight (atex-edit.js) reads
   that real available height at runtime (by briefly clearing its own
   inline height override) as the ceiling for "natural height * zoom", so it
   hugs the image with no dead space at zoom 1 and can never size the
   content taller than what .preview-panel can actually show - a hardcoded
   "100vh - 80px" here previously under/over-shot depending on the header's
   real rendered height, which is what clipped the last line when zoomed.

   margin-left/right: 0 overrides the base rule's margin: 10px auto - auto
   cross-axis margins on a flex item disable align-items: stretch entirely
   (confirmed live: #preview-content was rendering at ~219px, shrink-wrapped
   to whatever image happened to be inside it, instead of the panel's real
   ~700px). That's invisible for a story whose image is already wide (it
   shrink-wraps right up near the cap anyway), but for a narrow single-column
   story it collapsed the whole container down with it - the image's own
   width:100% (see #hnj-image) was then filling 100% of an already-tiny box,
   so zooming stayed correct-but-cramped inside the panel's real width
   rather than ever using the real available space. */
#preview-container #preview-content {
	flex: 1 1 auto;
	min-height: 0;
	margin-left: 0;
	margin-right: 0;
}

#preview-content:has(#web-preview-frame) {
	padding: 0;
	background: none;
	box-shadow: none;
	border-radius: 0;
	max-width: 100%;
	margin: 0;
	/* Height comes from #preview-container #preview-content's flex:1 above -
	   fills whatever .preview-panel's flex layout leaves after the header,
	   same as the print-preview case, no separate number needed here. */
	overflow: visible;
}

#web-preview-frame {
	width: 100%;
	height: 100%;
	border: none;
	display: block;
}

#preview-overlay {
	position: absolute;
	inset: 0;
	cursor: grab;
	touch-action: none;
	z-index: 10;
}

#preview-content pre {
	font-size: 14px;
	color: #666;
	background: rgba(255, 249, 196, 0.2); /* Light pastel yellow with 80% opacity */
	/* background: rgba(255, 228, 235, 0.4); /* Light pink with 40% opacity */
	padding: 10px;
	border-radius: 5px;
	border-left: 4px solid #D3D3D3;
	border-right: 4px solid white;
	white-space: pre-wrap;
	word-break: break-word;
	overflow: auto;
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

/* dir="auto" on the <pre> lets the browser resolve RTL scripts (Hebrew,
   Arabic, ...) from the text itself - :dir(rtl) then matches only once the
   browser has actually resolved it that way, so LTR previews are untouched.
   #preview-content's own text-align: left would otherwise force RTL text to
   read right-to-left but still sit flush left, which looks wrong; flipping
   the accent border to match keeps the "near edge" reading correct too. */
#preview-content pre:dir(rtl) {
	text-align: right;
	border-left: 4px solid white;
	border-right: 4px solid #D3D3D3;
}




.story-thumbnails img {
	display: inline-block;
	width: 98px; /* Fixed width */
	height: 98px; /* Fixed height to make it square */
	object-fit: cover; /* Crops the image to fit */
	border-radius: 5px; /* Optional: Adds slightly rounded corners */
	margin: 5px;
	border: 1px solid rgba(0, 0, 0, 0.2); /* Very fine black border (20% opacity) */
	box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.15); /* Subtle shadow for depth */
}


.story-thumbnails img:hover {
	transform: scale(1.1); /* Slight zoom */
	transition: transform 0.3s ease;
}

/* Wraps each thumbnail in a story's own associated-images gallery so the
   remove (bin) button below can overlay its corner. */
.story-thumb-wrap {
	position: relative;
	display: inline-block;
}
.story-thumb-remove {
	position: absolute;
	top: 7px;
	right: 7px;
	width: 20px;
	height: 20px;
	padding: 0;
	border: none;
	border-radius: 50%;
	background: rgba(0, 0, 0, 0.55);
	color: #fff;
	font-size: 11px;
	cursor: pointer;
	opacity: 0;
	transition: opacity 0.15s, background 0.15s;
}
.story-thumb-wrap:hover .story-thumb-remove {
	opacity: 1;
}
.story-thumb-remove:hover {
	background: #dc3545;
}
.story-thumb-remove:disabled {
	cursor: default;
	opacity: 0.5;
}

/* An assignment list ("Stories" on a page/image, "Images" on a story/page) -
   clicking one swaps the slide-out panel to that item's own preview (see
   #panel-back-btn to return, possibly several hops back). */
.clickable-assigned-story,
.clickable-assigned-image,
.clickable-assigned-page {
	cursor: pointer;
}



/* Responsive tweak */
@media (max-width: 768px) {
	.image-gallery {
	grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}
}



/* Styling for active folder or search result */
.folder.active,
	#sidebar-searches a.active {
	background-color: black;
	color: white;
	font-weight: bold;
	padding: 2px 5px;
	border-radius: 4px;
}

/* EDITIONING_ENABLED zone row-view: ctrl+click multi-select on a zone leaf
   (see onZoneClick in atex-entries.js). Deliberately not black/.active - a
   ctrl-click comparison is a different, additive selection from the normal
   single "where am I" tree state, so it gets its own accent colour instead
   of overloading .active's meaning. */
.folder.zone-row-selected {
	background-color: #0d6efd;
	color: #fff;
	font-weight: bold;
	padding: 2px 5px;
	border-radius: 4px;
}
/* Ctrl+clicking a zone from a different publication than the current
   row-view selection - rejected (same publication only), shown as a shake
   rather than silently doing nothing. */
.folder.zone-row-rejected {
	animation: meta-shake 0.3s ease;
}
/* Shift+click range-select (see onZoneClick) triggers the browser's own
   text-selection highlight on mousedown, before the click handler even
   runs - suppress it so a shift+click reads as a selection action, not a
   text-highlight drag. */
.folder.zone-leaf {
	user-select: none;
}


/* Make sure the row gets highlighted */
tr.highlighted {
	background-color: #f0f8ff !important; /* Light blue color */
}

/* Make sure links inside the row do not interfere with highlighting */
tr.highlighted a {
	background-color: transparent !important; /* Ensure link has no background that overrides the row highlight */
	color: inherit !important; /* Ensure link text color matches */
}



tr.highlighted-with-line td:first-child {
	border-left: 3px solid pink !important;
}

/* Ensure the rows have enough width to show the border */
.clickable-row {
	padding-left: 5px;  /* Adjust to ensure border is visible */
}










/* Style the input field */
#publication-date {
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
	width: 90%;
	box-sizing: border-box; /* so the padding/border below can never push the
	                           rendered width past the 90% cap - previously
	                           content-box width:73% + this padding/border
	                           could add up to wider than its container */
	padding: 8px 12px;
	font-size: 14px;
	border: 1px solid #ccc;
	border-radius: 5px;
	height: 32px;
	display: block;   /* Ensures it behaves like a block element */
	margin: 10px auto; /* Centers the field horizontally */
	text-align: center;
}


/* Style the entire datepicker popup */
.ui-datepicker {
	width: 200px;            /* Set fixed width */
	font-size: 13px;         /* Adjust font size */
	background: #fff;        /* Background color */
	border: 0px solid #ccc;  /* Border style */
	border-radius: 5px;      /* Rounded corners */
	box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Light shadow */
}

/* Style the month navigation buttons */
.ui-datepicker-prev, .ui-datepicker-next {
	font-size: 16px;         /* Adjust button size */
	color: #007bff;          /* Button color */
}



/* Highlight the selected day */
.ui-datepicker-calendar .ui-state-active {
	background-color: #007bff;  /* Selected date background */
	color: white;                /* Selected date text color */
}

/* Highlight today's date */
.ui-datepicker-today a {
	font-weight: bold;       /* Bold text for today */
	background-color: #f1f1f1; /* Light background for today */
}

/* Style the month/year header */
.ui-datepicker-header {
	background-color: #f4f4f4; /* Light background */
	border-bottom: 1px solid #ddd; /* Subtle border */
}

/* Style the weekday names */
.ui-datepicker-week-day {
	font-weight: bold;
	color: #666;
}

/* Optional: Style for the highlighted date when hovering */
.ui-datepicker-calendar td a:hover {
	background-color: pink; /* Hover effect */
	color: black; /* White text on hover */
}

/* Adjust the width of the individual days' columns */
.ui-datepicker-calendar td {
	width: 20px;  /* Adjust the width of each day column */
	padding: 3px; /* Adjust padding for better fit */
	text-align: center; /* Center the text */
	border: none !important; /* Ensure no borders appear */

}

/* Adjust the width of the day cells */
.ui-datepicker-calendar td a {
	display: block; /* Make the link block-level to occupy the full width */
	width: 100%;    /* Ensure the link fills the cell */
	text-align: center; /* Center the text inside the cell */
	padding: 1px 0;  /* Adjust padding */
	border: none !important;
	box-shadow: none !important;
}


#output {
	padding: 10px;      /* Optional padding for spacing */
}



/* Hover effect on submit button */
button[type="submit"]:hover i {
	color: pink;
}




/* Sliding Preview Panel */
.preview-panel {
	position: fixed;
	top: 0;
	right: -750px; /* Start off-screen (must match width below) */
	width: 750px;
	height: 100%;
	/* Without this, height:100% + padding below adds up to 100% of the
	   viewport PLUS 40px (top+bottom padding), pushing the panel's own
	   bottom edge below the viewport with no way to scroll to it (a
	   position:fixed element can't be brought into view by page scroll) -
	   the deeper #preview-content's zoom-driven height grows (see
	   _syncPreviewContainerHeight in atex-edit.js), the more of it landed in
	   that permanently-offscreen strip, which showed up as the bottom of the
	   zoomed preview image getting clipped. */
	box-sizing: border-box;
	/* Column flex so #preview-content (flex:1, see its own rule) fills
	   whatever space is actually left under #slide-out-header, whatever that
	   header's real rendered height turns out to be - no pixel guessing. */
	display: flex;
	flex-direction: column;
	background-color: #fff;
	box-shadow: -2px 0 5px rgba(0, 0, 0, 0.2);
	overflow-x: hidden;
	overflow-y: auto;
	transition: right 0.3s ease-in-out;
	z-index: 1000;
	padding: 20px;
}

.preview-panel.active {
	right: 0; /* Slide into view */
}

/* User-toggled show/hide (togglePreviewPanelVisibility(), atex-edit.js) -
   layered on top of .active rather than replacing it, so whatever set
   .active/.shrink (displayPreview(), showWebPreview(), etc.) doesn't need to
   know or care whether the user has chosen to hide the panel; these two
   selectors just override back to the closed/unshrunk look while that class
   is present. Higher specificity than the plain .preview-panel.active /
   .main-container.shrink rules above (an extra ancestor class) wins without
   needing !important. */
body.hide-preview-panel .preview-panel.active {
	right: -750px;
}
body.hide-preview-panel .main-container.shrink {
	margin-right: 0;
}

/* Always-visible handle attached to the preview panel's left edge - see
   #preview-panel-handle in edit.html and togglePreviewPanelVisibility() in
   atex-edit.js. Sits outside #preview-container so the panel's own slide
   transform never carries it off-screen, the same role .rail-collapse-btn
   plays for the sidebar (a control reachable regardless of whether the
   thing it toggles is currently shown or hidden). Tracks the panel's own
   right offset (750px open, 0 hidden) so it always hugs whichever edge is
   currently showing. */
#preview-panel-handle {
	position: fixed;
	top: 50%;
	transform: translateY(-50%);
	right: 750px;
	width: 22px;
	height: 64px;
	display: flex;
	align-items: center;
	justify-content: center;
	background: #e9ecef;
	border: none;
	border-radius: 6px 0 0 6px;
	color: #495057;
	cursor: pointer;
	z-index: 1001; /* above .preview-panel's 1000 */
	box-shadow: -2px 0 5px rgba(0, 0, 0, 0.15);
	transition: right 0.3s ease-in-out, background-color 0.15s ease-out;
}
#preview-panel-handle:hover {
	background: #dee2e6;
	color: #21262c;
}
#preview-panel-handle i {
	transition: transform 0.18s ease-out;
}
body.hide-preview-panel #preview-panel-handle {
	right: 0;
}
body.hide-preview-panel #preview-panel-handle i {
	transform: rotate(180deg);
}


/* width:100% (not max-width) so narrow single-column crops scale UP to fill
   #preview-content, same as wide crops already effectively do - otherwise a
   narrow image renders at its own small intrinsic size, and all the
   zoom/pan math in _clampPreviewPan/_zoomAroundPoint (atex-edit.js), which
   assumes the image's unzoomed footprint already spans the container, goes
   sideways: clicks land in the dead space beside the image and zooming
   pans to a partially blank, partially clipped view instead of filling the
   panel. */
#hnj-image {
    width: 100%;
    height: auto;
    display: block;
    margin: 0;
    transform-origin: 0 0;
    transition: transform 0.15s ease;
}

/* Wraps #hnj-image so #story-box-overlay can size/position itself against
   the image's own rendered box. display:block (not inline-block) so the
   wrap always spans #preview-content's full width, matching the image
   above - see #hnj-image's own comment. */
#hnj-image-wrap {
    position: relative;
    display: block;
    transform-origin: 0 0;
    transition: transform 0.15s ease;
}

#story-box-overlay {
    position: absolute;
    inset: 0;
    pointer-events: none;
}

.story-box {
    position: absolute;
    border: 1px dashed rgba(0, 120, 215, 0.85);
    background: rgba(0, 120, 215, 0.06);
    box-sizing: border-box;
}

.story-box[data-item-type="Image"] {
    border-color: rgba(215, 90, 0, 0.85);
    background: rgba(215, 90, 0, 0.06);
}

/* Page view: other content on the page, shown for context only - not
 * interactive (see _storyBoxAtClientPoint's :not(.page-context-box) filter).
 * Rules placed after the ones above so equal specificity still wins here. */
.story-box.page-context-box,
.story-box.page-context-box[data-item-type="Image"] {
    border-color: rgba(120, 120, 120, 0.5);
    background: rgba(120, 120, 120, 0.05);
}

/* Copyfit state from the live HnJ result - see _applyStoryBoxFitStates() in
 * atex-edit.js. Same green/red/blue fills as the entries page-preview
 * overlay (.box--fits-*), with a solid border in the same hue so the state
 * still reads against the busy page image. Before story-box-hidden below so
 * the overlay toggle still hides these too. */
.story-box.story-box--fits {
    border: 1px solid rgba(122, 150, 0, 0.9);
    background: rgba(164, 196, 0, 0.2);
}
.story-box.story-box--overset {
    border: 1px solid rgba(220, 53, 69, 0.9);
    background: rgba(220, 53, 69, 0.15);
}
.story-box.story-box--underset {
    border: 1px solid rgba(13, 110, 253, 0.9);
    background: rgba(13, 110, 253, 0.12);
}

/* Visible highlight toggled off via toggleStoryOverlay - the box stays in
 * the DOM at its real position/size so double-click/ctrl+click/drag-drop hit
 * detection keeps working, it just isn't drawn. */
.story-box.story-box-hidden {
    border-color: transparent;
    background: transparent;
}

/* Brief flash on the icml-field jumped to via a story-box double-click. */
.field-jump-highlight {
    animation: field-jump-flash 1.2s ease-out;
}

@keyframes field-jump-flash {
    0%   { box-shadow: 0 0 0 3px rgba(0, 120, 215, 0.7); }
    100% { box-shadow: 0 0 0 3px rgba(0, 120, 215, 0); }
}



/* ─── ICML-aware story editor ─────────────────────────────────────────────── */

.icml-field {
    margin-bottom: 24px;
}

.icml-field-body {
    border: 1px solid #dee2e6;
    border-radius: 6px;
    overflow: hidden;
    background: #fff;
}

.icml-para-area {
    outline: none;
    font-size: 14px;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    color: #212529;
    padding: 2px 0;
}
.icml-para-area:focus-within {
    box-shadow: inset 0 0 0 2px #2196f3;
}

/* Each paragraph is a normal block - no reserved gutter, text uses the full
   width. The style name is shown as a floating popup (see .para-style-tag
   below), not permanent layout space. */
.icml-para {
    position: relative;
    padding: 5px 14px;
    min-height: 1.9em;
    line-height: 1.65;
    word-wrap: break-word;
}

/* Non-editable style-name popup. contenteditable="false" on the span makes
   the browser treat it as an atomic unit and prevents any editing
   interaction with it. It takes up no layout space (position: absolute)
   and stays fully transparent/inert until hover, when it floats near the
   cursor like a tooltip (position tracked by the mousemove handler in
   _watchParaStructure, so it doesn't sit on top of the paragraph's own
   text). left/top below are just the pre-first-move fallback. Deliberately
   kept inside the paragraph's own box (rather than escaping into the
   margin) so it's never clipped by .icml-field-body's overflow:hidden. */
.para-style-tag {
    position: absolute;
    left: 6px;
    top: 4px;
    max-width: 200px;
    font-size: 11px;
    font-family: inherit;
    font-weight: 500;
    letter-spacing: 0.02em;
    color: #fff;
    background: #4b5563;
    padding: 2px 7px;
    border-radius: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: pointer;
    user-select: none;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.12s;
    z-index: 5;
    box-shadow: 0 1px 4px rgba(0,0,0,0.2);
}
/* List paragraphs (InDesign bullets/numbering, from the style or set on the
   paragraph - see _refreshListMarkers in atex-edit.js): hanging indent with
   the marker drawn in front, so the text itself never holds a "•". */
.icml-para[data-list] {
    padding-inline-start: 36px;
}
.icml-para[data-list]::before {
    position: absolute;
    inset-inline-start: 14px;
    width: 16px;
    text-align: end;
    color: #0053e2;
    font-weight: 600;
    pointer-events: none;
    user-select: none;
}
.icml-para[data-list="bullet"]::before {
    content: "\2022";
}
.icml-para[data-list="number"]::before {
    content: attr(data-list-num);
    font-variant-numeric: tabular-nums;
}
.icml-para:hover .para-style-tag {
    opacity: 1;
    pointer-events: auto;
}
/* Parked in the page margin beside the text box (see _placeTagOutside in
   atex-edit.js) so it never covers text being edited. Fixed, not absolute,
   to escape .icml-field-body's overflow:hidden; purely a label out there -
   moving onto it would leave the paragraph's :hover anyway. */
.para-style-tag.para-style-tag--outside {
    position: fixed;
    z-index: 1050;
}
.icml-para:hover .para-style-tag.para-style-tag--outside {
    pointer-events: none;
}
/* Edit-on-page frame: the page view draws the badge outside the frame
   instead (.page-edit-style-tag) - never over the text in here. */
body.editor-embed .para-style-tag {
    display: none;
}
.page-edit-style-tag {
    position: fixed;
    z-index: 10060;
    max-width: 200px;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.02em;
    color: #fff;
    background: #4b5563;
    padding: 2px 7px;
    border-radius: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    pointer-events: none;
    box-shadow: 0 1px 4px rgba(0,0,0,0.2);
}
/* Sticky stand-in for the native text selection, applied to every paragraph
 * a multi-paragraph (or ctrl+A) style-menu selection covers - the real
 * Selection collapses the instant the palette's filter input takes focus
 * (see togglePaletteMenu in atex-edit.js), so without this the paragraphs a
 * style change is about to apply to would visibly lose their highlight the
 * moment the menu opens. Left on through the style pick and afterwards;
 * cleared only once the user clicks/types back into the text. */
.icml-para--style-selected {
    background: rgba(33, 150, 243, 0.12);
}
/* The exact selected text, kept painted while a style menu has focus and
 * after the pick (CSS Custom Highlight API - registered by
 * _setTextSelectionHighlight in atex-edit.js, cleared on the next click/
 * keypress in the text). */
::highlight(atex-style-selection) {
    background-color: rgba(33, 150, 243, 0.35);
}
/* Hide style-name popups entirely when the toggle is off - overrides the
   hover/active reveal above regardless of mouse position or focus. */
.hide-style-tags .para-style-tag {
    display: none;
}
/* Web fields have no InDesign paragraph/character style of their own - see
   the print-only style palette gating in renderPaletteChips - so the print
   style-name badge is just noise there. */
#dynamic-fields-web .para-style-tag {
    display: none;
}

/* Hide Note markers entirely when the toggle is off - pure visual toggle,
   the DOM (and therefore what gets saved) is untouched either way. */
.hide-notes .icml-note-marker {
    display: none;
}

/* InDesign Note markers - sticky-note yellow to read distinctly from the
   indigo Tab/RightIndentTab chips below. The note's own text now shows
   inline (icml-note-marker-text) instead of only on hover/click - long
   notes are CSS-truncated with an ellipsis rather than swallowing the
   whole line; click still opens showNotePopover for the full text. */
.icml-note-marker {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    max-width: 100%;
    vertical-align: middle;
    font-size: 11px;
    color: #92400e;
    background: #fef3c7;
    border: 1px solid #fde68a;
    border-radius: 3px;
    padding: 0 4px;
    margin: 0 1px;
    cursor: pointer;
    user-select: none;
}
.icml-note-marker-text {
    max-width: 260px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* Floating card for viewing/composing a note - same visual language as
   .recent-queues-dropdown in atex-entries.js. */
.note-popover {
    position: fixed;
    z-index: 9999;
    background: #fff;
    border: 1px solid #ccc;
    border-radius: 5px;
    box-shadow: 2px 2px 10px rgba(0,0,0,0.2);
    min-width: 200px;
    max-width: 320px;
    padding: 10px 12px;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    font-size: 13px;
}
.note-popover-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 4px;
}
.note-popover-meta {
    font-size: 11px;
    color: #888;
}
.note-popover-restore-btn {
    flex-shrink: 0;
    border: none;
    background: transparent;
    color: #888;
    font-size: 12px;
    padding: 0;
    cursor: pointer;
    line-height: 1;
}
.note-popover-restore-btn:hover {
    color: #333;
}
.note-popover-text {
    white-space: pre-wrap;
    word-break: break-word;
}
.note-popover--compose .note-popover-textarea {
    width: 100%;
    min-height: 70px;
    resize: vertical;
    font-family: inherit;
    font-size: 13px;
    box-sizing: border-box;
}
.note-popover-actions {
    display: flex;
    justify-content: flex-end;
    gap: 6px;
    margin-top: 8px;
}

/* HnJ galley line-break markers (widows/orphans view). Unlike the other
   inline overlays in this file, these include a real forced <br> (see
   _makeGalleyMarker) so the line actually visually wraps where InDesign
   wraps it - a display:none <br> isn't reliable across browsers for
   un-forcing that break, so visibility here is "does the marker exist in
   the DOM" (toggleGalleyView adds/removes it directly), not a CSS class,
   unlike .hide-notes/.hide-style-tags. Only the marker <span> needs
   styling; the paired <br> (same class, for the shared skip-logic in
   _effectiveNodesForPara/_runsFromParaEl) is unaffected by these rules. */
.icml-galley-break {
    display: inline-block;
    vertical-align: middle;
    font-size: 10px;
    line-height: 1;
    color: #9ca3af;
    margin: 0 1px;
    cursor: default;
    user-select: none;
}
.icml-galley-break--hyphen {
    color: #b45309;
    text-decoration: underline;
}
.icml-galley-break--compressed {
    color: #b91c1c;
    text-decoration: underline;
}

/* InDesign special-character chips (Tab, Right Indent Tab, …) */
.icml-special-char {
    display: inline-block;
    vertical-align: middle;
    font-size: 10px;
    color: #6366f1;
    background: #eef2ff;
    border: 1px solid #c7d2fe;
    border-radius: 3px;
    padding: 0 3px;
    margin: 0 1px;
    cursor: default;
    user-select: none;
    font-family: 'Courier New', monospace;
}

/* Active paragraph — badge goes blue */
/* ── Overset markers ───────────────────────────────────────────────────────── */

/* Tiny inline bar at the exact cut character */
.icml-overset-start {
    display: inline;
    border-left: 2px solid #ef4444;
    margin: 0 1px;
    user-select: none;
    pointer-events: none;
}

/* Caption text shown below image when searching by caption */
.caption-search-preview {
    margin-top: 8px;
    padding: 8px 10px;
    background: #f8f8f8;
    border-left: 3px solid #ccc;
    font-size: 0.9em;
    line-height: 1.5;
    white-space: pre-wrap;
    word-break: break-word;
}

/* Same RTL treatment as the story-text preview (#preview-content pre):
   dir="auto" resolves Hebrew/Arabic from the caption itself, so flip the
   alignment and accent-border side to match once the browser resolves it. */
.caption-search-preview:dir(rtl) {
    text-align: right;
    border-left: none;
    border-right: 3px solid #ccc;
}

/* Image metadata fields (caption, published caption, ...): grow with content
   instead of staying a fixed one-line box - height is set in JS from
   scrollHeight (see _autoGrowTextarea in atex-edit-image.js), this just
   stops the browser's own resize handle and scrollbar from fighting it. */
.image-metadata-field--auto-grow,
.metadata-field--auto-grow {
    resize: none;
    overflow: hidden;
}

/* Search term highlight in story preview panel */
mark {
    background: pink;
    color: inherit;
    border-radius: 2px;
    padding: 0 1px;
}

/* Red highlight on overset text — inline span on the straddling paragraph
   (starts at the exact cut character), block background on all subsequent
   wholly-overset paragraphs.  Same colour throughout. */
.icml-overset-highlight {
    background: #fee2e2;
    border-radius: 2px;
}
.icml-para--overset {
    background: #fee2e2;
}

/* Web fields: no overmatter markers */
#dynamic-fields-web .icml-overset-start { display: none; }
#dynamic-fields-web .icml-overset-highlight { background: none; }
#dynamic-fields-web .icml-para--overset { background: none; }

/* Keep .icml-para-content harmless for any legacy markup */
.icml-para-content {
    padding: 10px 14px;
    min-height: 1.9em;
    line-height: 1.65;
    outline: none;
}

/* Character-style overrides — add more as needed */
.char-style {
    border-radius: 2px;
    padding: 0 1px;
}
.char-style[data-char-style="Slab Heavy"] {
    font-weight: 700;
}
.char-style[data-char-style="Bold"] {
    font-weight: 700;
}
.char-style[data-char-style="Italic"],
.char-style[data-char-style="Italic Text"] {
    font-style: italic;
}

/* Web-tab-only hyperlink tool — see insertOrEditLink() in atex-edit.js */
.run-link {
    color: #0b5ed7;
    text-decoration: underline;
    cursor: text;
}


/* ─── Style palette ────────────────────────────────────────────────────────── */

#icml-palette {
    display: none;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    background: #f8f9fa;
    border: 1px solid #dee2e6;
    border-radius: 6px;
    padding: 7px 12px;
    margin-bottom: 14px;
    position: sticky;
    top: var(--toolbar-h, 92px);
    z-index: 400;
    box-shadow: 0 2px 6px rgba(0,0,0,0.06);
}

.palette-section {
    position: relative;
    flex: 0 0 auto;
}

.palette-divider {
    align-self: stretch;
    width: 1px;
    background: #ced4da;
    margin: 2px 0;
}

.palette-label {
    font-size: 13px;
    font-weight: 700;
    color: #6c757d;
    user-select: none;
}

/* Closed-by-default trigger button - opens the style menu below it */
.palette-trigger {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    padding: 5px 10px;
    max-width: 220px;
    border-radius: 14px;
    border: 1px solid #ced4da;
    background: #fff;
    color: #495057;
    cursor: pointer;
    font-family: inherit;
    line-height: 1.4;
}
.palette-trigger:hover {
    background: #e9ecef;
    border-color: #adb5bd;
}
.palette-trigger.open {
    border-color: #0d6efd;
    box-shadow: 0 0 0 2px rgba(13,110,253,0.15);
}
.palette-trigger-value {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.palette-caret {
    font-size: 9px;
    color: #adb5bd;
}

/* Bulleted / numbered list buttons - see toggleList in atex-edit.js */
.palette-list-section {
    display: flex;
    align-items: center;
    gap: 2px;
}
.palette-list-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 28px;
    border: 1px solid transparent;
    border-radius: 6px;
    background: transparent;
    color: #495057;
    cursor: pointer;
    font-size: 14px;
}
.palette-list-btn:hover {
    background: #e9ecef;
}
.palette-list-btn.active {
    background: #e3ebfe;
    border-color: #c5d5fb;
    color: #0053e2;
}

/* Floating menu popover - positioned below its trigger, closed by default */
.palette-menu {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 200;
    width: min(300px, calc(100vw - 40px));
    background: #fff;
    border: 1px solid #dee2e6;
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.15);
    padding: 8px;
}
.palette-menu.open {
    display: block;
}

.palette-filter {
    display: block;
    width: 100%;
    margin-bottom: 6px;
    box-sizing: border-box;
    font-size: 11px;
    padding: 5px 9px;
    border: 1px solid #ced4da;
    border-radius: 10px;
    outline: none;
    font-family: inherit;
    background: #fff;
}
.palette-filter:focus {
    border-color: #86b7fe;
    box-shadow: 0 0 0 2px rgba(13,110,253,0.15);
}

.palette-chips {
    display: flex;
    flex-direction: column;
    gap: 1px;
    max-height: 260px;
    overflow-y: auto;
    padding-right: 2px;
}

.palette-chip {
    display: block;
    width: 100%;
    flex-shrink: 0;
    text-align: left;
    font-size: 13px;
    font-weight: 500;
    padding: 7px 10px;
    border-radius: 4px;
    border: 1px solid transparent;
    background: #fff;
    color: #212529;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: background 0.1s, color 0.1s;
    font-family: inherit;
    line-height: 1.4;
}
.palette-chip:hover {
    background: #e9ecef;
}
.palette-chip-active {
    background: #0d6efd;
    color: #fff;
    font-weight: 600;
}
.palette-chip-active:hover {
    background: #0b5ed7;
    color: #fff;
}
.palette-chip-none {
    border-style: dashed;
    border-color: #ced4da;
    color: #adb5bd;
}
.palette-chip-none:hover {
    border-color: #dc3545;
    color: #dc3545;
    background: #fff5f5;
}
.palette-chip-char {
    color: #6610f2;
}
.palette-chip-char:hover {
    background: #f3efff;
}

.palette-empty {
    font-size: 11px;
    color: #adb5bd;
}

/* Metadata tab — match font size of the ICML editor fields */
#tab-panel-metadata .form-label,
#tab-panel-metadata .form-control {
    font-size: 14px;
}

/* HnJ description line under each field */
.hnj-description {
    font-size: 12px;
    color: #666;
    margin-top: 4px;
    text-align: right;
}

/* Client-computed word count, shown alongside .hnj-description rather than
 * instead of it - InDesign's own per-field description text switches from a
 * word-count-shaped message to a fit-status one ("Copy Fits", "3 Lines
 * Overset", ...) once the story is actually placed on a page, so relying on
 * that field alone meant the word count effectively disappeared the moment
 * a story got placed. See updateWordCount. */
.hnj-wordcount {
    font-size: 12px;
    color: #666;
    margin-top: 4px;
    text-align: right;
}

/* Hamburger button: hidden on desktop, shown on mobile */
.mobile-menu-btn {
    display: none;
}

/* ─── Mobile (≤ 640px on its SHORT side) ─────────────────────────────────────
   "(max-width: 640px), (max-height: 640px)" - comma is an OR in CSS media
   queries, and that OR is exactly min(width,height)<=640: whichever
   dimension is smaller determines whether either individual condition can
   be true. A plain max-width-only query meant rotating a phone to
   landscape (routinely 700-900px wide) fell out of this block entirely and
   back to the full desktop layout - fine on a tablet, whose short side
   stays 720px+ in either orientation, but not on a phone, which stays
   under ~430px on its short side regardless of rotation. Keep this in sync
   with _isMobileViewport() in atex-entries.js - the two must keep
   agreeing, or JS and CSS would disagree about whether a given screen
   counts as mobile. The height half is limited to (pointer: coarse) so a
   low-res laptop (1366x768, or 1080p at 150% scaling - ~590-630 CSS px of
   viewport height after taskbar + browser chrome) isn't pulled in too; see
   _isMobileViewport() for the full reasoning. */
@media (max-width: 640px), (max-height: 640px) and (pointer: coarse) {
    /* iOS Safari auto-zooms the whole page in whenever a tapped
       input/textarea/select's font-size is under 16px, regardless of the
       viewport meta tag's user-scalable setting (that only stops deliberate
       pinch/double-tap zoom, a separate mechanism - see the meta tag in
       each template's <head>). Most fields in this file sit at 12-14px, so
       tapping practically any of them - the main search box included -
       triggered this, then zoomed back out on blur: the actual "zooming in
       and out" this app was doing, far more often than anyone deliberately
       pinching. One blanket floor here covers every field at once rather
       than auditing/overriding each one's own font-size individually.
       !important because that's the whole point - a floor with no
       exceptions - and several existing rules set font-size on a class
       (e.g. .search-input), which otherwise outranks this plain-element
       selector regardless of which is declared later. */
    input, textarea, select {
        font-size: 16px !important;
    }

    .mobile-menu-btn {
        display: inline-block;
    }

    /* Banner: stack logo/search/icons vertically - flex-wrap is still what
       pushes the search box (order:3, width:100%) onto its own row below.
       Logo+icons only need to be narrow enough to fit ALONGSIDE each other
       on that first row before wrapping - confirmed live (measuring actual
       rendered widths) that at 375px they were a mere ~15px over: shrinking
       both a little below is enough to reliably close that gap rather than
       needing to restructure anything. Already true in landscape (plenty
       of width there at full size) - this just gets portrait to the same
       one-row layout instead of icons dropping to their own row under a
       full-size logo. */
    .banner {
        flex-wrap: wrap;
        gap: 10px;
        padding: 12px;
    }
    .banner .logo {
        height: 36px;
    }
    .banner .icons {
        gap: 8px;
    }
    .banner .icon-item {
        font-size: 19px;
    }
    .icon-divider {
        display: none;
    }
    .banner .search-container {
        order: 3;
        width: 100%;
        top: 0;
        padding-bottom: 0;
    }
    .search-input {
        min-width: 0;
        width: 100%;
    }

    /* Hide the sidebar by default; the toggle still works */
    .sidebar-container {
        position: fixed;
        top: 0;
        left: 0;
        height: 100%;
        z-index: 900;
        transform: translateX(-100%);
        background: #f4f4f4;
        box-shadow: 2px 0 8px rgba(0,0,0,0.18);
    }
    .sidebar-container.mobile-open {
        transform: translateX(0);
    }

    /* Collapsing to just the icon rail (.sidebar-container.panel-collapsed,
       see atex.css) is a desktop concept - handing width back to the content
       area next to it. On mobile the drawer already overlays the content
       instead of sharing width with it, so collapsing here would only ever
       shrink the open drawer down to an unreadable 42px sliver with no
       obvious way back short of finding this same button again. The
       hamburger/overlay-tap toggle is this app's one mobile show/hide
       control instead. */
    .rail-collapse-btn {
        display: none;
    }

    /* Nothing on this page legitimately scrolls horizontally at the
       document level - only .stories-container's own overflow-x:auto
       (the results table) should. html/body carried no overflow-x rule
       at all before this, so although nothing actually overflowed them
       (scrollWidth === clientWidth), a real touch browser can still
       rubber-band/bounce the whole page sideways on a swipe that isn't
       confined to an inner scroll container, revealing blank canvas past
       the page edge. overflow-x:hidden forecloses that outright;
       overscroll-behavior-x backs it up in browsers that support it. */
    html, body {
        overflow-x: hidden;
        overscroll-behavior-x: none;
    }

    /* Content takes full width */
    .lower-container {
        overflow-x: hidden;
    }
    .content-container {
        width: 100%;
        min-width: 0;
    }

    /* .preview-container is dead CSS as of this file's current markup (no
       element anywhere carries that class any more - edit.html's own panel
       is #preview-container.preview-panel, an id, not this class) - left in
       place rather than pulled, since it costs nothing live. */
    .preview-container {
        width: 100% !important;
        right: -100% !important;
        left: auto;
    }
    .preview-container.open {
        right: 0 !important;
    }

    /* The results-list preview's edge handle's fixed 400px offset only
       makes sense at desktop widths; edit.html's own #preview-panel-handle
       gets repositioned instead of hidden - see further down. */
    #slide-out-panel-handle {
        display: none !important;
    }

    /* Editor's own preview panel (the HnJ/page image preview shown while
       editing a story) - same half-screen-bottom-sheet treatment as the
       results-list preview below, for the same reason: a full-screen
       takeover was blocking the actual text being edited, confirmed live
       as "gets in the way" on a phone. Already display:flex/flex-direction:
       column from the base .preview-panel rule, so only positioning needs
       overriding here - #preview-container #preview-content (further down)
       is what actually becomes the scrolling child. */
    .preview-panel {
        width: 100% !important;
        left: 0 !important;
        right: 0 !important;
        top: auto !important;
        bottom: 0;
        height: 55vh;
        transform: translateY(100%);
        transition: transform 0.3s ease, height 0.25s ease;
        border-radius: 14px 14px 0 0;
        box-shadow: 0 -3px 14px rgba(0, 0, 0, 0.25);
        overflow-y: hidden;
        z-index: 1000;
    }
    .preview-panel.active {
        transform: translateY(0);
    }
    /* togglePreviewPanelVisibility() only ever adds/removes
       body.hide-preview-panel - .active itself stays put, same reasoning
       as the results-list preview's own equivalent override. Needs its own
       rule here since the plain ".active { transform: translateY(0) }"
       above would otherwise always win regardless of the body class (equal
       specificity, declared later in the file). */
    body.hide-preview-panel .preview-panel.active {
        transform: translateY(100%);
    }
    /* Tapped via #preview-panel-sheet-handle (edit.html) when the half-
       screen default isn't enough room. */
    .preview-panel.expanded {
        height: 92vh;
    }
    #preview-container #preview-content {
        overflow-y: auto;
    }

    /* Drag-handle-styled bar at the sheet's top edge, matching the
       results-list preview's own #slide-out-sheet-handle - doubles as the
       tap target for expand/collapse (toggleEditorPreviewExpanded()), no
       actual drag gesture. */
    #preview-panel-sheet-handle {
        display: block;
        width: 40px;
        height: 5px;
        border-radius: 3px;
        background: #ccc;
        margin: 8px auto 2px;
        cursor: pointer;
        flex: 0 0 auto;
    }

    /* Repositioned instead of hidden (unlike the results-list preview's
       edge handle) - there's no "select a different item" action here to
       reopen the panel once hidden the way tapping a new row does there,
       so this stays the one persistent, always-reachable show/hide control:
       a small tab poking up from the bottom edge instead of the desktop
       edge tab, same togglePreviewPanelVisibility() either way. */
    #preview-panel-handle {
        top: auto !important;
        bottom: 0 !important;
        left: 50% !important;
        right: auto !important;
        transform: translateX(-50%) !important;
        width: 56px !important;
        height: 22px !important;
        border-radius: 6px 6px 0 0 !important;
    }
    #preview-panel-handle i {
        transform: rotate(90deg);
    }
    body.hide-preview-panel #preview-panel-handle {
        bottom: 0 !important;
    }
    body.hide-preview-panel #preview-panel-handle i {
        transform: rotate(-90deg);
    }

    /* Results-list preview: a half-screen sheet anchored to the bottom
       instead of a full-screen takeover, so the results list stays
       visible (and scrollable) above it for context - closer to how a
       Files app or Mail preview behaves on a phone. translateY (rather
       than the bottom-offset approach used elsewhere in this file) always
       fully hides the sheet regardless of its current height, which
       matters here since .expanded (below) changes that height. */
    #slide-out-panel {
        width: 100% !important;
        left: 0 !important;
        right: 0 !important;
        top: auto !important;
        bottom: 0;
        height: 55vh;
        transform: translateY(100%);
        transition: transform 0.3s ease, height 0.25s ease;
        border-radius: 14px 14px 0 0;
        box-shadow: 0 -3px 14px rgba(0, 0, 0, 0.25);
        /* Overrides the base rule's own overflow-y:auto - scrolling moves
           down to #slide-out-content alone (see its own mobile override),
           so the handle/header/status row above it can stay flex:0 0 auto
           fixed in place instead of scrolling away with the rest. */
        display: flex;
        flex-direction: column;
        overflow-y: hidden;
    }
    #slide-out-panel.visible {
        transform: translateY(0);
    }
    /* toggleSlideOutPanelVisibility() (see #mobile-close-slide-out-btn
       below) only ever adds/removes body.hide-slide-out-panel - .visible
       itself stays put, same as on desktop. Needs its own rule here since
       the plain ".visible { transform: translateY(0) }" above would
       otherwise always win regardless of the body class (equal
       specificity, declared later). */
    body.hide-slide-out-panel #slide-out-panel.visible {
        transform: translateY(100%);
    }
    /* Tapped via #slide-out-sheet-handle (entries.html) when the half-
       screen default isn't enough room - e.g. the page-preview's box
       overlay needs real height to stay legible. */
    #slide-out-panel.expanded {
        height: 92vh;
    }

    /* The one section of #slide-out-panel's new flex column that actually
       grows and scrolls - everything above it (handle/header/status row)
       stays fixed in place regardless of how far into a story you've
       scrolled. min-height:0 is required for a flex child to be allowed to
       shrink below its content's natural height at all (the flexbox
       default is as if min-height:auto), which is what lets this scroll
       instead of just pushing the panel taller than its own 55vh/92vh. */
    #slide-out-content {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        /* Base rule's 20px is even on all sides - here the top edge sits
           right under the now-fixed header row, so it doesn't need as much
           breathing room as the sides/bottom do. */
        padding: 8px 14px 20px;
    }

    /* #preview-content's own base rule (margin:10px auto, padding:15px) was
       tuned for the desktop panel where it sits under a big <h1> icon - now
       that the icon's moved up into the header (see articleIcon in
       atex-entries.js), that top margin/padding is just dead space above
       the story text. Scoped to #slide-out-content so this never touches
       edit.html's own #preview-container #preview-content. */
    #slide-out-content #preview-content {
        margin-top: 0;
        margin-bottom: 6px;
        padding-top: 8px;
    }

    /* ...so the sheet needs its own way out - an in-header close button
       instead of the now-hidden edge handle. */
    #mobile-close-slide-out-btn {
        display: inline-block !important;
    }

    /* Pin removed on mobile - confirmed live as a genuine dead end, not
       just an awkward fit: closing the sheet (the button above) leaves the
       pin toggle unreachable (it lives inside the now-hidden panel), and
       every content-loading path in atex-entries.js has a "don't update if
       pinned" guard, so the preview got permanently stuck showing the last
       pinned item until the page was reloaded. closeMobileSlideOutPanel()
       now also defensively clears the pinned flag itself, but hiding the
       toggle too means it can't be set again in the first place - drag-and-
       drop onto a pinned preview (the toggle's whole reason to exist) isn't
       a usable phone interaction anyway. */
    #toggle-pin {
        display: none;
    }

    /* Page-grid multi-select bar (#autopaginate-selection-bar, built in
       atex-entries.js) - its base styles are a JS-set inline cssText, sized
       to fit its full button row (count + up to 6 buttons) on one line and
       centered via left:50%/transform - comfortably wide enough on desktop,
       but measured live at ~540px natural width against a 375px phone
       screen: centering something wider than the viewport pushes HALF of
       it off-screen on both sides, hiding the selection count and the
       Clear button entirely with no way to reach them. !important
       throughout since all of this is overriding that inline style, not a
       plain stylesheet rule - inline always wins otherwise regardless of
       specificity. Turning the bar itself into a same-height horizontal
       scroll strip (rather than trying to shrink/wrap the buttons to fit)
       keeps every button reachable via a swipe without redesigning the
       button set itself. */
    #autopaginate-selection-bar {
        left: 8px !important;
        right: 8px !important;
        bottom: 8px !important;
        transform: none !important;
        width: auto !important;
        max-width: none !important;
        overflow-x: auto !important;
        flex-wrap: nowrap !important;
        justify-content: flex-start !important;
    }
    #autopaginate-selection-bar > * {
        flex: 0 0 auto !important;
    }
    /* ...and the bar being fixed-position means it sits ON TOP of whatever
       the page grid has scrolled to, not below it - confirmed live as
       "can't reach/select the last page, it's hidden behind the bar".
       has-page-select-bar is toggled on <body> alongside the bar's own
       show/hide (see updateAutoPaginateBar()), so this padding only applies
       while the bar is actually visible - scrolling to the bottom then
       reveals the true last card above the bar instead of underneath it.
       #page-data.page-container, NOT .stories-container - confirmed live
       (walking up from an actual page card's real scrollable ancestor)
       that the page grid scrolls its own nested #page-data, not the
       .stories-container wrapper around it the results list/thumb grid use. */
    body.has-page-select-bar #page-data.page-container {
        padding-bottom: 90px;
    }

    /* Drag-handle-styled bar at the sheet's top edge, doubling as the tap
       target for expand/collapse (see toggleMobilePreviewExpanded()) -
       no actual drag gesture, just the familiar bottom-sheet affordance. */
    #slide-out-sheet-handle {
        display: block;
        width: 40px;
        height: 5px;
        border-radius: 3px;
        background: #ccc;
        margin: 8px auto 2px;
        cursor: pointer;
    }

    /* #slide-out-panel becomes a flex column of one fixed-height section
       (the header - handle stays flex:0 0 auto too) plus one that actually
       grows/scrolls (#slide-out-content) - see there for why, and for the
       matching overflow-y:hidden override on #slide-out-panel itself. This
       is what actually keeps the header (pin/status/action icons/close,
       all consolidated into this one row now) docked in place - it only
       means anything for that row to live "with pin and close" if it then
       stays put while a long story's text scrolls underneath it, rather
       than scrolling away with everything else like it used to. */
    #slide-out-sheet-handle,
    #slide-out-header {
        flex: 0 0 auto;
    }

    /* Status, inline in the header row - see #preview-status-inline in
       entries.html and _renderMobileStatusRow() in atex-entries.js. The
       full status word (e.g. "SUBBING REQUIRED") is too wide to sit next
       to pin/close on a phone, so this is a colour dot standing in for
       it instead (same colour as the desktop bar's status pill - the dot's
       own title attribute carries the actual word for a tap-and-hold),
       plus whichever action icons apply (lock/offline-edit/history/bolt). */
    #preview-status-inline {
        display: flex;
        align-items: center;
        gap: 12px;
        flex: 0 0 auto;
    }
    #preview-status-inline .preview-status-dot {
        display: inline-block;
        width: 12px;
        height: 12px;
        border-radius: 50%;
        border: 1px solid rgba(0, 0, 0, 0.15);
        flex: 0 0 auto;
    }
    #preview-status-inline i {
        font-size: 17px;
        color: #999;
        cursor: pointer;
    }

    /* Preview "Show details" toggle - the exhaustive system/metadata
       field dump and the raw-XML button (see #preview-details,
       renderResults's neighbour loadItemIntoSlideOutPanel() in
       atex-entries.js) are built for someone debugging, not glancing at a
       phone. Collapsed behind this toggle by default on mobile rather
       than removed outright, so that data's still reachable the rare time
       someone on mobile actually needs it. Desktop always shows both, as
       before - .preview-details-toggle stays display:none there (see the
       unconditional rule above) and #preview-details is never given the
       .preview-details-collapsed class to begin with. */
    .preview-details-toggle {
        display: block;
        width: calc(100% - 24px);
        margin: 10px 12px;
        padding: 8px;
        background: #f4f4f4;
        border: 1px solid #ddd;
        border-radius: 6px;
        color: #555;
        font-size: 13px;
        text-align: center;
        cursor: pointer;
    }
    #preview-details.preview-details-collapsed {
        display: none;
    }

    /* Cancel the margin-push that the panels normally trigger */
    .main-container.panel-visible,
    .main-container.shrink {
        margin-right: 0 !important;
    }

    /* Story cards: sensible padding on narrow screens */
    .story-card {
        padding: 10px;
    }
    .stories-container {
        padding: 12px;
    }

    /* Editor: keep buttons wrap-friendly */
    .d-flex.gap-3 {
        flex-wrap: wrap;
    }

    /* Thumbnails: slightly smaller on phones */
    .story-thumbnails img {
        width: 72px;
        height: 72px;
    }

    /* Images-only view (the thumb-grid toggle in the results toolbar): the
       120px minimum tile below was sized for a desktop/mouse layout and
       only fit ~2 per row on a phone screen, wasting most of the width and
       forcing a lot of scrolling. Smaller tiles + tighter gap/padding get a
       denser, more phone-gallery-like 4-per-row grid instead; label/
       placeholder sizes scaled down to match so they don't look oversized
       against the smaller tile. */
    .thumbs-grid {
        grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
        gap: 8px;
        padding: 6px 2px 12px;
    }
    .thumb-label {
        font-size: 10px;
        margin-top: 3px;
    }
    .thumb-placeholder {
        font-size: 24px;
    }

    /* Results list: same table as desktop, same text size - just tighter
       padding and a narrower per-cell cap, rather than restructured into
       stacked cards. Columns that still don't fit fall back to
       .stories-container's existing overflow-x:auto sideways scroll, same
       as desktop. */
    #results-table th,
    #results-table td {
        padding: 5px 5px;
    }
    #results-table td {
        max-width: 110px;
    }
    #results-table tbody tr td:first-child {
        width: 34px;
    }
    #results-table td i {
        font-size: 16px;
    }

    /* Run-script and revision-history icons: dropped entirely on mobile -
       neither is a quick-glance action a phone user needs from the row
       (running a script isn't really a phone task, and history opens a
       whole modal table of its own), and they take up space that'd
       otherwise sit awkwardly since nothing here hovers anyway.
       #results-table tbody (one extra ancestor vs. the unconditional
       desktop rule further down this file) so this wins on specificity,
       not source order. */
    #results-table tbody .script-bolt-icon,
    #results-table tbody .history-icon {
        display: none;
    }

    /* Offline-edit download/check-in (images only) still earns its place
       on a phone - keep it, sticky-pinned like on desktop, just visible
       without a hover to reveal it (nothing hovers on a touchscreen) and
       sized to be tapped with a finger instead of aimed at with a
       cursor. The column only ever needs to fit this one icon now, so it
       can be narrower than the old 3-icon width. */
    #results-table tbody td.script-action-cell {
        width: 30px;
    }
    #results-table tbody tr .script-action-icons {
        opacity: 1;
    }
    #results-table .offline-edit-icon {
        font-size: 15px;
        padding: 3px;
    }
}


/* ─── Drag-and-drop image association ─────────────────────────────────────── */
#slide-out-panel.drop-enabled {
    outline: 2px dashed transparent;
    transition: outline-color 0.2s;
}
#slide-out-panel.drag-over {
    outline: 2px dashed #4a90e2;
    background-color: rgba(74, 144, 226, 0.05);
}
#slide-out-panel.drag-over::after,
#slide-out-panel.drag-over-page::after {
    position: fixed;
    bottom: 20px;
    right: 20px;
    background: #4a90e2;
    color: white;
    padding: 8px 14px;
    border-radius: 6px;
    font-size: 13px;
    font-weight: bold;
    pointer-events: none;
    z-index: 9999;
}
/* Sticky, not absolute: #results-table is often wider than its scrolling
   ancestor (.stories-container, which now has overflow-x:auto - see there
   for why), so a plain fixed-width column at the table's far right can be
   scrolled out of view, and absolute-positioning against the row doesn't
   help since that's still anchored to the row's true (possibly off-screen)
   width, not the visible scrolled viewport. Sticky pins this cell to the
   right edge of whatever's currently visible instead, so the icons are
   always reachable regardless of horizontal scroll position or how narrow
   the slide-out panel makes the table's available space.
   #results-table td (an ID selector) sets padding/overflow/max-width with
   higher specificity than a plain class - qualify with the table id here
   too, or these get silently overridden. */
#results-table td.script-action-cell {
    position: sticky;
    right: 0;
    width: 76px;
    background-color: inherit;
    text-align: center;
    padding: 0 4px;
}
.script-action-icons {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    opacity: 0;
    transition: opacity 0.15s;
}
#results-table tbody tr:hover .script-action-icons {
    opacity: 1;
}
.script-bolt-icon,
.history-icon,
.offline-edit-icon {
    font-size: 13px;
    color: #bbb;
    cursor: pointer;
    transition: color 0.15s;
}
.script-bolt-icon:hover,
.slide-out-bolt-icon:hover {
    color: #f59e0b !important;
}
.history-icon:hover,
.slide-out-history-icon:hover {
    color: #2563eb !important;
}
.offline-edit-icon:hover {
    color: #0d6efd !important;
}

/* Version/audit history table - same visual language as #results-table so
   the history list reads like the results list it was opened from. */
#history-table {
	width: 100%;
	border-collapse: separate;
	border-spacing: 0 3px;
	border-radius: 12px;
	overflow: hidden;
	background-color: #f9f9f9;
	box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
#history-table thead {
	background-color: #f9f9f9;
	color: black;
}
#history-table tbody tr {
	background-color: white;
	transition: background-color 0.2s ease-in-out;
	border: 1px solid #ddd;
}
#history-table tbody tr:hover {
	background-color: #f2f2f2;
}
#history-table tbody tr td {
	border-bottom: 1px solid #ddd;
}
#history-table th, #history-table td {
	text-align: left;
	padding: 6px 6px;
	white-space: nowrap;
}
#history-table td {
	overflow: hidden;
	text-overflow: ellipsis;
	max-width: 260px;
}
#history-table tbody tr.history-row-active {
	background-color: #eef4ff;
}
.history-compare-cell {
	width: 20px;
	text-align: center;
	cursor: default;
}

/* Word-level diff between two selected versions - two full, independently
   readable texts stacked in the same .history-preview-panel-content box the
   single-version preview uses, each labelled with its own version number and
   only its differing spans picked out (one neutral highlight colour on both
   sides - which side it's on already says added-vs-removed, so it doesn't
   need red/green to also carry that meaning). */
.history-diff-side + .history-diff-side {
	margin-top: 14px;
	padding-top: 14px;
	border-top: 1px dashed #ddd;
}
.history-diff-label {
	font-weight: bold;
	font-size: 12px;
	color: #555;
	margin-bottom: 4px;
}
.history-diff-changed {
	background: rgba(255, 196, 0, 0.25);
	border-radius: 2px;
}

/* .editor-tab--active normally goes white to blend into a bordered content
   panel directly beneath it (see edit.html) - here in the history modal
   there's no such panel to visually "attach" to, so the same white just
   disappears into the modal's own white background. Override with an actual
   standout state, scoped to this modal only so the editor page's own tabs
   are untouched. */
#itemHistoryModal .editor-tab--active {
	background: #eef4ff;
	color: #1e40af;
	font-weight: bold;
	border-bottom: 3px solid #2563eb;
}

/* Slide-out panel for previewing a single history-table row's version, same
   position/transition/visual language as #slide-out-panel + #preview-content
   in the main results view (right-edge panel, pastel-yellow accented text
   box) - but its own classes rather than reusing those ids, since the real
   #slide-out-panel already exists elsewhere on this page with its own live
   editing/locking state that a read-only historical version must not touch. */
.history-preview-panel {
	position: fixed;
	top: 0;
	right: -400px;
	width: 400px;
	height: 100%;
	background: #f9f9f9;
	box-shadow: -3px 0 5px rgba(0, 0, 0, 0.2);
	transition: right 0.3s ease;
	overflow-y: auto;
	overflow-x: hidden;
	z-index: 10050;
}
.history-preview-panel.visible {
	right: 0;
}
.history-preview-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	padding: 10px 15px;
	background: #f4f4f4;
	color: black;
	font-weight: bold;
	flex: 0 0 auto;
}
.history-preview-close {
	background: transparent;
	border: none;
	color: black;
	font-size: 24px;
	cursor: pointer;
	line-height: 1;
}
.history-preview-body {
	padding: 20px;
	font-size: 12px;
	line-height: 1.5;
}
.history-preview-panel-content {
	background: #f8f9fa;
	padding: 15px;
	border-radius: 8px;
	box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.1);
	text-align: left;
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
	position: relative;
	overflow: hidden;
}
.history-preview-panel-content pre {
	font-size: 14px;
	color: #666;
	background: rgba(255, 249, 196, 0.2);
	padding: 10px;
	border-radius: 5px;
	border-left: 4px solid #D3D3D3;
	border-right: 4px solid white;
	white-space: pre-wrap;
	word-break: break-word;
	overflow: auto;
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
.history-preview-panel-content pre:dir(rtl) {
	text-align: right;
	border-left: 4px solid white;
	border-right: 4px solid #D3D3D3;
}
.history-preview-thumb {
	display: block;
	max-width: 100%;
	max-height: 340px;
	margin: 0 auto;
	border-radius: 8px;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

/* Bolt icon on thumb cards */
.thumb-bolt-wrap {
    position: absolute;
    top: 4px;
    right: 4px;
}
.thumb-bolt-icon {
    font-size: 22px;
    color: #bbb;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.15s, color 0.15s;
    background: rgba(255,255,255,0.85);
    border-radius: 50%;
    padding: 4px;
}
.clickable-page .thumb-bolt-icon {
    font-size: 20px;
}
.thumb-status {
    width: 100%;
    font-size: 11px;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    text-align: center;
    padding: 2px 4px;
    border-radius: 3px;
    margin-top: 3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.thumb-card:hover .thumb-bolt-icon,
.clickable-page:hover .thumb-bolt-icon {
    opacity: 1;
}
.thumb-bolt-icon:hover {
    color: #f59e0b !important;
}

/* Offline-edit download icon - top-left, mirroring .thumb-bolt-wrap's
   top-right fade-in-on-hover so it reads as part of the same icon family. */
.thumb-offline-wrap {
    position: absolute;
    top: 4px;
    left: 4px;
}
.thumb-offline-icon {
    font-size: 22px;
    color: #bbb;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.15s, color 0.15s;
    background: rgba(255,255,255,0.85);
    border-radius: 50%;
    padding: 4px;
}
.thumb-card:hover .thumb-offline-icon {
    opacity: 1;
}
.thumb-offline-icon:hover {
    color: #0d6efd !important;
}


.thumb-design-icon {
    font-size: 22px;
    color: #bbb;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.15s, color 0.15s;
    background: rgba(255,255,255,0.85);
    border-radius: 50%;
    padding: 4px;
}
.clickable-page .thumb-design-icon {
    font-size: 20px;
}
.thumb-card:hover .thumb-design-icon,
.clickable-page:hover .thumb-design-icon {
    opacity: 1;
}
.thumb-design-icon:hover {
    color: #7c3aed !important;
}

.thumb-remove-icon {
    font-size: 22px;
    color: #bbb;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.15s, color 0.15s;
    background: rgba(255,255,255,0.85);
    border-radius: 50%;
    padding: 4px;
}
.clickable-page .thumb-remove-icon {
    font-size: 20px;
}
.thumb-card:hover .thumb-remove-icon,
.clickable-page:hover .thumb-remove-icon {
    opacity: 1;
}
.thumb-remove-icon:hover {
    color: #dc2626 !important;
}

/* Page design picker - thumbnails styled like the publication view's own
   page cards (rounded corners, soft shadow, subtle hover lift). */
.design-thumb-card {
    transition: transform 0.2s ease;
}
.design-thumb-card img,
.design-thumb-card .design-thumb-placeholder {
    border-radius: 10px;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3);
    transition: box-shadow 0.2s ease;
}
.design-thumb-card:hover {
    transform: translateY(-3px);
}
.design-thumb-card:hover img,
.design-thumb-card:hover .design-thumb-placeholder {
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.4);
}

.clickable-page.page-selected img.page-card {
    box-shadow: 0 0 8px 2px rgba(0, 0, 0, 0.35);
    transform: scale(1.04);
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

#slide-out-panel.drag-over::after {
    content: 'Drop image to associate';
}
#slide-out-panel.drag-over-page::after {
    content: 'Drop story or image to assign to page';
}

.icon-wrap {
    position: relative;
    display: inline-block;
    line-height: 0;
}
.assigned-dot {
    position: absolute;
    bottom: -2px;
    right: -2px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    box-shadow: 0 0 0 2.5px #fff;
    pointer-events: none;
    z-index: 2;
}
.assigned-dot--placed {
    background: #00bcd4;
}
.assigned-dot--unplaced {
    background: #ff00ff;
}
/* Inline variant for the page-preview assignments list (a plain <li>, no
   icon to corner-anchor to) - shares the --placed/--unplaced colour classes
   above, just laid out inline instead of absolutely positioned. */
.assignment-list-dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    margin-right: 6px;
    vertical-align: middle;
}
/* Same corner as .assigned-dot (bottom-right), offset a bit to its left so
   the two sit as a cluster rather than overlapping - "this story has an
   associated image". The dot is added synchronously at initial row render
   while this badge only arrives later via the lock-state poll, so DOM order
   alone can't be trusted to keep the dot on top - explicit z-index does
   instead. Square keeps it shape-distinct from the round dot without
   needing a glyph (an FA icon has too much fill to read cleanly at this
   size and just blurs into a blob). */
.assoc-image-badge {
    position: absolute;
    bottom: -2px;
    right: 8px;
    width: 9px;
    height: 9px;
    border-radius: 0;
    background: #ffc57a;
    box-shadow: 0 0 0 2.5px #fff;
    pointer-events: none;
    z-index: 1;
    transform: rotate(45deg);
}
/* Unplaced assignments-list rows draggable onto the page preview's boxes/areas
   (see draggableAttrs() in atex-entries.js) - grab cursor as the drag hint,
   faded while actively dragging. */
li.clickable-assigned-story[draggable="true"],
li.clickable-assigned-image[draggable="true"] {
    cursor: grab;
}
li.clickable-assigned-story.dragging,
li.clickable-assigned-image.dragging {
    opacity: 0.5;
}

/* ─── Page Tracker mode (PAGETRACKER_MODE, app.py) ──────────────────────────
   View-only install: hide every control that would change something. app.py
   refuses those routes anyway (see _PAGETRACKER_ALLOWED_ENDPOINTS) and
   atex-entries.js swallows double-click / drag-drop / modifier-clicks - this
   just stops offering them. Page-card icons get their opacity set inline on
   hover, hence !important. */
.pagetracker-badge {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	margin-left: 16px;
	margin-right: auto;
	padding: 3px 12px;
	border: 1px solid #ced4da;
	border-radius: 999px;
	background: #fff;
	color: #495057;
	font-size: 13px;
	font-weight: 600;
	white-space: nowrap;
}
[dir="rtl"] .pagetracker-badge {
	margin-left: auto;
	margin-right: 16px;
}
.pagetracker .search-container,
.pagetracker .thumb-bolt-icon,
.pagetracker .thumb-design-icon,
.pagetracker .thumb-remove-icon,
.pagetracker .page-select-wrap,
.pagetracker #autopaginate-selection-bar,
.pagetracker .folder-book-search-icon,
.pagetracker .slide-out-bolt-icon,
.pagetracker .slide-out-history-icon,
.pagetracker .slide-out-checkout-icon,
.pagetracker .slide-out-checkin-icon,
.pagetracker .story-thumb-remove,
.pagetracker #toggle-pin {
	display: none !important;
}
.pagetracker .clickable-status {
	cursor: inherit;
}

/* ─── Edit-on-page frame ──────────────────────────────────────────────────────
   /edit?embed=1 inside the page preview's edit frame (openPageEdit in
   atex-entries.js; _EMBED in atex-edit.js): just the one field, the style
   palette and a save/cancel bar - no banner, tabs, preview panel or XML. */
body.editor-embed {
	background: #fff !important;
	padding-bottom: 52px;
}
.editor-embed .banner,
.editor-embed .editor-tabs,
.editor-embed #tab-panel-images,
.editor-embed #preview-container,
.editor-embed #preview-panel-handle,
.editor-embed #xml-toggle-btn,
.editor-embed #xml-display {
	display: none !important;
}
.editor-embed .main-container,
.editor-embed .main-container.shrink,
.editor-embed .main-container.panel-visible {
	width: auto !important;
	margin: 0 !important;
	padding: 0 !important;
}
.editor-embed .container {
	max-width: none;
	margin: 0 !important;
	padding: 8px 10px 0;
}
.editor-embed #tab-panel-text {
	padding: 0 !important;
	border: none;
	box-shadow: none !important;
}
/* Pinned to the top of the frame (not sticky - the frame scrolls the whole
   document, and sticky depends on every ancestor's layout); the text scrolls
   between it and the fixed save/cancel bar. body's padding-top follows the
   palette's real height, which wraps in a narrow frame (_embedPinPalette). */
.editor-embed #icml-palette {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	margin: 0;
	padding: 5px 8px;
	border-radius: 0;
	border-width: 0 0 1px 0;
	z-index: 600;
}
.editor-embed .icml-field {
	margin-bottom: 4px !important;
}
.embed-bar {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 8px 10px;
	background: #fff;
	border-top: 1px solid #dee2e6;
	z-index: 500;
	font-size: 12px;
}
.embed-spacer {
	flex: 1;
}
.embed-hint {
	color: #6c757d;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.embed-chip {
	display: inline-flex;
	align-items: center;
	padding: 3px 9px;
	border-radius: 12px;
	font-weight: 600;
	font-size: 11.5px;
	white-space: nowrap;
}
.embed-chip--busy  { background: #eef0f4; color: #5f6876; }
.embed-chip--ok    { background: #e6f4ea; color: #1a7f37; }
.embed-chip--over  { background: #fdecec; color: #c0262d; }
.embed-chip--under { background: #e7efff; color: #0053e2; }

/* Page preview: pencil on a story's text box (edit on page) - bottom-right,
   the one corner nothing else uses: the unassign bin owns the story group's
   top-left, the similar-length button its top-right (full screen) and the
   headline wand the headline box's top-right. Same size/look as those. */
.box .page-edit-btn {
	position: absolute;
	bottom: 2px;
	right: 2px;
	display: none;
	background: rgba(0, 0, 0, 0.55);
	color: #fff;
	border: none;
	border-radius: 3px;
	padding: 3px 7px;
	font-size: 1em;
	line-height: normal;
	cursor: pointer;
	z-index: 10;
}
/* full-screen page view only - not the small panel preview */
#page-fullscreen .box:hover .page-edit-btn {
	display: block;
}
.box .page-edit-btn:hover {
	background: rgba(0, 0, 0, 0.75);
}
.box.box--page-editing {
	outline: 2px solid #3b73f5;
	outline-offset: 1px;
}
.box.box--page-editing .page-edit-btn {
	display: none;
}
/* The frame holding /edit?embed=1 (openPageEdit in atex-entries.js) - fixed
   to the viewport and re-positioned onto its box every frame, above the
   full-screen page view (z-index 1500) and the box overlay (.box 9999). */
.page-edit-wrap {
	position: fixed;
	z-index: 10050;
	background: #fff;
	border: 1px solid #c5d5fb;
	border-radius: 8px;
	box-shadow: 0 10px 30px rgba(2, 31, 81, 0.28);
	overflow: hidden;
}
.page-edit-frame {
	display: block;
	width: 100%;
	height: 100%;
	border: 0;
}
.page-edit-loading {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	background: #fff;
	color: #3b73f5;
	font-size: 22px;
}

/* Edit on page: the live HnJ render of the page while an element is being
   edited (_showPageEditLive in atex-entries.js) - laid over the page image
   inside its .page-zoom-layer, under the box overlay, cropped to this page. */
.page-edit-live {
	position: absolute;
	inset: 0;
	overflow: hidden;
	pointer-events: none;
	border-radius: 12px; /* as .page-card img */
}
.page-card .page-edit-live img.page-edit-live-img {
	position: absolute;
	left: 0;
	top: 0;
	width: 100%;
	height: 100%;
	max-width: none;
	border-radius: 0;
	transition: none;
}
/* the edited story's own boxes lose their tint so the render reads cleanly */
.box.box--page-edit-story {
	background: transparent !important;
}
.page-edit-busy {
	position: absolute;
	left: 2px;
	bottom: 2px;
	display: none;
	align-items: center;
	gap: 5px;
	background: rgba(2, 31, 81, 0.8);
	color: #fff;
	border-radius: 3px;
	padding: 2px 7px;
	font-size: 11px;
	white-space: nowrap;
	pointer-events: none;
	z-index: 11;
}
.page-edit-busy.visible {
	display: inline-flex;
}

/* Edit on page: the assignments list (Stories / Images / On Page) gives its
   place to the edit frame while an element is being edited - hidden but
   still taking up (and growing to) the frame's space, which is fixed on top
   of it. See _positionPageEdit in atex-entries.js. */
.assignments-list-panel.pe-reserve,
.page-fs-assignments.pe-reserve {
	visibility: hidden;
	overflow: hidden !important;
	box-sizing: border-box;
}
#page-fullscreen .page-fs-assignments.pe-reserve {
	display: block !important; /* even when it has no list (hidden attr) */
	width: 440px;
	max-height: none;
}

/* Space held in full screen (Space+click edits a text box on the page -
   _pageEditSpaceHeld in atex-entries.js): text cursor on the story boxes. */
body.pe-space-held #page-fullscreen .box[data-item-type="Story"] {
	cursor: text;
}

/* After saving from the page editor: quiet label on the page card until the
   rebuilt page image arrives (_closePageEdit in atex-entries.js) - in place
   of the preview spinner, since the live render already shows the text. */
.page-card .page-edit-saved-badge {
	position: absolute;
	right: 8px;
	bottom: 8px;
	z-index: 20;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 4px 9px;
	border-radius: 12px;
	background: rgba(2, 31, 81, 0.82);
	color: #fff;
	font-size: 12px;
	pointer-events: none;
}
.page-card .page-edit-saved-badge i {
	color: #7ee2a8;
}

/* Galley view: HnJ column breaks (event 'c') as a full-width labelled line,
   and - in the edit-on-page frame, which knows the boxes' pages - the break
   onto the next page stronger still. See _makeGalleyMarker. */
.icml-galley-break.icml-galley-break--column,
.icml-galley-break.icml-galley-break--page {
	display: block;
	margin: 6px 0 4px;
	padding-top: 1px;
	border-top: 1px dashed #3b73f5;
	font-size: 10px;
	line-height: 1.3;
	letter-spacing: 0.03em;
	color: #3b73f5;
	text-align: right;
	text-decoration: none;
	vertical-align: baseline;
}
.icml-galley-break.icml-galley-break--page {
	border-top: 2px dotted #b45309;
	color: #b45309;
	font-weight: 600;
}
.icml-galley-break--loose {
	color: #b91c1c;
	text-decoration: underline;
}
/* Edit-on-page: the text that sits in the box that was clicked */
::highlight(atex-box-text) {
	background-color: rgba(255, 214, 0, 0.35);
}

/* Full-screen page view: an outline on every placed item's box, so each
   element frame of a story (headline, byline, text, caption...) is visible
   - the tint alone runs touching frames together, and .box's own
   "border: 1px pink" has no line style so it never drew. Dashed like the
   empty-area slots (.area-sub-box), drawn inside the box (outline-offset)
   so no box changes size; coloured by fit state, purple for pictures as
   with empty picture slots. Hidden with the tint by the overlay toggle. */
#page-fullscreen .box {
	outline: 1px dashed rgba(107, 142, 35, 0.95);
	outline-offset: -1px;
}
#page-fullscreen .box.box--fits-overset {
	outline-color: #dc3545;
}
#page-fullscreen .box.box--fits-underset {
	outline-color: #0d6efd;
}
#page-fullscreen .box[data-item-type="Image"] {
	outline-color: #6f42c1;
}
#page-fullscreen .box:hover {
	outline-style: solid;
}
#page-fullscreen.overlay-hidden .box {
	outline: none;
}
/* the element being edited keeps its own (stronger) outline */
#page-fullscreen .box.box--page-editing {
	outline: 2px solid #3b73f5;
	outline-offset: 1px;
}

/* Full screen: Ctrl+Shift+drag zoom rectangle, crosshair while the keys are
   held, and the "250% · Ctrl+0 to fit" badge while a page is zoomed. */
.page-zoom-marquee {
	position: fixed;
	z-index: 10060;
	border: 1px dashed #3b73f5;
	background: rgba(59, 115, 245, 0.12);
	pointer-events: none;
}
body.pz-marquee-ready #page-fullscreen .page-card,
body.pz-marquee-ready #page-fullscreen .page-card .box {
	cursor: crosshair !important;
}
#page-fullscreen .page-fs-zoom-badge {
	position: fixed;
	top: 10px;
	left: 50%;
	transform: translateX(-50%);
	z-index: 1600;
	padding: 4px 12px;
	border-radius: 12px;
	background: rgba(2, 31, 81, 0.85);
	color: #fff;
	font-size: 12px;
	pointer-events: none;
}
#page-fullscreen .page-fs-zoom-badge[hidden] {
	display: none;
}
