:root {
  /* Color Tokens */
  --accent: #b8860b;
  --accent-dark: #8a6508;
  --accent-weak: #fcf8ee;
  --accent-strong: #966c07;

  --surface: #f6f7f9;
  --surface-raised: #ffffff;
  --surface-sunken: #eef2f7;

  --text: #1b1b1f;
  --text-muted: #5b6470;
  --text-subtle: #888890;

  --line: #e4e6ea;
  --line-strong: #dfe2e6;

  --danger: #c0392b;
  --danger-hover: #962d22;
  --danger-bg: #fdeceb;
  --danger-border: #f3bcb6;

  --success: #1e7e34;
  --success-bg: #e5f6e8;
  --success-border: #b6e4c0;

  --info-bg: #eef2f7;

  --sidebar-bg: #1b1b1f;
  --sidebar-border: #33333d;
  --sidebar-hover: #2a2a31;
  --sidebar-text: #dddddd;
  --sidebar-scroll-thumb: rgba(255, 255, 255, 0.18);
  --sidebar-scroll-thumb-hover: rgba(255, 255, 255, 0.32);
  --sidebar-text-muted: #888888;
  --sidebar-subhead: #999999;
  --shadow-color: rgba(0, 0, 0, 0.3);
  --veil-bg: rgba(0, 0, 0, 0.45);
  --drag-color: #aaaaaa;

  /* Spacing Tokens */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 28px;
  --space-8: 32px;

  /* Radius Tokens */
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 12px;

  /* Typography Steps */
  --font-family: 'Fira Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --font-size-xs: 0.75rem;
  --font-size-sm: 0.875rem;
  --font-size-base: 1rem;
  --font-size-lg: 1.25rem;
  --font-size-xl: 1.5rem;

  /* Motion */
  --transition: 150ms ease-out;
  --sidebar-width: 240px;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: var(--font-family);
  font-size: var(--font-size-base);
  line-height: 1.5;
  color: var(--text);
  background: var(--surface);
}

/* Kill the macOS/iOS elastic rubber-band everywhere. All scrolling happens in
   inner containers, so an overscroll past the bottom of one would otherwise
   pull the content above it back into view. none on the document catches any
   view that ever overflows the window. */
html,
body {
  overscroll-behavior: none;
}

/* Programmatic scrolling (anchor jumps, scrollIntoView, scrollTop restoration
   after a re-render) should glide instead of teleport. Wheel and trackpad
   input is not affected — that stays native. */
html {
  scroll-behavior: smooth;
}

.sidebar nav,
.cards-list,
.modal-body,
.hp-scroll,
.detail-view {
  scroll-behavior: smooth;
}

:focus-visible {
  outline: 2px solid var(--accent-strong);
  outline-offset: 2px;
}

/* Skip link: only visible when focused, so keyboard users can jump over the
   navigation sidebar's many tab stops straight to the content. */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 2147483647;
  background: var(--accent-strong);
  color: #fff;
  padding: var(--space-2) var(--space-3);
  border-radius: 0 0 var(--radius-md) 0;
  font-weight: 600;
  text-decoration: none;
}

.skip-link:focus {
  left: 0;
  outline: none;
}

@media (prefers-reduced-motion: reduce) {

  *,
  *::before,
  *::after {
    transition: none !important;
    animation: none !important;
    scroll-behavior: auto !important;
  }
}

/* Login Page */
.login-body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  background: linear-gradient(160deg, var(--sidebar-bg), var(--sidebar-border));
}

.login-card {
  background: var(--surface-raised);
  padding: var(--space-6);
  border-radius: var(--radius-lg);
  width: 360px;
  max-width: 90vw;
  box-shadow: 0 20px 50px var(--shadow-color);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.login-card h1 {
  margin: 0;
  font-size: var(--font-size-lg);
}

.login-card .muted {
  margin: 0 0 var(--space-2);
  color: var(--text-muted);
}

.login-brand {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

/* Deploy status pill. Colour carries the meaning at a glance: amber while
   building, green when genuinely live, red only for a real failure. */
.deploy-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: var(--font-size-sm);
  font-weight: 600;
  white-space: nowrap;
  border: 1px solid transparent;
}

.deploy-status[hidden] {
  display: none;
}

/* The "Deployed" badge dismisses itself once the deploy is done. */
.deploy-status {
  transition: opacity 0.4s ease;
}

.deploy-status.deploy-fading {
  opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
  .deploy-status {
    transition: none;
  }
}

.deploy-status::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}

.deploy-building {
  background: var(--accent-weak);
  color: var(--accent-strong);
  border-color: var(--accent);
}

/* Pulse only while work is genuinely in progress. */
.deploy-building::before {
  animation: deploy-pulse 1.2s ease-in-out infinite;
}

@keyframes deploy-pulse {

  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.25;
  }
}

@media (prefers-reduced-motion: reduce) {
  .deploy-building::before {
    animation: none;
  }
}

.deploy-live {
  background: var(--success-bg);
  color: var(--success);
  border-color: var(--success-border);
}

.deploy-failed {
  background: var(--danger-bg);
  color: var(--danger);
  border-color: var(--danger-border);
}

/* Persistent "which version is live" chip. Unlike the transient publish badge,
   it stays on screen while idle, so a deploy failure remains visible long
   after the poll that noticed it has finished. */
.live-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: var(--font-size-sm);
  font-weight: 600;
  white-space: nowrap;
  border: 1px solid transparent;
  max-width: 26rem;
  overflow: hidden;
  text-overflow: ellipsis;
}

.live-status[hidden] {
  display: none;
}

.live-status::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}

.live-status.live-live {
  background: var(--success-bg);
  color: var(--success);
  border-color: var(--success-border);
}

.live-status.live-building {
  background: var(--accent-weak);
  color: var(--accent-strong);
  border-color: var(--accent);
}

.live-status.live-building::before {
  animation: deploy-pulse 1.2s ease-in-out infinite;
}

.live-status.live-failed {
  background: var(--danger-bg);
  color: var(--danger);
  border-color: var(--danger-border);
}

/* Why the Publish button is currently disabled. Native :disabled swallows
   pointer events, so a tooltip can never reach the user — show the reason
   inline instead. */
.publish-block-hint {
  font-size: var(--font-size-sm);
  color: var(--text-muted);
  max-width: 22rem;
  overflow-wrap: break-word;
}

.publish-block-hint[hidden] {
  display: none;
}

/* Language coverage advisory shown in the publish-confirm dialog: one language
   version is more complete than the other. Informational — publishing stays
   possible. Rendered as a set-out box so it reads as a checklist, not raw text. */
.coverage-panel {
  background: #fff8e6;
  border: 1px solid #e7cf8a;
  color: #6b5317;
  border-radius: var(--radius-md);
  padding: var(--space-3);
  font-size: var(--font-size-sm);
  margin-top: var(--space-3);
}

.coverage-panel strong {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 700;
  margin-bottom: var(--space-2);
}

.coverage-panel strong::before {
  content: "△";
  color: #a8862a;
}

.coverage-panel ul {
  margin: 0;
  padding-left: 1.1rem;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.coverage-panel li {
  line-height: 1.4;
}

.coverage-panel .muted {
  margin: var(--space-2) 0 0;
  color: #8a6d1f;
}

.deploy-unknown,
.deploy-idle {
  background: var(--surface);
  color: var(--text-muted);
  border-color: var(--line);
}

/* Deploy history rows */
.deploy-row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--line);
}

.deploy-row:last-child {
  border-bottom: none;
}

.deploy-row-main {
  min-width: 0;
  flex: 1;
}

.deploy-row-msg {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.deploy-row-meta {
  font-size: var(--font-size-sm);
  color: var(--text-muted);
  margin-top: 2px;
}

/* Unpublished-changes banner. Amber (the existing accent), not red: having
   unpublished work is a normal state, not an error. The slot only reserves the
   banner's height while the banner is visible: the initial state is
   server-rendered into the page, so a hidden banner costs nothing and a visible
   one can never arrive late and shift the layout below it. */
.draft-banner-slot {
  margin: 0 var(--space-6);
}

.draft-banner-slot:has(.draft-banner:not([hidden])) {
  min-height: 68px;
  margin: var(--space-4) var(--space-6) 0;
}

.draft-banner {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--accent-weak);
  border: 1px solid var(--accent);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius-md);
  color: var(--text);
  font-size: var(--font-size-sm);
}

.draft-banner[hidden] {
  display: none;
}

.draft-banner>.svg-icon {
  color: var(--accent);
  flex-shrink: 0;
}

.draft-banner-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}

.draft-banner-text span {
  color: var(--text-muted);
}

.draft-banner-actions {
  display: flex;
  gap: var(--space-2);
  flex-shrink: 0;
}

@media (max-width: 720px) {
  .draft-banner-slot {
    margin: 0 var(--space-4);
  }

  .draft-banner-slot:has(.draft-banner:not([hidden])) {
    margin: var(--space-3) var(--space-4) 0;
  }

  .draft-banner {
    flex-wrap: wrap;
  }

  .draft-banner-actions {
    width: 100%;
    justify-content: flex-end;
  }
}

.login-help {
  margin: var(--space-3) 0 0;
  text-align: center;
  font-size: var(--font-size-sm);
}

.login-help a {
  color: var(--text-muted);
}

.login-help a:hover {
  color: var(--accent);
}

.password-wrapper {
  position: relative;
  display: flex;
  align-items: center;
}

.password-wrapper input {
  width: 100%;
  padding-right: 44px;
}

.toggle-password {
  position: absolute;
  right: var(--space-1);
  background: none;
  border: none;
  cursor: pointer;
  padding: var(--space-2);
  min-height: 44px;
  min-width: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
}

.toggle-password:hover {
  color: var(--text);
}

/* Shell Layout */
.shell {
  display: flex;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

.sidebar {
  width: var(--sidebar-width);
  background: var(--sidebar-bg);
  color: var(--sidebar-text);
  display: flex;
  flex-direction: column;
  padding: var(--space-4) 0;
  flex-shrink: 0;
  transition: width var(--transition), transform var(--transition);
  height: 100vh;
  height: 100dvh;
  min-height: 0;
}

.sidebar .brand {
  font-weight: 700;
  padding: 0 var(--space-4) var(--space-4);
  border-bottom: 1px solid var(--sidebar-border);
  margin-bottom: var(--space-2);
  display: flex;
  flex-direction: column;
}

.sidebar .brand span {
  font-weight: 400;
  font-size: var(--font-size-xs);
  color: var(--sidebar-subhead);
}

.sidebar nav {
  display: flex;
  flex-direction: column;
  flex: 1;
  overflow-y: auto;
  min-height: 0;
  overscroll-behavior: none;
  /* Slim scrollbar that reads as part of the dark sidebar rather than the OS. */
  scrollbar-width: thin;
  scrollbar-color: var(--sidebar-scroll-thumb) transparent;
}

/* The nav scrolls, so its children must keep their natural height. Without
   this, expanding every group made flexbox squeeze the headings (which have
   min-height: 0) until they overlapped the items beneath them. */
.sidebar nav>* {
  flex-shrink: 0;
}

.sidebar nav::-webkit-scrollbar {
  width: 6px;
}

.sidebar nav::-webkit-scrollbar-track {
  background: transparent;
}

.sidebar nav::-webkit-scrollbar-thumb {
  background: var(--sidebar-scroll-thumb);
  border-radius: 3px;
}

.sidebar nav::-webkit-scrollbar-thumb:hover {
  background: var(--sidebar-scroll-thumb-hover);
}

/* Group headings double as collapse toggles. They are <button> elements, so the
   `.sidebar button` rule above applies to them too — its 44px min-height and
   larger font must be undone, or the labels stop reading as quiet section
   headings and start competing with the nav items beneath them. */
.sidebar .sidebar-group-heading {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  width: 100%;
  min-height: 0;
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--sidebar-subhead);
  padding: var(--space-4) var(--space-4) var(--space-1);
  font-weight: 700;
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  /* "Workshops & Events" wrapped to two lines once the scrollbar narrowed the
     sidebar; the label stays on one line and the chevron keeps its place. */
  white-space: nowrap;
}

.sidebar .sidebar-group-heading>span {
  overflow: hidden;
  text-overflow: ellipsis;
}

.sidebar .sidebar-group-heading:hover {
  color: var(--sidebar-text);
}

.sidebar .sidebar-group-heading:focus-visible {
  outline: 2px solid var(--accent-strong);
  outline-offset: -2px;
}

.sidebar .sidebar-chevron {
  flex: none;
  width: 10px;
  height: 10px;
  opacity: 0.55;
  transition: transform var(--transition), opacity var(--transition);
}

.sidebar .sidebar-group-heading:hover .sidebar-chevron {
  opacity: 1;
}

.sidebar .sidebar-group-heading[aria-expanded="true"] .sidebar-chevron {
  transform: rotate(90deg);
}

.sidebar-group[hidden] {
  display: none;
}

.sidebar ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.sidebar button {
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  color: var(--sidebar-text);
  padding: var(--space-2) var(--space-4);
  cursor: pointer;
  font-size: var(--font-size-sm);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 44px;
  transition: background-color var(--transition), color var(--transition);
}

.sidebar button .svg-icon {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}

.sidebar button:hover {
  background: var(--sidebar-hover);
}

.sidebar button[aria-current="page"],
.sidebar button.active {
  background: var(--accent);
  color: var(--sidebar-bg);
  font-weight: 600;
}

.logout-form {
  padding: var(--space-3) var(--space-4) 0;
}

.content {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  padding: 0;
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
  flex-shrink: 0;
  background: var(--surface);
  padding: var(--space-4) var(--space-6);
  border-bottom: 1px solid var(--line);
  z-index: 10;
}

.topbar h1,
.topbar #viewTitle {
  font-size: var(--font-size-xl);
  font-weight: 700;
  margin: 0;
}

.topbar-actions {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  flex-wrap: wrap;
}

/* The per-page preview links are secondary to the main actions. Group them
   and separate them with a rule, so the topbar reads as three tiers —
   page previews | site-wide actions | publish — instead of five buttons
   of equal weight all competing for attention. */
#previewLinks {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  flex-wrap: wrap;
}

#previewLinks:not(:empty) {
  padding-right: var(--space-3);
  margin-right: var(--space-1);
  border-right: 1px solid var(--line-strong);
}

@media (max-width: 900px) {
  #previewLinks:not(:empty) {
    padding-right: 0;
    margin-right: 0;
    border-right: none;
  }
}

#view {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  padding: var(--space-5) var(--space-6);
}

#sidebarToggle {
  display: none;
  background: none;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: var(--space-2);
  min-height: 44px;
  min-width: 44px;
  cursor: pointer;
  color: var(--text);
  align-items: center;
  justify-content: center;
}

/* Controls & Form Elements */
label {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: var(--font-size-sm);
  font-weight: 600;
  color: var(--text);
}

label input,
label textarea,
label select,
.input-control {
  font: inherit;
  font-size: var(--font-size-sm);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  font-weight: 400;
  background: var(--surface-raised);
  color: var(--text);
  min-height: 44px;
  transition: border-color var(--transition), box-shadow var(--transition);
}

textarea.input-control,
label textarea {
  min-height: 80px;
}

label input:focus,
label textarea:focus,
label select:focus,
.input-control:focus {
  border-color: var(--accent-strong);
  outline: none;
  box-shadow: 0 0 0 2px var(--accent-weak);
}

label input[aria-invalid="true"],
label textarea[aria-invalid="true"],
label select[aria-invalid="true"] {
  border-color: var(--danger);
}

label.inline {
  flex-direction: row;
  align-items: center;
  gap: var(--space-2);
}

/* Buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-4);
  font: inherit;
  font-size: var(--font-size-sm);
  font-weight: 600;
  cursor: pointer;
  min-height: 44px;
  min-width: 44px;
  text-decoration: none;
  transition: background-color var(--transition), border-color var(--transition), color var(--transition);
}

.btn.small {
  padding: var(--space-1) var(--space-3);
  font-size: var(--font-size-xs);
  min-height: 44px;
}

.btn-primary {
  background: var(--accent);
  color: var(--sidebar-bg);
}

.btn-primary:hover {
  background: var(--accent-dark);
  color: var(--surface-raised);
}

.btn-primary:active {
  background: var(--accent-strong);
}

.btn-ghost {
  background: var(--surface-sunken);
  color: var(--text);
  border: 1px solid var(--line);
}

.btn-ghost:hover {
  background: var(--line-strong);
}

.btn-ghost:active {
  background: var(--line);
}

.btn-danger {
  background: var(--danger);
  color: var(--surface-raised);
}

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

.btn-danger:active {
  background: #7a241a;
}

.btn:disabled,
.btn[disabled] {
  opacity: 0.6;
  cursor: not-allowed;
  pointer-events: none;
}

.btn {
  transition: background-color var(--transition), border-color var(--transition),
    color var(--transition), box-shadow var(--transition), transform 100ms ease-out;
}

.btn:active:not(:disabled) {
  transform: scale(0.97);
}

.btn-primary:hover {
  box-shadow: 0 3px 10px rgba(184, 134, 11, 0.28);
}

.btn .svg-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

/* Alerts & Toast Stack */
/* Bottom-right, not top-right: at the top it covered the Publish live /
   Preview draft buttons exactly when a publish toast was on screen. */
#toast {
  position: fixed;
  bottom: var(--space-4);
  right: var(--space-4);
  z-index: 9999;
  max-width: 360px;
  width: calc(100vw - var(--space-8));
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  pointer-events: none;
}

#toast .alert {
  pointer-events: auto;
}

.alert {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-2);
  font-size: var(--font-size-sm);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.alert.success {
  background: var(--success-bg);
  color: var(--success);
  border: 1px solid var(--success-border);
}

.alert.error {
  background: var(--danger-bg);
  color: var(--danger);
  border: 1px solid var(--danger-border);
}

.alert.info {
  background: var(--info-bg);
  color: var(--text);
  border: 1px solid var(--line);
}

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(6px) scale(0.98);
  }

  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

#toast .alert {
  animation: toast-in 200ms ease-out both;
  transition: opacity 180ms ease, transform 180ms ease;
}

#toast .alert.alert-leaving {
  opacity: 0;
  transform: translateY(6px) scale(0.98);
}

.alert-dismiss {
  background: none;
  border: none;
  font-size: var(--font-size-lg);
  line-height: 1;
  cursor: pointer;
  padding: 0;
  color: inherit;
  min-height: 32px;
  min-width: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.cards-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--space-3);
}

/* Dashboard */
.cards-grid.dash {
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: var(--space-4);
}

/* Section-type picker cards (Add section modal) */
.type-card {
  display: flex !important;
  flex-direction: column !important;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  text-align: center;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-3);
  min-height: 100px;
  cursor: pointer;
  transition: border-color var(--transition), box-shadow var(--transition), background-color var(--transition);
}

.type-card:hover,
.type-card:focus-visible {
  border-color: var(--accent);
  background: var(--accent-weak);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}

.type-card .type-card-icon {
  font-size: 1.7rem;
  line-height: 1;
}

.type-card .type-card-label {
  font-size: var(--font-size-sm);
  font-weight: 600;
  color: var(--text);
}

.dashcard {
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  cursor: pointer;
  transition: border-color var(--transition), box-shadow var(--transition);
}

.dashcard:hover {
  border-color: var(--accent);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}

.dashcard h2 {
  margin: 0 0 var(--space-1);
  font-size: var(--font-size-sm);
  color: var(--text-muted);
}

.dashcard .big {
  font-size: var(--font-size-xl);
  font-weight: 700;
  margin: 0;
  color: var(--text);
}

.hint {
  flex-shrink: 0;
  background: var(--info-bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  font-size: var(--font-size-sm);
  color: var(--text);
  margin-bottom: var(--space-3);
}

.hint-dismissible {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}

.hint-dismissible span {
  flex: 1;
}

.hint-dismissible .alert-dismiss {
  flex-shrink: 0;
  min-height: 24px;
  min-width: 24px;
}

.hint-pending {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  background: var(--accent-weak, #fff8e1);
  border-color: var(--accent, #e0a400);
}

.list-actions {
  flex-shrink: 0;
  margin-bottom: var(--space-3);
}

/* View header: hint on the left, "Add New" pinned to the right */
.view-header {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-3);
}

.view-header .hint {
  margin: 0;
  flex: 1;
  min-width: 0;
}

.view-header .btn {
  flex-shrink: 0;
}

/* Search bar */
.search-bar {
  flex-shrink: 0;
  position: relative;
  display: flex;
  align-items: center;
  margin-bottom: var(--space-3);
}

.search-bar .search-icon {
  position: absolute;
  left: var(--space-3);
  color: var(--text-subtle);
  pointer-events: none;
}

.search-input {
  width: 100%;
  font: inherit;
  font-size: var(--font-size-sm);
  padding: var(--space-2) var(--space-8) var(--space-2) calc(var(--space-8) + 2px);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  color: var(--text);
  min-height: 44px;
  transition: border-color var(--transition), box-shadow var(--transition);
}

.search-input:focus {
  border-color: var(--accent-strong);
  outline: none;
  box-shadow: 0 0 0 2px var(--accent-weak);
}

.search-input::-webkit-search-cancel-button {
  display: none;
}

.search-clear {
  position: absolute;
  right: var(--space-2);
  background: none;
  border: none;
  font-size: var(--font-size-lg);
  line-height: 1;
  cursor: pointer;
  color: var(--text-muted);
  min-height: 32px;
  min-width: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  transition: background-color var(--transition), color var(--transition);
}

.search-clear:hover {
  background: var(--surface-sunken);
  color: var(--text);
}

.item-card.is-filtered-out {
  display: none;
}

/* Skeleton loading text */
.skeleton-text {
  display: inline-block;
  color: transparent;
  background: linear-gradient(90deg, var(--surface-sunken) 25%, var(--line) 37%, var(--surface-sunken) 63%);
  background-size: 400% 100%;
  border-radius: var(--radius-sm);
  animation: skeleton-shimmer 1.4s ease infinite;
}

@keyframes skeleton-shimmer {
  0% {
    background-position: 100% 50%;
  }

  100% {
    background-position: 0 50%;
  }
}

/* Item Cards & Lists */
.cards-list {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  overflow-y: auto;
  min-height: 0;
  padding-right: var(--space-1);
  overscroll-behavior: none;
}

@keyframes card-in {
  from {
    opacity: 0;
    transform: translateY(4px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.item-card {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-3) var(--space-4);
  transition: border-color var(--transition), box-shadow var(--transition);
  animation: card-in 200ms ease-out both;
}

.item-card:hover {
  border-color: var(--line-strong);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}

.item-card .drag-handle {
  cursor: grab;
  color: var(--drag-color);
  font-size: var(--font-size-lg);
  padding: var(--space-1);
  min-height: 44px;
  min-width: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.item-card .thumb {
  width: 52px;
  height: 52px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
  flex-shrink: 0;
}

.item-card .thumb.placeholder {
  background: var(--line);
}

.item-info {
  flex: 1;
  min-width: 0;
}

.item-title {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.item-sub {
  font-size: var(--font-size-xs);
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.item-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
}

/* Language Completeness Indicator */
.lang-badge {
  font-size: var(--font-size-xs);
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  font-weight: 600;
  background: var(--surface-sunken);
  color: var(--text-muted);

  display: inline-flex;
  align-items: center;
  gap: 3px;
}

.lang-badge.complete {
  background: var(--success-bg);
  color: var(--success);
}

.lang-badge.incomplete {
  background: var(--danger-bg);
  color: var(--danger);
}

/* Switch Toggle Component */
.switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  cursor: pointer;
  font-size: var(--font-size-xs);
  user-select: none;
  min-height: 44px;
}

.switch input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.switch-slider {
  width: 36px;
  height: 20px;
  background-color: var(--line-strong);
  border-radius: 20px;
  position: relative;
  transition: background-color var(--transition);
}

.switch-slider::before {
  content: "";
  position: absolute;
  width: 16px;
  height: 16px;
  left: 2px;
  top: 2px;
  background-color: var(--surface-raised);
  border-radius: 50%;
  transition: transform var(--transition);
}

.switch input:checked+.switch-slider {
  background-color: var(--success);
}

.switch input:checked+.switch-slider::before {
  transform: translateX(16px);
}

.switch input:focus-visible+.switch-slider {
  outline: 2px solid var(--accent-strong);
  outline-offset: 2px;
}

/* Tab Component */
.tab-list {
  display: flex;
  gap: var(--space-1);
  border-bottom: 2px solid var(--line);
  margin-bottom: var(--space-4);
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
  /* Inside a flex column (e.g. .detail-view) this would otherwise be shrunk to
     the height of its own border, hiding the tab buttons entirely. */
  flex: none;
}

.tab-list::-webkit-scrollbar {
  display: none;
}

/* Card modal: the DE/EN tabs sit at the top of a scrolling .modal-body, so
   they scroll away on long forms (e.g. the workshops card). Pin them to the
   top of the body, bleeding the background across the body's padding, like the
   detail editor header. Sticky offsets are measured from the body's padding
   edge, so top is pulled up by the body's top padding; with top: 0 the fields
   scroll through that padding band above the tabs. */
.modal-body .tab-list {
  position: sticky;
  top: calc(var(--space-4) * -1);
  z-index: 6;
  background: var(--surface-raised);
  margin: 0 calc(var(--space-5) * -1);
  padding: var(--space-1) var(--space-5);
}

/* When the tabs open the body, pull them up over its top padding so they sit
   flush under the modal header instead of below a blank band. The empty error
   summary slot is hidden so its flex gap doesn't add to that band. */
.modal-body>#errorSummaryContainer:empty {
  display: none;
}

.modal-body>form:first-child>.tab-list:first-child,
.modal-body>#errorSummaryContainer:empty+form>.tab-list:first-child {
  margin-top: calc(var(--space-4) * -1);
}

/* Custom Thin Scrollbars */
.modal-body::-webkit-scrollbar,
#view::-webkit-scrollbar,
.cards-list::-webkit-scrollbar,
.hp-scroll::-webkit-scrollbar,
#detailForm::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

.modal-body::-webkit-scrollbar-track,
#view::-webkit-scrollbar-track,
.cards-list::-webkit-scrollbar-track,
.hp-scroll::-webkit-scrollbar-track,
#detailForm::-webkit-scrollbar-track {
  background: transparent;
}

.modal-body::-webkit-scrollbar-thumb,
#view::-webkit-scrollbar-thumb,
.cards-list::-webkit-scrollbar-thumb,
.hp-scroll::-webkit-scrollbar-thumb,
#detailForm::-webkit-scrollbar-thumb {
  background: var(--line-strong);
  border-radius: 6px;
}

.modal-body::-webkit-scrollbar-thumb:hover,
#view::-webkit-scrollbar-thumb:hover,
.cards-list::-webkit-scrollbar-thumb:hover,
.hp-scroll::-webkit-scrollbar-thumb:hover,
#detailForm::-webkit-scrollbar-thumb:hover {
  background: var(--text-subtle);
}

/* Radio Inline Options */
.radio-inline-group {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-top: 4px;
  margin-bottom: var(--space-2);
}

.radio-inline {
  display: inline-flex !important;
  flex-direction: row !important;
  align-items: center !important;
  gap: 6px !important;
  font-size: var(--font-size-sm);
  font-weight: 500;
  color: var(--text);
  cursor: pointer;
  user-select: none;
}

.radio-inline input[type="radio"] {
  accent-color: var(--accent);
  width: 15px;
  height: 15px;
  cursor: pointer;
  margin: 0;
}

/* Preset Radio Segment Cards */
.preset-radio-group {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-1);
  margin-bottom: var(--space-2);
  flex-wrap: wrap;
}

.preset-radio-card {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  cursor: pointer;
  user-select: none;
  font-size: var(--font-size-xs);
  font-weight: 500;
  color: var(--text);
  transition: all var(--transition);
}

.preset-radio-card:hover {
  border-color: var(--accent);
  background: var(--accent-weak);
}

.preset-radio-card input[type="radio"] {
  accent-color: var(--accent);
  width: 14px;
  height: 14px;
  cursor: pointer;
  margin: 0;
}

.preset-radio-card.selected {
  border-color: var(--accent);
  background: var(--accent-weak);
  font-weight: 600;
  color: var(--accent-strong);
}

.tab-btn {
  padding: var(--space-2) var(--space-4);
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  font-size: var(--font-size-sm);
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  transition: color var(--transition), border-color var(--transition);
}

.tab-btn:hover {
  color: var(--text);
}

.tab-btn[aria-selected="true"],
.tab-btn.active {
  color: var(--accent-strong);
  border-bottom-color: var(--accent-strong);
}

/* Detail editor: DE/EN tab row with the layout switch pinned on the right.
   The tab-list keeps its own bottom border; the row just holds them apart. */
.detail-tabs-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.detail-tabs-row .tab-list {
  flex: 1;
  margin-bottom: 0;
}

.detail-layout-toggle {
  display: inline-flex;
  gap: var(--space-1);
  flex: none;
}

.layout-btn {
  font: inherit;
  font-size: var(--font-size-xs);
  font-weight: 600;
  padding: var(--space-1) var(--space-2);
  background: none;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  cursor: pointer;
  min-height: 32px;
  transition: color var(--transition), border-color var(--transition),
    background var(--transition);
}

.layout-btn:hover {
  color: var(--text);
  border-color: var(--line-strong);
}

.detail-layout-toggle .layout-btn.active {
  background: var(--accent-weak);
  border-color: var(--accent-strong);
  color: var(--accent-strong);
}

.tab-badge-warn {
  color: var(--danger);
  font-weight: bold;
}

.tab-panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.tab-panel[hidden] {
  display: none !important;
}

/* Error Summary */
.error-summary {
  background: var(--danger-bg);
  border: 1px solid var(--danger-border);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
  color: var(--danger);
}

.error-summary h4 {
  margin: 0 0 var(--space-2);
  font-size: var(--font-size-sm);
}

.error-summary ul {
  margin: 0;
  padding-left: var(--space-4);
  font-size: var(--font-size-sm);
}

.error-summary a {
  color: var(--danger);
  text-decoration: underline;
}

.field-error-text {
  font-size: var(--font-size-xs);
  color: var(--danger);
  margin-top: var(--space-1);
}

.field-hint {
  font-size: 11px;
  color: var(--text-subtle);
  font-weight: 400;
  margin-top: 3px;
  line-height: 1.35;
  display: block;
}

.field-hint.counter-warn {
  color: #7a4e07;
  font-weight: 600;
  background: #fdf1d7;
  border: 1px solid #e7cf8a;
  border-radius: var(--radius-sm, 4px);
  padding: 2px 6px;
}

.field-hint.counter-over {
  color: var(--danger);
  font-weight: 700;
  background: var(--danger-border);
  border: 1px solid var(--danger);
  border-radius: var(--radius-sm, 4px);
  padding: 2px 6px;
}

.muted {
  color: var(--text-muted);
  font-size: var(--font-size-sm);
}

.badge-current {
  display: inline-block;
  font-size: var(--font-size-xs);
  font-weight: 600;
  color: var(--accent-strong);
  background: var(--accent-weak);
  border-radius: var(--radius-sm);
  padding: 1px 8px;
  margin-left: var(--space-2);
  vertical-align: middle;
}

/* Version history diff view */
.diff-list {
  list-style: none;
  margin: 0 0 var(--space-3);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.diff-list h4 {
  margin: var(--space-3) 0 var(--space-2);
}

.diff-list>li {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
}

.diff-sublist {
  list-style: none;
  margin: var(--space-2) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.diff-sublist>li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
  padding: var(--space-1) 0;
  border-top: 1px dashed var(--line);
  font-size: var(--font-size-sm);
}

.diff-field {
  font-weight: 600;
  min-width: 140px;
}

.diff-old {
  color: var(--danger);
  text-decoration: line-through;
  word-break: break-word;
}

.diff-new {
  color: var(--success, #1a7f37);
  font-weight: 600;
  word-break: break-word;
}

.diff-arrow {
  color: var(--text-subtle);
}

body.modal-open {
  overflow: hidden;
}

/* Modal Shell */
.modal-veil {
  position: fixed;
  inset: 0;
  background: var(--veil-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9998;
  overflow: hidden;
  padding: var(--space-4) var(--space-3);
  opacity: 0;
  transition: opacity 180ms ease;
}

.modal-veil.visible {
  opacity: 1;
}

.modal-veil[hidden] {
  display: none;
}

.modal {
  background: var(--surface-raised);
  border-radius: var(--radius-lg);
  padding: 0;
  width: 560px;
  max-width: 100%;
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - var(--space-6));
  box-shadow: 0 10px 30px var(--shadow-color);
  overflow: hidden;
  transform: translateY(10px) scale(0.98);
  opacity: 0;
  transition: transform 180ms ease, opacity 180ms ease;
}

.modal-veil.visible .modal {
  transform: translateY(0) scale(1);
  opacity: 1;
}

.modal.modal-wide {
  width: 760px;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--line);
  background: var(--surface-raised);
  flex-shrink: 0;
}

.modal-header h3 {
  margin: 0;
  font-size: var(--font-size-lg);
}

.modal-body {
  overflow-y: auto;
  flex: 1;
  padding: var(--space-4) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  overscroll-behavior: none;
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  border-top: 1px solid var(--line);
  background: var(--surface-raised);
  flex-shrink: 0;
}

/* A single labeled field inside a form. display:flex + flex-direction:column here
   (not a plain block) is required: flexbox's default cross-axis stretch is what
   makes the input/textarea fill the full row width — a block label would let the
   input shrink to its tiny intrinsic default width instead. */
.field-row {
  display: flex !important;
  flex-direction: column !important;
  gap: var(--space-1);
  width: 100%;
}

.field-row>textarea,
.field-row>input,
.field-row>select,
.field-row>.dropzone {
  width: 100%;
}

.layout-field-row {
  display: flex;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.layout-field-row label {
  flex: 1;
  min-width: 160px;
}

/* Top / up / down / bottom controls on a list card. */
.move-group {
  display: inline-flex;
  gap: 2px;
}

.move-group .btn:disabled {
  opacity: 0.35;
  cursor: default;
}

/* Heading row of a repeatable list in a dialog: the title may wrap, the Add
   button never does. */
.item-list-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-3);
}

.item-list-head h4 {
  margin: 0;
  min-width: 0;
}

.item-list-head .btn {
  flex: none;
  white-space: nowrap;
}

/* A one-line pointer from a dialog to the screen where related content is
   managed (e.g. the homepage logos section to the Trusted-by Logos list). */
.linked-note {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-top: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-sunken);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
}

.linked-note-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.linked-note-text span {
  font-size: var(--font-size-sm);
  color: var(--text-muted);
}

.linked-note .btn {
  flex: none;
  white-space: nowrap;
}

@media (max-width: 520px) {
  .linked-note {
    flex-direction: column;
    align-items: flex-start;
  }
}

.shared-section-divider {
  margin: var(--space-4) 0 var(--space-3);
  border-top: 1px solid var(--line);
  padding-top: var(--space-3);
  font-weight: 700;
  font-size: var(--font-size-xs);
  text-transform: uppercase;
  color: var(--text-muted);
  letter-spacing: 0.05em;
}

/* Dropzone & Upload */
.dropzone {
  border: 2px dashed var(--line-strong);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  text-align: center;
  background: var(--surface);
  cursor: pointer;
  transition: border-color var(--transition), background-color var(--transition);
}

.dropzone:hover,
.dropzone.dragover {
  border-color: var(--accent);
  background: var(--accent-weak);
}

/* While uploading, the dropzone fills left to right with the progress set in
   --upload-progress by EditorShared.uploadFromDropzone(). */
.dropzone-in-flight {
  pointer-events: none;
  border-style: solid;
  border-color: var(--accent);
  background: linear-gradient(
    to right,
    var(--accent-weak) var(--upload-progress, 0%),
    var(--surface) var(--upload-progress, 0%)
  );
}

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

.upload-error[hidden] {
  display: none;
}

.file-preview img {
  max-width: 140px;
  max-height: 90px;
  border-radius: var(--radius-sm);
  margin-top: var(--space-2);
  display: block;
}

.panel {
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.theme-color-grid {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--surface);
}

.theme-color-row {
  display: flex !important;
  flex-direction: row !important;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--line);
  transition: background-color var(--transition);
}

.theme-color-row:last-child {
  border-bottom: none;
}

.theme-color-row:hover {
  background: var(--surface-raised);
}

.theme-color-label {
  flex: 1;
  min-width: 0;
  font-weight: 600;
  font-size: var(--font-size-sm);
  line-height: 1.4;
}

.theme-color-label .field-hint {
  font-weight: 400;
  margin-top: 1px;
}

@media (max-width: 520px) {
  .theme-color-row {
    flex-wrap: wrap;
    row-gap: var(--space-2);
  }

  .theme-color-label {
    flex-basis: 100%;
  }

  .color-field {
    width: 100%;
  }
}

/* Single-pill color picker: swatch + hex code inside one bordered field */
.color-field {
  display: flex !important;
  flex-direction: row !important;
  align-items: center;
  gap: var(--space-2);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  padding: 0 var(--space-3) 0 0;
  min-height: 44px;
  width: 150px;
  flex-shrink: 0;
  transition: border-color var(--transition), box-shadow var(--transition);
}

.color-field:focus-within {
  border-color: var(--accent-strong);
  box-shadow: 0 0 0 2px var(--accent-weak);
}

.color-field input[type="color"] {
  appearance: none;
  -webkit-appearance: none;
  flex-shrink: 0;
  width: 22px !important;
  height: 22px !important;
  min-width: 22px !important;
  min-height: 22px !important;
  margin-left: var(--space-3);
  padding: 0 !important;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  background: none;
  overflow: hidden;
}

.color-field input[type="color"]::-webkit-color-swatch-wrapper {
  padding: 0;
  border-radius: 5px;
}

.color-field input[type="color"]::-webkit-color-swatch {
  border: 1px solid rgba(0, 0, 0, 0.15);
  border-radius: 5px;
}

.color-field input[type="text"] {
  flex: 1;
  min-width: 0;
  border: none !important;
  background: transparent !important;
  padding: 0 !important;
  min-height: auto !important;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--font-size-xs);
  color: var(--text);
}

.color-field input[type="text"]:focus {
  outline: none;
  box-shadow: none !important;
}

.color-field input[type="text"]::placeholder {
  color: var(--text-subtle);
  font-family: inherit;
}

/* Homepage Builder View */
.hp-view {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.hp-header {
  flex-shrink: 0;
}

.hp-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: none;
  padding-right: var(--space-1);
}

/* .cards-list is a scroller in its own right in the list views, but inside
   .hp-scroll the OUTER container owns scrolling. Nested, it sized to its full
   content (flex:1 is inert here — .hp-scroll is not a flex parent), so it had
   nothing to scroll while its overscroll-behavior stopped the wheel
   from chaining outwards: the wheel did nothing over the cards, and only
   dragging the scrollbar worked. */
.hp-scroll .cards-list {
  overflow: visible;
  overscroll-behavior: auto;
  flex: none;
  min-height: auto;
  padding-right: 0;
}

/* Account page: center the password-change panel on the page */
.account-view {
  flex: 1;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  min-height: 0;
  padding: var(--space-6) var(--space-4);
  overflow-y: auto;
}

/* One tabbed card rather than two loose panels: keeps the page anchored and
   gives each section the full width instead of two half-empty columns. */
.account-card {
  width: 100%;
  max-width: 560px;
  background: var(--surface-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: var(--space-5) var(--space-6) var(--space-6);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
  animation: card-in 200ms ease-out both;
}

.account-card .tab-list {
  margin-bottom: var(--space-5);
}

.account-tab-panel h3 {
  margin: 0;
  font-size: var(--font-size-lg);
}

/* The history list can grow; keep the card from running off the screen. */
#deployHistory {
  max-height: 420px;
  overflow-y: auto;
}

.account-panel {
  width: 100%;
  max-width: 420px;
  animation: card-in 200ms ease-out both;
}

.account-panel h3 {
  margin: 0;
}

@media (max-width: 640px) {
  .account-view {
    padding: var(--space-4) var(--space-3);
  }

  .account-card {
    padding: var(--space-4);
  }
}

/* Detail Editor View */
.detail-view {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: none;
}

.detail-sticky {
  /* The header (breadcrumb + Save/Cancel) and the DE/EN tabs stay pinned while
     the form below scrolls, so switching languages is always one click away.
     The whole block is sticky, not just the tabs, so nothing scrolls through
     the 12px gap between the two. No negative side margins: .detail-view is
     the scroll container, so a bleed was clipped anyway and only added a
     sideways scroll that let the whole editor shift left. */
  position: sticky;
  top: 0;
  z-index: 9;
  background: var(--surface);
  margin: 0;
  padding: var(--space-3) 0 0;
  flex: none;
}

.detail-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.repeatable-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.repeatable-item {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: var(--space-3);
}

.repeatable-item .drag-handle {
  cursor: grab;
  color: var(--drag-color);
  padding-top: var(--space-2);
}

.repeatable-fields {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* One language at a time inside a repeatable row. Both languages stay in the
   DOM so the form still reads them on save; only the inactive one is hidden. */
.lang-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.lang-field[hidden],
.lang-panel[hidden],
.tab-panel[hidden] {
  display: none !important;
}

/* "One quote for both languages" toggle on testimonial rows. */
.common-toggle {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--text-muted);
  cursor: pointer;
  user-select: none;
}

.common-toggle input {
  margin: 0;
  accent-color: var(--accent-strong);
}

/* Side-by-side language editing: both panels and every per-language field are
   forced visible, and the form becomes a two-column grid. Overrides the hidden
   toggling above, so it must come after and carry the same weight. */
.detail-view.layout-split .lang-panel[hidden],
.detail-view.layout-split .lang-field[hidden] {
  display: block !important;
}

.detail-view.layout-split #detailForm {
  display: grid !important;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-4);
  align-items: start;
}

.detail-view.layout-split .shared-section-divider {
  grid-column: 1 / -1;
}

.detail-view.layout-split #detail-panel-de,
.detail-view.layout-split #detail-panel-en {
  display: block !important;
  min-width: 0;
}

.detail-view.layout-split #detail-panel-de>.panel,
.detail-view.layout-split #detail-panel-en>.panel {
  height: 100%;
}

/* In split mode only the two language panels sit side by side. Every shared
   panel spans both columns, and inside it the per-language fields take one
   column each (German left, English right) while everything language-neutral
   spans the full row. */
.detail-view.layout-split #detailForm>.panel {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
  column-gap: var(--space-4);
}

.detail-view.layout-split #detailForm>.panel>*:not(.lang-field) {
  grid-column: 1 / -1;
}

/* The same German/English pairing inside each repeatable row. */
.detail-view.layout-split .repeatable-fields {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
}

.detail-view.layout-split .repeatable-fields>*:not(.lang-field) {
  grid-column: 1 / -1;
}

/* Empty state */
.empty-state {
  text-align: center;
  padding: var(--space-8) var(--space-4);
  background: var(--surface-raised);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  animation: card-in 220ms ease-out both;
}

.empty-state[hidden] {
  display: none;
}

/* Search "no matches", rendered inside the scrolling card list. Sits flush
   within the panel border instead of overflowing past it. */
.empty-state.is-inline {
  margin: auto 0;
  padding: var(--space-6) var(--space-4);
  background: transparent;
  border: 0;
}

.empty-state .svg-icon {
  width: 48px;
  height: 48px;
  color: var(--text-subtle);
}

.empty-state p {
  margin: 0;
  color: var(--text-muted);
  max-width: 400px;
}

/* Responsive Media Queries */
@media (max-width: 1023px) {
  :root {
    --sidebar-width: 64px;
  }

  .sidebar .brand span,
  .sidebar button span:not(.svg-icon),
  .sidebar .sidebar-group-heading {
    display: none;
  }

  .sidebar .brand {
    align-items: center;
    padding: 0 0 var(--space-4);
  }

  .sidebar button {
    justify-content: center;
    padding: var(--space-2);
  }

  .logout-form {
    padding: var(--space-3) var(--space-2) 0;
  }

  .logout-form button span:not(.svg-icon) {
    display: none;
  }
}

@media (max-width: 767px) {
  #sidebarToggle {
    display: inline-flex;
  }

  .shell {
    position: relative;
  }

  .sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 9990;
    width: 240px;
    transform: translateX(-100%);
    box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
  }

  .sidebar.open {
    transform: translateX(0);
  }

  .sidebar.open .brand span,
  .sidebar.open button span:not(.svg-icon),
  .sidebar.open .sidebar-group-heading {
    display: flex;
  }

  .sidebar.open button {
    justify-content: flex-start;
    padding: var(--space-2) var(--space-4);
  }

  .content {
    padding: var(--space-4);
  }

  .topbar {
    flex-direction: column;
    align-items: flex-start;
  }

  .topbar-actions {
    width: 100%;
    justify-content: flex-start;
  }

  .view-header {
    flex-wrap: wrap;
  }

  .view-header .hint {
    flex-basis: 100%;
  }

  .view-header .btn {
    width: 100%;
  }

  /* At phone widths the card row is far too narrow for buttons + badges +
     title on one line: a title collapsed to "E…" and the badges overflowed.
     Stack the card: info first, actions wrapped onto their own row. */
  .item-card {
    flex-wrap: wrap;
  }

  .cards-list .item-card .thumb {
    width: 44px;
    height: 44px;
  }

  .item-title,
  .item-sub {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
  }

  .cards-list .item-actions {
    width: 100%;
    justify-content: flex-end;
    flex-wrap: wrap;
    row-gap: var(--space-1);
  }
}

/* ---------- Rich text fields (FAQ answers, agenda bodies) ---------- */
/* The underlying <textarea> stays in the DOM so form reads are unchanged; it is
   simply hidden behind the editable surface. */
.rt-source {
  display: none !important;
}

.rt-wrap {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  overflow: hidden;
}

.rt-wrap:focus-within {
  border-color: var(--accent-strong);
  box-shadow: 0 0 0 3px var(--accent-soft, rgba(150, 108, 7, 0.12));
}

.rt-toolbar {
  display: flex;
  gap: 2px;
  padding: var(--space-1);
  background: var(--surface-sunken, #f8f9fa);
  border-bottom: 1px solid var(--border);
}

.rt-btn {
  min-width: 30px;
  height: 28px;
  padding: 0 var(--space-2);
  border: 1px solid transparent;
  border-radius: var(--radius-xs, 4px);
  background: none;
  color: var(--text-muted);
  font-size: var(--font-size-xs);
  font-family: inherit;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--transition), color var(--transition);
}

.rt-btn:hover {
  background: var(--surface);
  color: var(--text);
  border-color: var(--border);
}

.rt-btn:active {
  background: var(--border);
}

.rt-editable {
  min-height: 92px;
  max-height: 340px;
  overflow-y: auto;
  padding: var(--space-2) var(--space-3);
  font-size: var(--font-size-sm);
  line-height: 1.6;
  color: var(--text);
  /* The page base weight is 600, and Chromium treats everything >= 600 as
     already bold, which turns execCommand("bold") into "unbold". Give the
     editor a normal-weight basis so the bold toggle works in both directions. */
  font-weight: 400;
  outline: none;
}

.rt-editable:empty::before {
  content: attr(data-placeholder);
  color: var(--text-muted);
  pointer-events: none;
}

.rt-editable>*:first-child {
  margin-top: 0;
}

.rt-editable>*:last-child {
  margin-bottom: 0;
}

.rt-editable p {
  margin: 0 0 var(--space-2);
}

.rt-editable ul,
.rt-editable ol {
  margin: 0 0 var(--space-2);
  padding-left: 1.35em;
}

.rt-editable li {
  margin-bottom: 0.25em;
}

.rt-editable a {
  color: var(--accent-strong);
  text-decoration: underline;
}

/* Accent spans mirror the published page so a colour change shows up while
   you type, not only after publishing. Near-black accents get a touch of
   weight so they read as emphasis on light surfaces too. */
.rt-editable .c-accent {
  color: #80384a;
}

.rt-editable .c-ink,
.rt-editable .em-alt {
  color: #2f2f2f;
  font-weight: 600;
}

.rt-editable .c-board {
  color: #101815;
  font-weight: 600;
}

/* ---------- Read-only event summary on the workshop detail page ---------- */
.readonly-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--space-3);
  margin: 0;
  padding: var(--space-3);
  background: var(--surface-sunken, #f8f9fa);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.readonly-grid dt {
  font-size: var(--font-size-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 2px;
}

.readonly-grid dd {
  margin: 0;
  font-weight: 600;
  color: var(--text);
}

.edit-on-card {
  color: var(--accent-strong);
}

/* Inline rich-text fields (highlight descriptions) sit inside a list item on the
   published page, so they are single-paragraph and need less height. */
.rt-wrap.rt-inline .rt-editable {
  min-height: 46px;
}

/* ---------- Repeatable rows (highlights, agenda, FAQ) ---------- */
/* Inputs inside these rows are bare — there is no wrapping <label> — so the
   `label input` rules above never reached them and they rendered as unstyled
   browser defaults next to the styled rich-text editors. */
.repeatable-fields input[type="text"],
.repeatable-fields textarea:not(.rt-source) {
  width: 100%;
  font: inherit;
  font-size: var(--font-size-sm);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  color: var(--text);
  transition: border-color var(--transition), box-shadow var(--transition);
}

.repeatable-fields input[type="text"]:focus,
.repeatable-fields textarea:not(.rt-source):focus {
  border-color: var(--accent-strong);
  outline: none;
  box-shadow: 0 0 0 2px var(--accent-weak);
}

/* The first field of a row is the bullet's bold title on the published page,
   so it leads the row visually rather than looking like a second body field. */
.repeatable-fields>.lang-field>input[type="text"]:first-child {
  font-weight: 600;
  font-size: var(--font-size-md, 1rem);
  min-height: 44px;
}

.repeatable-fields input[type="text"]::placeholder,
.repeatable-fields textarea::placeholder {
  font-weight: 400;
  color: var(--text-muted);
}

/* Tie the editor to the title above it as one control. */
.repeatable-fields .rt-wrap {
  margin-top: var(--space-1);
}

/* Suggestion shown when the agenda's day steps do not match the stated duration */
.day-suggestion {
  margin-top: var(--space-3);
  padding: var(--space-3);
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-sunken, #f8f9fa);
  font-size: var(--font-size-sm);
  color: var(--text-muted);
}
/* Executive Briefing panel.
   Not part of the website's draft/publish content: these PDFs live outside
   SITE_ROOT and go live the moment they are uploaded, so this screen has no
   Preview/Publish and says so. */
.briefing-view {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: var(--space-5) var(--space-4);
}

.briefing-inner { max-width: 940px; margin: 0 auto; }

/* One-line intro with an info affordance: the full explanation is reference
   material and does not need re-reading on every visit. */
.bf-intro {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 var(--space-4);
  color: #6b665e;
  font-size: .92em;
}
.bf-info {
  display: inline-flex;
  color: #b9a06a;
  cursor: help;
}
.bf-info:focus-visible { outline: 2px solid #b9a06a; outline-offset: 2px; border-radius: 50%; }

.briefing-note,
.briefing-warn {
  padding: var(--space-3);
  border-radius: 8px;
  margin: 0 0 var(--space-4);
  line-height: 1.6;
}
.briefing-note { border-left: 3px solid #b9a06a; background: #faf8f4; }
.briefing-warn { border-left: 3px solid #b3261e; background: #fdf3f2; }

.briefing-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4);
}
@media (max-width: 900px) { .briefing-grid { grid-template-columns: 1fr; } }

.bf-card {
  background: #fff;
  border: 1px solid #e4e2dd;
  border-radius: 12px;
  padding: var(--space-4);
}

.bf-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}
.bf-head h3 { margin: 0 0 2px; }
.bf-who { margin: 0; font-size: .85em; color: #6b665e; }

.bf-badge {
  flex: none;
  font-size: .72em;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: 4px 9px;
  border-radius: 999px;
  background: #ececea;
  color: #6b665e;
  white-space: nowrap;
}
.bf-badge.on { background: #e6f4e8; color: #276b2d; }
.bf-badge.warn { background: #fdf0d9; color: #8a5a00; }

/* One click target: choosing or dropping a file uploads immediately. */
.bf-drop {
  border: 1.5px dashed #cfcbc4;
  border-radius: 10px;
  padding: var(--space-4) var(--space-3);
  text-align: center;
  cursor: pointer;
  color: #6b665e;
  transition: border-color .15s, background .15s;
}
.bf-drop:hover,
.bf-drop:focus-visible { border-color: #b9a06a; background: #faf8f4; outline: none; }
.bf-drop.over { border-color: #b9a06a; background: #f4efe4; border-style: solid; }
.bf-drop.busy { opacity: .6; pointer-events: none; }

.bf-drop svg { color: #b9a06a; margin-bottom: 6px; }
.bf-drop-main { margin: 0 0 4px; font-size: .95em; color: #3a3833; }
.bf-link { color: #8a6d2f; text-decoration: underline; }
.bf-drop-sub { margin: 0; font-size: .82em; }

/* Staged file: shown between choosing and confirming. Replacing the live PDF
   cannot be undone, so it is never a single click. */
.bf-staged {
  margin-top: var(--space-3);
  padding: var(--space-3);
  border: 1px solid #e4e2dd;
  border-left: 3px solid #b9a06a;
  border-radius: 8px;
  background: #faf8f4;
}
.bf-staged-name { margin: 0 0 6px; font-size: .9em; word-break: break-word; }
.bf-staged-warn {
  margin: 0 0 10px;
  font-size: .82em;
  color: #8a5a00;
}
.bf-actions { display: flex; gap: .5rem; flex-wrap: wrap; }
.bf-actions .btn { font-size: .9em; }

/* Stacked, not side by side: a long error message squeezed the link into a
   three-line column. */
.bf-foot {
  margin-top: var(--space-3);
  min-height: 1.4em;
}
.bf-view {
  display: inline-block;
  font-size: .85em;
  color: #8a6d2f;
  white-space: nowrap;
}
.bf-msg {
  display: block;
  margin-top: 4px;
  font-size: .85em;
  color: #6b665e;
}
.bf-msg.good { color: #276b2d; }
.bf-msg.bad { color: #b3261e; }

/* .btn sets display:flex, which beats the plain `hidden` attribute, so a
   hidden button still showed. Needed by the Executive Briefing screen, which
   hides the website-only Preview/Publish controls. */
.topbar-actions .btn[hidden],
.topbar-actions [hidden] {
  display: none !important;
}
