/* ============================================================================
   Phase 2 — Layouts, Menus, Sliders, Data Lists, Dynamic Components.

   Split out of admin.css rather than appended to it: this sheet is loaded by both
   the admin shell (_Layout) and the public shell (_PublicLayout), because the
   renderer output — menus, sliders, dynamic lists — has to look identical in the
   admin preview and on the live site. It reuses admin.css's design tokens.
   ========================================================================== */

/* ══════════════════════════════════════════════════════════════════════════
   MENUS — list screen
   ══════════════════════════════════════════════════════════════════════════ */
.menu-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 16px; }
.menu-card { padding: 16px 18px 14px; display: flex; flex-direction: column; gap: 12px; }
.menu-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.menu-card-name { font-size: 15px; font-weight: 650; color: var(--ink); display: inline-flex; align-items: center; gap: 8px; }
.menu-card-name:hover { color: var(--brand); }
.menu-card-name i { color: var(--brand); }
.menu-card-slug { margin-top: 5px; }
.menu-card-slug code { font-size: 11.5px; color: var(--muted); background: var(--canvas); padding: 2px 6px; border-radius: 5px; }
.menu-badge { flex: none; font-size: 11px; font-weight: 600; padding: 3px 9px; border-radius: 20px; background: var(--canvas); color: var(--muted); display: inline-flex; align-items: center; gap: 5px; }
.menu-badge.on { background: var(--green-bg); color: var(--green); }
.menu-card-meta { display: flex; gap: 16px; font-size: 12.5px; color: var(--muted); }
.menu-card-meta i { color: var(--faint); margin-right: 4px; }
.menu-card-actions { display: flex; align-items: center; gap: 6px; border-top: 1px solid var(--line-2); padding-top: 12px; margin-top: auto; }

/* ══════════════════════════════════════════════════════════════════════════
   MENU BUILDER
   ══════════════════════════════════════════════════════════════════════════ */
.mb-wrap { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 16px; align-items: start; }
.mb-side { display: flex; flex-direction: column; gap: 16px; }
.mb-panel { padding: 0; overflow: hidden; }
/* The preview renders a real menu, and a header menu's submenu is absolutely positioned, so the
   overflow:hidden above (which keeps panel content inside the rounded corners) would slice the
   dropdown off at the card edge. This one panel has to let its content escape. */
.mb-panel.mb-panel-overflow { overflow: visible; }
/* Collapse/Expand all sit next to the Add item dropdown — without this, that dropdown's own
   wrapping <div class="dropdown"> block-breaks onto its own line below the two buttons. */
.mb-add { display: flex; align-items: center; gap: 8px; }
.mb-panel-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 16px; border-bottom: 1px solid var(--line-2); font-size: 14px;
}
.mb-hint-inline { font-size: 12px; color: var(--muted); font-weight: 400; margin-left: 10px; }
.mb-foot {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 16px; border-top: 1px solid var(--line-2);
  font-size: 12.5px; color: var(--muted);
}
.mb-depth-note { color: var(--faint); }

/* ── Tree ───────────────────────────────────────────────────────────────── */
.mb-tree-host { padding: 12px; min-height: 240px; }
.mb-tree, .mb-branch { list-style: none; margin: 0; padding: 0; }
.mb-branch { margin-left: 26px; border-left: 1px dashed var(--line); padding-left: 12px; margin-top: 4px; }
.mb-node { margin-bottom: 4px; }

.mb-row {
  display: flex; align-items: center; gap: 9px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 9px; padding: 8px 10px; cursor: pointer;
  transition: border-color .13s, box-shadow .13s, background .13s;
}
.mb-row:hover { border-color: var(--brand-100); background: var(--brand-50); }
.mb-node.sel > .mb-row { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-50); background: #fff; }
.mb-node.hidden > .mb-row { opacity: .55; }
.mb-row.dragging { opacity: .4; }

.mb-grip { color: var(--faint); cursor: grab; font-size: 15px; line-height: 1; flex: none; }
/* Keeps a leaf row's label lined up with a parent row's label above/below it — same width as
   the .js-toggle-collapse button (.mb-ib) that sits here on a row that actually has children.
   That button lives outside .mb-row-actions, so — unlike Move/Outdent/Delete — it's visible
   all the time, not just on hover/select: a collapsed branch should stay obviously collapsed
   (and re-expandable) even when nothing in the tree is being hovered. */
.mb-caret-spacer { width: 24px; flex: none; }
.mb-label { font-size: 13.5px; font-weight: 550; color: var(--ink); display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.mb-label .mb-ico { color: var(--brand); font-size: 13px; }
.mb-star { color: var(--amber); font-size: 10.5px; }
.mb-off { color: var(--faint); font-size: 11px; }

.mb-badge {
  flex: none; margin-left: auto; font-size: 11px; font-weight: 500;
  padding: 2px 8px; border-radius: 20px; display: inline-flex; align-items: center; gap: 5px;
  max-width: 190px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mb-badge.page { background: var(--blue-bg); color: var(--blue); }
.mb-badge.url  { background: var(--violet-bg); color: var(--violet); }
.mb-badge.none { background: var(--canvas); color: var(--muted); }

.mb-row-actions { display: flex; gap: 2px; flex: none; opacity: 0; transition: opacity .12s; }
.mb-row:hover .mb-row-actions, .mb-node.sel > .mb-row .mb-row-actions { opacity: 1; }
.mb-ib {
  width: 24px; height: 24px; border: none; background: none; border-radius: 6px;
  color: var(--muted); display: inline-flex; align-items: center; justify-content: center;
  font-size: 14px; cursor: pointer;
}
.mb-ib:hover { background: rgba(0,0,0,.06); color: var(--ink); }
.mb-ib:disabled { opacity: .3; cursor: default; }
.mb-ib.danger:hover { background: var(--red-bg); color: var(--red); }

/* Drop hints: a line for reordering, a filled outline for nesting. */
.mb-row.drop-before { box-shadow: 0 -3px 0 0 var(--brand); }
.mb-row.drop-after  { box-shadow: 0  3px 0 0 var(--brand); }
.mb-row.drop-into   { border-color: var(--brand); background: var(--brand-100); box-shadow: inset 0 0 0 1px var(--brand); }

.mb-empty { text-align: center; padding: 34px 20px; color: var(--muted); }
.mb-empty i { font-size: 30px; color: var(--faint); display: block; margin-bottom: 10px; }
.mb-empty p { font-size: 13.5px; margin: 0; }

/* ── Properties panel ───────────────────────────────────────────────────── */
.mb-props { padding: 14px 16px 18px; }
.mb-props-empty { text-align: center; padding: 26px 10px; color: var(--muted); }
.mb-props-empty i { font-size: 26px; color: var(--faint); display: block; margin-bottom: 8px; }
.mb-props-empty p { font-size: 13px; margin: 0; }
.mb-opt { font-weight: 400; color: var(--faint); font-size: 11px; }
.mb-checks { margin-top: 14px; display: flex; flex-direction: column; gap: 9px; }
.mb-checks label { font-size: 13px; color: var(--ink-2); display: flex; align-items: center; gap: 8px; cursor: pointer; }

/* Inline menu rename. Reads as a heading until focused, so the panel header does not
   look like a form; the tick only appears once the name has actually changed. */
.mb-rename { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.mb-rename-input {
  font-size: 15px; font-weight: 700; color: var(--ink);
  border: 1px solid transparent; border-radius: 7px; background: transparent;
  padding: 3px 8px; margin-left: -8px; min-width: 180px; max-width: 340px;
  transition: border-color .12s, background .12s;
}
.mb-rename-input:hover { border-color: var(--line); }
.mb-rename-input:focus { outline: none; border-color: var(--brand); background: #fff; box-shadow: 0 0 0 3px var(--brand-50); }
.mb-rename-save {
  width: 28px; height: 28px; flex: none; border: none; border-radius: 7px;
  background: var(--brand); color: #fff; cursor: pointer;
  display: none; align-items: center; justify-content: center; font-size: 14px;
}
.mb-rename.is-dirty .mb-rename-save { display: inline-flex; }
.mb-rename-save:hover { filter: brightness(1.06); }
.mb-rename.is-invalid .mb-rename-input { border-color: var(--red); background: var(--red-bg); }
.mb-rename-msg { font-size: 11.5px; font-weight: 600; color: var(--red); flex-basis: 100%; }

/* Mega-panel settings in the builder's props panel (top-level items only). */
.mb-mega { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line-2); }
.mb-mega-toggle { font-size: 13px; font-weight: 600; color: var(--ink-2); display: flex; align-items: center; gap: 8px; cursor: pointer; }
.mb-hint { font-size: 11.5px; color: var(--faint); margin-top: 5px; line-height: 1.45; }
.mb-mega-badge {
  display: inline-flex; align-items: center; gap: 4px; margin-left: 7px;
  padding: 1px 7px; border-radius: 999px; background: var(--brand-50); color: var(--brand);
  font-size: 10px; font-weight: 700; letter-spacing: .02em;
}
.mb-mega-badge i { font-size: 9.5px; }

/* ── Preview + placement ────────────────────────────────────────────────── */
/* min-height keeps a one-item menu from collapsing to a sliver, and gives an opened dropdown
   somewhere to sit before it starts overlapping the panel below. */
.mb-preview { padding: 14px 16px; min-height: 68px; }
/* Lift an opened submenu above the sibling panels that follow it in the column. */
.mb-preview .cms-menu-sub { z-index: 40; }
.mb-place { padding: 14px 16px 18px; font-size: 13px; color: var(--ink-2); }
.mb-place p { margin: 0 0 8px; }
.mb-code { display: block; font-size: 11.5px; background: var(--ink); color: #e5e7eb; padding: 9px 11px; border-radius: 8px; overflow-x: auto; }
.mb-usedin { list-style: none; margin: 0; padding: 0; font-size: 12.5px; }
.mb-usedin li { padding: 3px 0; color: var(--ink-2); }
.mb-usedin i { color: var(--brand); margin-right: 6px; }

@media (max-width: 1180px) {
  .mb-wrap { grid-template-columns: minmax(0, 1fr); }
}

/* ══════════════════════════════════════════════════════════════════════════
   RENDERED MENUS — MenuRenderer output (public site + admin preview)
   ══════════════════════════════════════════════════════════════════════════ */
.cms-menu, .cms-menu-sub { list-style: none; margin: 0; padding: 0; }
.cms-menu { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }
.cms-menu-item { position: relative; }
.cms-menu-link, .cms-menu-label {
  display: inline-block; font-size: 14.5px; font-weight: 500; color: #4b5563;
  padding: 6px 2px; border-bottom: 2px solid transparent; transition: color .14s, border-color .14s;
}
.cms-menu-link:hover { color: var(--site, var(--brand)); }
.cms-menu-link.active { color: var(--site, var(--brand)); border-bottom-color: var(--site, var(--brand)); }
.cms-menu-label { color: #4b5563; cursor: default; }
.cms-menu .cms-menu-item  .cms-menu-sub .cms-menu-label { color: #4b5563; cursor: pointer; }
/* A highlighted item renders as a button — the header's "Get in touch" affordance. */
.cms-menu-item.is-highlighted > .cms-menu-link {
  background: var(--site, var(--brand)); color: #fff !important;
  border-radius: var(--site-radius-btn, 9px); padding: 9px 18px;
  font-weight: 600; border-bottom: none;
}
.cms-menu-item.is-highlighted > .cms-menu-link:hover { filter: brightness(.94); color: #fff !important; }

/* Second level: hover-revealed dropdown on wide screens. */
.cms-menu > .cms-menu-item > .cms-menu-sub {
  position: absolute; top: 100%; left: 0; min-width: 280px; z-index: 30;
  background: #fff; border: 1px solid rgba(17,24,39,.1); border-radius: 10px;
  box-shadow: 0 14px 30px rgba(17,24,39,.12); padding: 6px;
  opacity: 0; visibility: hidden; transform: translateY(4px);
  transition: opacity .14s, transform .14s, visibility .14s;
}
.cms-menu > .cms-menu-item:hover > .cms-menu-sub,
.cms-menu > .cms-menu-item:focus-within > .cms-menu-sub,
/* .mega-pinned (site-nav.js): now also applied to has-children items, not just has-mega —
   see the margin-top comment below for why a regular dropdown needs the same close-delay. */
.cms-menu > .cms-menu-item.mega-pinned > .cms-menu-sub {
  opacity: 1; visibility: visible; transform: translateY(0);
}
/* .open-left (site-nav.js, positionSubmenus): a trigger near the right edge of the viewport
   would anchor this card past it with the base left:0 above — real overflow, not just a
   visual clip, since the card stays laid out (opacity:0, not display:none) even while
   closed and so counts toward scrollWidth the moment it exists, open or not (see the
   overflow-x:hidden note in site-shell.css). Flipping to the trigger's right edge instead
   keeps the card fully on-screen. One extra class beats the 3-class rule above regardless
   of source order, so this doesn't depend on appearing later in the file. */
.cms-menu > .cms-menu-item > .cms-menu-sub.open-left { left: auto; right: 0; }
/* .psite-header-navrow's row is taller than its own links — .psite-nav carries its own
   padding:10px (site-shell.css) on top of the link's own padding, and a top-level <li> only
   ever sits as tall as its own link content (align-items:center lets flex items keep their
   natural height). That left top:100% landing inside the row's own remaining background,
   ~10px before the row's true bottom edge — the dropdown's rounded top corners visibly cut
   into the dark bar instead of starting cleanly below it.
   Tried stretching the <li> to close that gap at the source instead of compensating for it —
   same principle as the mega panel's width fix — but align-self:stretch didn't propagate
   through .psite-nav → .cms-menu → <li> in testing, and forcing it via height:100% +
   margin-bottom on .cms-menu fed back into .psite-nav's own (content-driven, not fixed)
   height and shrank the whole row. A plain, known-fixed margin-top — matching .psite-nav's
   own declared padding, not a guess — is simpler and doesn't touch any ancestor's sizing.
   It does reopen a small hover gap, which is why has-children items were added to the same
   mega-pinned close-delay below, not just has-mega ones. */
.psite-header-navrow .cms-menu > .cms-menu-item > .cms-menu-sub { margin-top: 10px; }
.cms-menu-sub .cms-menu-item { display: block; }
/* flex + space-between rather than block: a plain leaf row is unaffected (nothing to
   space out), but a row with the has-children caret below pushes that caret flush to the
   row's own right edge instead of trailing right after the label text — "right aligned",
   not just "after the text" — which is what actually reads as "this opens a further level"
   at a glance, the same way the row's own width already does. */
.cms-menu-sub .cms-menu-link, .cms-menu-sub .cms-menu-label {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 12px; border-radius: 7px; border-bottom: none; font-size: 13.5px;
}
.cms-menu-sub .cms-menu-link:hover { background: var(--canvas, #f4f5f7); }

/* Caret on items that have children. */
.cms-menu-item.has-children > .cms-menu-link::after,
.cms-menu-item.has-children > .cms-menu-label::after {
  content: ''; display: inline-block; margin-left: 6px; vertical-align: middle;
  border: 4px solid transparent; border-top-color: currentColor; opacity: .55;
  transform: translateY(2px); flex-shrink: 0;
}
/* Inside a dropdown the caret is flex-positioned by the row above, not inline text flow —
   the inline margin/translateY tuned for sitting next to top-level label text would throw
   it off-centre against the row's own flex baseline. */
.cms-menu-sub .cms-menu-item.has-children > .cms-menu-link::after,
.cms-menu-sub .cms-menu-item.has-children > .cms-menu-label::after {
  margin-left: 0; transform: none;
}

/* Third level flies out to the side. */
.cms-menu-sub .cms-menu-sub {
  position: absolute; top: -6px; left: 100%; min-width: 280px; z-index: 31;
  background: #fff; border: 1px solid rgba(17,24,39,.1); border-radius: 10px;
  box-shadow: 0 14px 30px rgba(17,24,39,.12); padding: 6px;
  opacity: 0; visibility: hidden; transition: opacity .14s, visibility .14s;
}
.cms-menu-sub .cms-menu-item:hover > .cms-menu-sub { opacity: 1; visibility: visible; }
.cms-menu-sub .cms-menu-item.has-children > .cms-menu-link::after,
.cms-menu-sub .cms-menu-item.has-children > .cms-menu-label::after {
  transform: rotate(-90deg);
}
/* .open-left (site-nav.js, positionSubmenus) — same reasoning as the 2nd-level dropdown
   above: flies to the trigger's left edge instead of its right when the right-flyout
   would otherwise run off the viewport. The caret flips with it so it still points the
   way the panel actually opens, via :has() rather than a sibling selector — the submenu
   that carries .open-left is a sibling of the link the caret lives on, not a descendant
   of it, so nothing shorter reaches it. */
.cms-menu-sub .cms-menu-sub.open-left { left: auto; right: 100%; }
.cms-menu-sub .cms-menu-item.has-children:has(> .cms-menu-sub.open-left) > .cms-menu-link::after,
.cms-menu-sub .cms-menu-item.has-children:has(> .cms-menu-sub.open-left) > .cms-menu-label::after {
  transform: rotate(90deg);
}

/* ── Mega panel ──────────────────────────────────────────────────────────────
   A presentation of the same tree: depth 2 becomes a column heading, depth 3 the
   links under it. The panel spans the menu rather than hanging off one item, so it
   is positioned against .cms-menu — which is why that element needs `position:
   relative` here and the panel uses left/right:0 instead of a width.

   Hover AND focus-within: the dropdowns above are hover-only, so a keyboard user
   tabbing into a mega panel would open nothing. :focus-within costs one selector
   and makes the panel reachable without a mouse. */
.cms-menu { position: relative; }
.cms-menu-item.has-mega { position: static; }
/* …but inside a shell region, anchor the panel to the REGION, not the menu.
   left:0/right:0 resolve against the nearest positioned ancestor, which was .cms-menu —
   an element only as wide as the links themselves. A right-aligned 6-column menu is
   ~300px, so the panel was ~300px and each column collapsed to about 20px, which is the
   "mega menu items overlap at small widths" everyone sees. .psite-header-in and
   .psite-navbar-in are position:relative (site-shell.css); making .cms-menu static inside
   them hands the panel the full content width instead. */
.psite-header-in .cms-menu,
.psite-navbar-in .cms-menu { position: static; }
/* A header built from Craft's Columns block (CLAUDE.md's "menu on its own row" pattern —
   shell-topbar/shell-brand/cms-menu dropped into a plain Bootstrap column) has neither
   wrapper above: the menu's nearest positioned ancestor is whatever column it sits in, so
   a short top-level list ("Home / About / Contact") still anchors the panel to just those
   few words. .cms-sec-inner is already position:relative and already carries the
   author's chosen section width (cms-sec-w-narrow/boxed/wide) — the same "layout/max fixed
   size" the packaged header anchors to above — and .cms-sec only clips the X axis
   (overflow-x: clip), so a panel this wide dropping below the section is not cut off. */
.cms-sec-inner .cms-menu { position: static; }
/* The "Centered" header variant (ShellBlocks.HeaderCenteredTemplate) puts the nav on its
   own row BELOW .psite-header-in, as a sibling — not a descendant — so neither rule above
   ever matches it, and .cms-menu stays the (narrow) anchor.
   First attempt anchored to .psite-header-navrow .psite-nav instead — it already carries
   max-width:var(--psite-shell-w) — which fixed the width but broke hover: that element has
   real padding (padding:10px, min-height:46px) around the links, so top:100% landed below
   the padding box's own bottom edge rather than the links' bottom edge, leaving a dead strip
   the pointer crossed (and lost :hover in) on the way down to the panel. .cms-menu itself
   has no padding — it is exactly as tall as the links — so widening .cms-menu to fill .psite-nav
   and anchoring to IT instead puts top:100% flush against the links with no gap, while still
   getting the full (capped) width via the parent's own max-width. justify-content:center is
   redeclared because centering now happens inside .cms-menu's own 100%-width box rather than
   via .psite-nav centering .cms-menu as a content-sized flex item. */
.psite-header-navrow .cms-menu { position: relative; width: 100%; justify-content: center; }
.cms-mega {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 32;
  display: flex; gap: 28px; align-items: flex-start;
  background: #fff; border: 1px solid rgba(17,24,39,.1); border-radius: 12px;
  box-shadow: 0 18px 44px rgba(17,24,39,.14); padding: 22px 24px; margin-top: 6px;
  opacity: 0; visibility: hidden; transform: translateY(4px);
  transition: opacity .14s, transform .14s, visibility .14s;
}
.cms-menu-item.has-mega:hover > .cms-mega,
.cms-menu-item.has-mega:focus-within > .cms-mega,
/* .mega-pinned (site-nav.js): a short close-delay so crossing .cms-mega's margin-top gap at
   an angle doesn't drop :hover before the pointer reaches the panel — see the JS comment. */
.cms-menu-item.has-mega.mega-pinned > .cms-mega {
  opacity: 1; visibility: visible; transform: translateY(0);
}
/* The authored column count is a target, not a promise, and so is which heading ends up in
   which column. A grid with one heading per track left a 2-link column and a 9-link column
   side by side — same row, wildly different heights, so the short column was mostly blank
   space under its own links. CSS multi-column instead pours the heading+list groups into
   --cms-mega-cols columns and balances them by height (column-fill's default for an
   auto-height box), so a couple of short headings share a column with each other while a
   long one gets a column of its own — same tree, same groups, just distributed instead of
   mapped 1:1. column-width is the same "floor before it gets unreadable" the grid used:
   both are hints, and the UA won't go narrower than column-width even if that means fewer
   than --cms-mega-cols columns. */
.cms-mega-cols {
  flex: 1; column-gap: 28px;
  column-count: var(--cms-mega-cols, 3);
  column-width: max(150px, calc((100% - (var(--cms-mega-cols, 3) - 1) * 28px) / var(--cms-mega-cols, 3)));
}
.cms-mega-col { min-width: 0; break-inside: avoid-column; margin-bottom: 16px; }
.cms-mega-col:last-child { margin-bottom: 0; }
.cms-mega-heading {
  display: block; padding: 0 0 4px; margin-bottom: 6px;
  border-bottom: 1px solid rgba(17,24,39,.08);
  font-size: 14px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--brand-primary-800, #333) ;
}
.cms-mega-list { list-style: none; margin: 0; padding: 0; }
.cms-mega-list .cms-menu-item { display: block; }
.cms-mega-list .cms-menu-link, .cms-mega-list .cms-menu-label {
  display: block; padding: 6px 8px; border-radius: 7px; border-bottom: none; font-size: 13.5px;
}
.cms-mega-list .cms-menu-link:hover { background: var(--canvas, #f4f5f7); }
.cms-mega-featured { flex: 0 0 clamp(200px, 26%, 320px); min-width: 0; }
/* The caret belongs on the trigger, not on the headings inside the panel. */
.cms-mega-heading::after { content: none !important; }

/* Rounded-corners opt-out (Menu.RoundedSubmenus, the Menu Builder checkbox) — square covers
   the regular dropdown, its 3rd-level flyout, and the mega panel, since MenuRenderer puts
   .cms-menu-square on the one root <ul> (as a second class, alongside .cms-menu itself — not
   an ancestor of it) and every one of these is a descendant of that element.
   Worked for the mega panel (.cms-menu-square .cms-mega, 2 classes, beats .cms-mega's own
   1-class base rule) but not the regular dropdown: its base rule is
   .cms-menu > .cms-menu-item > .cms-menu-sub (3 classes), which outranked the 2-class
   override regardless of source order, so it stayed rounded no matter the checkbox. Each
   selector below now matches (or beats) its own base rule's specificity directly instead of
   assuming "ancestor + descendant" is automatically enough. */
.cms-menu-square.cms-menu > .cms-menu-item > .cms-menu-sub,
.cms-menu-square .cms-menu-sub .cms-menu-sub,
.cms-menu-square .cms-mega {
  border-radius: 0;
}

/* Narrow screens: a wide floating panel has nowhere to go, so it becomes part of
   the flow — the same shape the vertical variant already uses. */
@media (max-width: 860px) {
  .cms-mega {
    position: static; opacity: 1; visibility: visible; transform: none;
    display: block; border: none; border-radius: 0; box-shadow: none;
    padding: 4px 0 4px 14px; margin-top: 0;
  }
  .cms-mega-cols { column-count: 1; }
  .cms-mega-col { margin-bottom: 12px; }
  .cms-mega-featured { margin-top: 14px; }
}

/* Vertical variant (sidebars, footer columns) — always expanded, no dropdowns.
   These selectors deliberately mirror the dropdown rules above rather than being shorter: the
   second-level rule is `.cms-menu > .cms-menu-item > .cms-menu-sub` (three classes), so a plain
   `.cms-menu-vertical .cms-menu-sub` (two) loses the background/border/shadow declarations and the
   submenu renders as a white dropdown card — very visible as white "Explore"/"Quick links" panels
   on the dark footer. Matching depth is what fixes it; !important is not needed. */
.cms-menu-vertical .cms-menu { flex-direction: column; align-items: stretch; gap: 2px; }
.cms-menu-vertical .cms-menu > .cms-menu-item > .cms-menu-sub,
.cms-menu-vertical .cms-menu-sub .cms-menu-sub,
.cms-menu-vertical .cms-menu-sub,
/* A mega panel in a sidebar or footer flattens like any other submenu — there is no
   horizontal room to float one, and the tree already reads correctly expanded. */
.cms-menu-vertical .cms-mega {
  position: static; opacity: 1; visibility: visible; transform: none;
  background: none; border: none; border-radius: 0; box-shadow: none;
  padding: 0 0 0 14px; min-width: 0; z-index: auto;
}
.cms-menu-vertical .cms-mega { display: block; margin-top: 0; }
.cms-menu-vertical .cms-mega-cols { column-count: 1; }
.cms-menu-vertical .cms-mega-col { margin-bottom: 10px; }
.cms-menu-vertical .cms-menu-link, .cms-menu-vertical .cms-menu-label {
  display: block; padding: 7px 0; border-bottom: none;
}
/* The dropdown hover fill is a light grey pill — wrong on a dark footer, and pointless in an
   always-expanded list. */
.cms-menu-vertical .cms-menu-sub .cms-menu-link:hover { background: none; }
.cms-menu-vertical .cms-menu-item.has-children > .cms-menu-link::after,
.cms-menu-vertical .cms-menu-item.has-children > .cms-menu-label::after { display: none; }

@media (max-width: 720px) {
  .cms-menu { flex-direction: column; align-items: stretch; gap: 0; }
  /* Same trap as the vertical variant: without resetting background/border-radius these keep the
     dropdown's white card styling, which is wrong wherever the menu sits on a dark surface. */
  .cms-menu > .cms-menu-item > .cms-menu-sub,
  .cms-menu-sub .cms-menu-sub {
    position: static; opacity: 1; visibility: visible; transform: none;
    background: none; border: none; border-radius: 0; box-shadow: none;
    padding: 0 0 0 14px; min-width: 0;
  }
  /* The header's mobile drawer is white, so links there need their own separator; the footer
     supplies its own colours via .psite-footer rules. */
  .cms-menu-link, .cms-menu-label { padding: 11px 2px; }
  .psite-header .cms-menu-link, .psite-header .cms-menu-label { border-bottom: 1px solid #f1f2f4; }
}

/* ── Mobile drawer: submenus collapse until tapped ────────────────────────────
   The rules above flatten every dropdown for touch, which is right — a hover
   dropdown is unreachable on a phone. But flattening them all at once expands the
   ENTIRE tree the moment the burger opens: on the seeded menu that is 13 of 14
   links plus a whole mega panel, so the drawer becomes a wall of text and the
   top-level items it is meant to show scroll off.

   Collapsed by default, one open at a time via .is-open (site-nav.js). Scoped to
   .nav-open drawers so nothing here touches desktop dropdowns or the deliberately
   always-expanded .cms-menu-vertical used by the footer and sidebar.

   display, not visibility: the flattening rules above already set
   visibility:visible, and a collapsed item must take up no space at all. */
@media (max-width: 860px) {
  .psite-navbar.nav-open .cms-menu-sub,
  .psite-navbar.nav-open .cms-mega { display: none; }
  .psite-navbar.nav-open .cms-menu-item.is-open > .cms-menu-sub { display: block; }
  .psite-navbar.nav-open .cms-menu-item.is-open > .cms-mega { display: block; }
}
@media (max-width: 720px) {
  .psite-header.nav-open .cms-menu-sub,
  .psite-header.nav-open .cms-mega { display: none; }
  .psite-header.nav-open .cms-menu-item.is-open > .cms-menu-sub { display: block; }
  .psite-header.nav-open .cms-menu-item.is-open > .cms-mega { display: block; }
}
/* The caret already exists on has-children triggers; flip it so the row shows its
   own state. has-mega triggers get one too — they are expandable here as well.
   Scoped with .nav-open on every selector (not just a max-width), so a nested trigger
   gets the SAME down/up convention as a top-level one regardless of which component's own
   breakpoint (720px header vs 860px navbar) actually opened the drawer. */
@media (max-width: 860px) {
  .psite-navbar.nav-open .cms-menu-item.has-mega > .cms-menu-link::after,
  .psite-header.nav-open .cms-menu-item.has-mega > .cms-menu-link::after,
  .psite-navbar.nav-open .cms-menu-item.has-mega > .cms-menu-label::after,
  .psite-header.nav-open .cms-menu-item.has-mega > .cms-menu-label::after,
  /* Every has-children trigger, at any depth — not just has-mega ones — needs the same
     reset: without it, a nested trigger (e.g. "Admission" inside "Students") keeps the
     desktop flyout caret's rotate(-90deg)/margin-left:0 (phase2.css, the "second level:
     hover-revealed dropdown" section), pointing sideways while every top-level trigger in
     the same drawer points down. There is no sideways flyout on a phone; everything here
     expands inline, so every trigger should look and behave the same way. */
  .psite-navbar.nav-open .cms-menu-item.has-children > .cms-menu-link::after,
  .psite-header.nav-open .cms-menu-item.has-children > .cms-menu-link::after,
  .psite-navbar.nav-open .cms-menu-item.has-children > .cms-menu-label::after,
  .psite-header.nav-open .cms-menu-item.has-children > .cms-menu-label::after {
    content: ''; display: inline-block; margin-left: 6px;
    border: 4px solid transparent; border-top-color: currentColor; opacity: .55;
    transform: translateY(2px);
  }
  .psite-navbar.nav-open .cms-menu-item.is-open > .cms-menu-link::after,
  .psite-header.nav-open .cms-menu-item.is-open > .cms-menu-link::after,
  .psite-navbar.nav-open .cms-menu-item.is-open > .cms-menu-label::after,
  .psite-header.nav-open .cms-menu-item.is-open > .cms-menu-label::after {
    transform: translateY(-2px) rotate(180deg);
  }
  /* Tapping a parent expands it instead of navigating, so the row must read as a
     control rather than as a dead link. Same "any depth" reasoning as the caret above —
     dropped the has-mega duplicate, has-children already covers it (a mega item always
     carries has-children too; see MenuRenderer). */
  .psite-navbar.nav-open .cms-menu-item.has-children > .cms-menu-link,
  .psite-header.nav-open .cms-menu-item.has-children > .cms-menu-link {
    display: flex; align-items: center; justify-content: space-between;
  }
  /* Resets the desktop dropdown's own box styling (padding:8px 12px, border-radius:7px,
     font-size:13.5px — the "second level: hover-revealed dropdown" section) back to the
     drawer's flat, borderless, top-level-matching look, so a nested row and a top-level
     row are visually identical here instead of one looking like a floating white card. */
  .psite-navbar.nav-open .cms-menu-sub .cms-menu-link,
  .psite-header.nav-open .cms-menu-sub .cms-menu-link,
  .psite-navbar.nav-open .cms-menu-sub .cms-menu-label,
  .psite-header.nav-open .cms-menu-sub .cms-menu-label {
    padding: 11px 2px; border-radius: 0; font-size: 14.5px;
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   MANAGED SHELL — styling for the seeded header/footer/sidebar layouts.

   These reuse the .psite-* class names the built-in shell used so the existing
   inline stylesheet in _PublicLayout still applies. The rules here only cover
   what changed: navigation is now MenuRenderer output rather than hand-written
   anchors, and that output defaults to dark-on-light — wrong inside the dark
   footer. Compound selectors (.psite-footer-in.psite-footer-managed) so these
   win over _PublicLayout's inline <style>, which loads later in the document.
   ══════════════════════════════════════════════════════════════════════════ */

/* Footer: brand | menu columns | contact */
.psite-footer-in.psite-footer-managed { grid-template-columns: 1.4fr 1.6fr 1fr; }
.psite-foot-menu .cms-menu {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px; align-items: start;
}
/* Group headings match the footer's existing column titles. */
.psite-foot-menu .cms-menu > .cms-menu-item > .cms-menu-label {
  font-size: 16px; letter-spacing: .06em; font-weight: 700;
   margin: 0 0 12px; padding: 0; color: var(--brand-primary-100) !important;
}
.psite-footer .pfoot-title
{
  color: var(--brand-primary-100);
  font-weight: 600;
}
.psite-footer .cms-menu-link { color: var(--brand-primary-100); font-size:14px; padding: 6px 0; border-bottom: none; }
.psite-footer .cms-menu-link:hover { color: #fff; }
.psite-footer .cms-menu-link.active { color: #fff; border-bottom: none; }
.psite-footer .cms-menu-item.is-highlighted > .cms-menu-link {
  background: none; color: #cbd2dd !important; padding: 4px 0; font-weight: 500;
}
.psite-footer .cms-menu-item.is-highlighted > .cms-menu-link:hover { color: #fff !important; }

@media (max-width: 720px) {
  .psite-footer-in.psite-footer-managed { grid-template-columns: 1fr; }
  .psite-foot-menu .cms-menu { grid-template-columns: 1fr; gap: 18px; }
}

/* Sidebar */
.psite-side-inner { display: flex; flex-direction: column; gap: 20px; }
.psite-side-block h4 {
  font-size: 12px; text-transform: uppercase; letter-spacing: .06em;
  color: #6b7280; margin: 0 0 8px; font-weight: 600;
}
.psite-side-block .cms-menu-link, .psite-side-block .cms-menu-label {
  font-size: 14px; padding: 7px 0; border-bottom: none;
}
.psite-side-card {
  background: var(--canvas, #f4f5f7); border: 1px solid rgba(17,24,39,.07);
  border-radius: 12px; padding: 18px;
}
.psite-side-card-ico {
  width: 38px; height: 38px; border-radius: 10px; margin-bottom: 10px;
  background: var(--site, #4338ca); color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: 18px;
}
.psite-side-card h5 { font-size: 15px; font-weight: 650; margin: 0 0 6px; color: #111827; }
.psite-side-card p { font-size: 13px; color: #6b7280; margin: 0 0 12px; line-height: 1.55; }
.psite-side-btn {
  display: inline-block; background: var(--site, #4338ca); color: #fff !important;
  font-size: 13.5px; font-weight: 600; padding: 8px 15px;
  border-radius: var(--site-radius-btn, 9px); text-decoration: none;
}
.psite-side-btn:hover { filter: brightness(.94); }

/* ══════════════════════════════════════════════════════════════════════════
   LAYOUTS — list screen
   ══════════════════════════════════════════════════════════════════════════ */
.lay-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(380px, 1fr)); gap: 16px; }
.lay-card { padding: 0; overflow: hidden; display: flex; flex-direction: column; }
.lay-card.is-default { box-shadow: 0 0 0 2px var(--brand-100), var(--shadow-sm); }
.lay-head { padding: 14px 16px 10px; }
.lay-title a { font-size: 15px; font-weight: 650; color: var(--ink); }
.lay-title a:hover { color: var(--brand); }
.lay-flags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.lay-flag {
  font-size: 10.5px; font-weight: 600; padding: 3px 8px; border-radius: 20px;
  display: inline-flex; align-items: center; gap: 4px; background: var(--canvas); color: var(--muted);
}
.lay-flag.def { background: var(--brand-50); color: var(--brand); }
.lay-flag.live { background: var(--green-bg); color: var(--green); }
.lay-flag.draft { background: var(--canvas); color: var(--muted); }
.lay-flag.pending { background: var(--amber-bg); color: var(--amber); }
.lay-flag.html { background: var(--violet-bg); color: var(--violet); }

.lay-preview { height: 132px; background: #fff; border-top: 1px solid var(--line-2); border-bottom: 1px solid var(--line-2); overflow: hidden; position: relative; }
.lay-preview iframe { width: 200%; height: 264px; border: 0; transform: scale(.5); transform-origin: top left; pointer-events: none; }
.lay-preview-empty {
  height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 7px; color: var(--faint); font-size: 12.5px; background: var(--canvas);
}
.lay-preview-empty i { font-size: 22px; }

.lay-meta { display: flex; flex-wrap: wrap; gap: 6px 15px; padding: 11px 16px; font-size: 12px; color: var(--muted); }
.lay-meta i { color: var(--faint); margin-right: 4px; }
.lay-actions { display: flex; align-items: center; gap: 6px; padding: 0 16px 14px; margin-top: auto; }

/* ══════════════════════════════════════════════════════════════════════════
   SHARED MEDIA PICKER (media-picker.js)

   Loaded by both the admin shell and the Craft builder iframe, so it must not
   depend on Bootstrap's modal — everything here is self-contained.
   ══════════════════════════════════════════════════════════════════════════ */
/* z-index 1400 puts the picker above TinyMCE's own popup container (.tox-tinymce-aux, 1300) in
   both surfaces. It is opened FROM the editor's image button, so it has to clear TinyMCE's menus
   and dialogs — and it already clears the drawer (1060), Bootstrap modals (1055) and toasts
   (1080) in the admin shell. See the layer table above .rte-overlay below. */
.cmp-overlay {
  position: fixed; inset: 0; z-index: 1400;
  background: rgba(17, 24, 39, .55);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.cmp-box {
  background: #fff; border-radius: 14px; width: min(900px, 100%); max-height: 86vh;
  display: flex; flex-direction: column; overflow: hidden;
  box-shadow: 0 24px 60px rgba(17, 24, 39, .28);
}
.cmp-head {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 14px 18px; border-bottom: 1px solid var(--line, #e5e7eb);
}
.cmp-title { font-weight: 700; font-size: 15px; color: var(--ink, #111827); display: inline-flex; align-items: center; gap: 8px; }
.cmp-title i { color: var(--brand, #2563eb); }
.cmp-head-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.cmp-search {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--canvas, #f4f5f7); border: 1px solid var(--line, #e5e7eb);
  border-radius: 9px; padding: 6px 10px;
}
.cmp-search i { color: var(--faint, #9ca3af); font-size: 13px; }
.cmp-search input { border: none; background: none; outline: none; font-size: 13px; width: 190px; }
.cmp-upload {
  display: inline-flex; align-items: center; gap: 6px; border: none;
  background: var(--brand, #2563eb); color: #fff; border-radius: 9px;
  padding: 7px 13px; font-size: 13px; font-weight: 600; cursor: pointer;
}
.cmp-upload:hover { filter: brightness(1.06); }
.cmp-close {
  border: none; background: none; color: var(--muted, #6b7280);
  font-size: 15px; padding: 6px 8px; border-radius: 7px; cursor: pointer;
}
.cmp-close:hover { background: var(--canvas, #f4f5f7); color: var(--ink, #111827); }

.cmp-crumbs {
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
  padding: 10px 18px; border-bottom: 1px solid var(--line-2, #eef0f3);
}
.cmp-crumb {
  border: none; background: none; padding: 3px 6px; border-radius: 6px; cursor: pointer;
  font-size: 12.5px; font-weight: 600; color: var(--brand, #2563eb);
}
.cmp-crumb:hover { background: var(--brand-50, #eff4ff); }
.cmp-crumb:last-child { color: var(--ink-2, #374151); }
.cmp-crumb-sep { color: var(--faint, #9ca3af); font-size: 10px; }

.cmp-body { padding: 16px 18px 20px; overflow-y: auto; }
.cmp-section {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--faint, #9ca3af); margin: 4px 0 10px;
}
.cmp-note { font-size: 12.5px; color: var(--muted, #6b7280); margin-bottom: 12px; }

.cmp-folders { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 10px; margin-bottom: 18px; }
.cmp-folder {
  display: flex; align-items: center; gap: 10px; text-align: left; cursor: pointer;
  background: #fff; border: 1px solid var(--line, #e5e7eb); border-radius: 10px; padding: 11px 13px;
}
.cmp-folder:hover { border-color: var(--brand, #2563eb); background: var(--brand-50, #eff4ff); }
.cmp-folder > i { color: #f5b942; font-size: 17px; flex: none; }
.cmp-folder-name { font-size: 13.5px; font-weight: 550; color: var(--ink, #111827); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cmp-folder-n { margin-left: auto; font-size: 11.5px; color: var(--muted, #6b7280); flex: none; }

.cmp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px; }
.cmp-item {
  border: 1px solid var(--line, #e5e7eb); border-radius: 10px; overflow: hidden;
  background: #fff; padding: 0; cursor: pointer; text-align: left;
}
.cmp-item:hover { border-color: var(--brand, #2563eb); box-shadow: 0 4px 12px rgba(37, 99, 235, .18); }
.cmp-thumb { display: block; aspect-ratio: 4 / 3; background: var(--canvas, #f4f5f7); }
.cmp-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Icon card for kinds with no renderable thumbnail (documents, video, archives). */
.cmp-thumb-icon {
  width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
  font-size: 34px; color: var(--muted, #6b7280);
}
.cmp-name {
  display: block; padding: 7px 9px; font-size: 11.5px; color: var(--ink-2, #374151);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cmp-empty { text-align: center; color: var(--muted, #6b7280); padding: 44px 20px; font-size: 13.5px; }
.cmp-empty i { display: block; font-size: 28px; color: var(--faint, #9ca3af); margin-bottom: 10px; }
.cmp-empty p { margin: 0; }

@media (max-width: 620px) {
  .cmp-head-actions { width: 100%; }
  .cmp-search input { width: 100%; }
  .cmp-search { flex: 1; }
}

/* ══════════════════════════════════════════════════════════════════════════
   ICON SELECTOR (icon-picker.js)
   ══════════════════════════════════════════════════════════════════════════ */
.cip-field { display: flex; align-items: stretch; gap: 8px; }
.cip-field .set-input { flex: 1; min-width: 0; }
.cip-preview {
  flex: none; width: 40px; display: flex; align-items: center; justify-content: center;
  background: var(--canvas, #f4f5f7); border: 1px solid var(--line, #e5e7eb);
  border-radius: 9px; color: var(--brand, #2563eb); font-size: 17px;
}
.cip-field.is-empty .cip-preview { color: var(--faint, #9ca3af); }
.cip-browse {
  flex: none; display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--line, #e5e7eb); background: #fff; color: var(--ink-2, #374151);
  border-radius: 9px; padding: 0 12px; font-size: 12.5px; font-weight: 600; cursor: pointer;
}
.cip-browse:hover { border-color: var(--brand, #2563eb); color: var(--brand, #2563eb); }

.cip-overlay {
  position: fixed; inset: 0; z-index: 1095;
  background: rgba(17, 24, 39, .55);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.cip-box {
  background: #fff; border-radius: 14px; width: min(760px, 100%); max-height: 84vh;
  display: flex; flex-direction: column; overflow: hidden;
  box-shadow: 0 24px 60px rgba(17, 24, 39, .28);
}
.cip-head {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 18px; border-bottom: 1px solid var(--line, #e5e7eb);
}
.cip-title { font-weight: 700; font-size: 15px; color: var(--ink, #111827); display: inline-flex; align-items: center; gap: 8px; }
.cip-title i { color: var(--brand, #2563eb); }
.cip-search {
  margin-left: auto; display: inline-flex; align-items: center; gap: 7px;
  background: var(--canvas, #f4f5f7); border: 1px solid var(--line, #e5e7eb);
  border-radius: 9px; padding: 6px 10px;
}
.cip-search i { color: var(--faint, #9ca3af); font-size: 13px; }
.cip-search input { border: none; background: none; outline: none; font-size: 13px; width: 180px; }
.cip-close { border: none; background: none; color: var(--muted, #6b7280); font-size: 15px; padding: 6px 8px; border-radius: 7px; cursor: pointer; }
.cip-close:hover { background: var(--canvas, #f4f5f7); color: var(--ink, #111827); }

.cip-body { padding: 14px 18px 18px; overflow-y: auto; }
.cip-group {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--faint, #9ca3af); margin: 14px 0 8px;
}
.cip-group:first-child { margin-top: 0; }
.cip-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 8px; }
.cip-icon {
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 11px 6px; cursor: pointer;
  border: 1px solid var(--line, #e5e7eb); border-radius: 10px; background: #fff;
}
.cip-icon:hover { border-color: var(--brand, #2563eb); background: var(--brand-50, #eff4ff); }
.cip-icon i { font-size: 20px; color: var(--ink-2, #374151); }
.cip-icon:hover i { color: var(--brand, #2563eb); }
.cip-icon span {
  font-size: 10.5px; color: var(--muted, #6b7280);
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cip-empty { text-align: center; padding: 40px 20px; color: var(--muted, #6b7280); font-size: 13.5px; }
.cip-empty-sub { font-size: 12.5px; color: var(--faint, #9ca3af); }

.cip-foot {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 18px; border-top: 1px solid var(--line-2, #eef0f3);
}
.cip-hint { font-size: 12px; color: var(--muted, #6b7280); }
.cip-clear {
  margin-left: auto; border: 1px solid var(--line, #e5e7eb); background: #fff;
  border-radius: 8px; padding: 6px 12px; font-size: 12.5px; font-weight: 600;
  color: var(--muted, #6b7280); cursor: pointer;
}
.cip-clear:hover { border-color: var(--red, #dc2626); color: var(--red, #dc2626); }

/* ══════════════════════════════════════════════════════════════════════════
   USERS + ACCOUNT PROFILE
   ══════════════════════════════════════════════════════════════════════════ */
.usr-cell { display: flex; align-items: center; gap: 11px; }
.usr-av {
  width: 34px; height: 34px; border-radius: 50%; flex: none;
  background: linear-gradient(135deg, var(--brand), #6f9bf7);
  color: #fff; font-size: 12px; font-weight: 600;
  display: flex; align-items: center; justify-content: center;
}
.usr-name { font-size: 13.5px; font-weight: 600; color: var(--ink); display: flex; align-items: center; gap: 7px; }
.usr-email { font-size: 12px; color: var(--muted); }
.usr-you { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; background: var(--brand-50); color: var(--brand); padding: 1px 6px; border-radius: 20px; }
.usr-inactive { opacity: .55; }
.usr-role { font-size: 11.5px; font-weight: 600; padding: 3px 9px; border-radius: 20px; }
.usr-role.role-platform { background: var(--violet-bg); color: var(--violet); }
.usr-role.role-support { background: var(--amber-bg); color: var(--amber); }
.usr-role.role-admin { background: var(--brand-50); color: var(--brand); }
.usr-role.role-editor { background: var(--canvas); color: var(--muted); }
.icon-btn.disabled { opacity: .35; cursor: not-allowed; }

/* Role → permission matrix */
.perm-matrix td, .perm-matrix th { font-size: 13px; }
.perm-matrix .perm-col { text-align: center; width: 140px; }
.perm-name { color: var(--ink-2); }
.perm-yes { color: var(--green); font-size: 15px; }
.perm-no { color: var(--line); font-size: 15px; }

/* Account profile */
.prof-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; align-items: start; }
.prof-wide { grid-column: 1 / -1; }
.prof-body { padding: 16px 20px 20px; }
.prof-id { display: flex; align-items: center; gap: 14px; padding-bottom: 4px; }
.prof-av {
  width: 52px; height: 52px; border-radius: 50%; flex: none;
  background: linear-gradient(135deg, var(--brand), #6f9bf7);
  color: #fff; font-size: 17px; font-weight: 600;
  display: flex; align-items: center; justify-content: center;
}
.prof-role { font-size: 14px; font-weight: 650; color: var(--ink); }
.prof-tenant { font-size: 12.5px; color: var(--muted); }
.prof-pwmeta { margin-top: 12px; font-size: 12.5px; color: var(--muted); display: flex; align-items: center; gap: 7px; }
.prof-pwmeta i { color: var(--faint); }
.prof-perms { display: flex; flex-wrap: wrap; gap: 8px; }
.prof-perm {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12.5px; font-weight: 500; color: var(--ink-2);
  background: var(--canvas); border: 1px solid var(--line); border-radius: 20px; padding: 5px 12px;
}
.prof-perm i { color: var(--green); font-size: 13px; }

@media (max-width: 900px) {
  .prof-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ══════════════════════════════════════════════════════════════════════════
   DATA LISTS
   ══════════════════════════════════════════════════════════════════════════ */
.dl-name { font-size: 14px; font-weight: 600; color: var(--ink); }
.dl-name:hover { color: var(--brand); }
.dl-sub { font-size: 12px; color: var(--muted); margin-top: 3px; }
.dl-sub code { background: var(--canvas); padding: 1px 5px; border-radius: 4px; font-size: 11px; }
.dl-tag {
  font-size: 11.5px; font-weight: 500; padding: 3px 9px; border-radius: 20px;
  background: var(--canvas); color: var(--muted); display: inline-flex; align-items: center; gap: 5px;
  text-decoration: none; max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dl-tag.form { background: var(--violet-bg); color: var(--violet); }
.dl-tag.dyn { background: var(--blue-bg); color: var(--blue); }
.dl-tag.page { background: var(--green-bg); color: var(--green); }
.dl-tag.pdf { background: var(--red-bg); color: var(--red); }
a.dl-tag:hover { filter: brightness(.92); }

/* Two-column editor: columns designer beside the record grid. */
.dl-layout { display: grid; grid-template-columns: 340px minmax(0, 1fr); gap: 16px; align-items: start; margin-top: 20px; }
.dl-panel { padding: 0; overflow: scroll; }
.dl-panel-head {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 16px; border-bottom: 1px solid var(--line-2); font-size: 14px;
}
.dl-count {
  font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 20px;
  background: var(--canvas); color: var(--muted);
}
.dl-panel-head .search-box { margin-bottom: 0; }

/* ── Records panel fullscreen ────────────────────────────────────────────
   1030: comfortably above ordinary page content, but below Bootstrap's own
   modal (~1050/1055, CLAUDE.md's layer-order scale) so the Add/Edit record
   modal still opens on top of a fullscreen grid instead of underneath it.
   .dl-panel's own overflow:scroll is for the un-expanded layout; fullscreen
   takes over as a flex column instead, with only the table area scrolling
   so the head (title, search, toggle) and the pager stay pinned in view. */
.dl-panel.is-fullscreen {
  position: fixed; inset: 0; z-index: 1030;
  border-radius: 0; overflow: hidden;
  display: flex; flex-direction: column;
}
.dl-panel.is-fullscreen .dl-panel-head,
.dl-panel.is-fullscreen .dl-pager { flex: none; }
.dl-panel.is-fullscreen .table-wrap { flex: 1 1 auto; overflow: auto; }
.dl-panel.is-fullscreen .empty-lg {
  flex: 1 1 auto; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
}
body.dl-fullscreen-lock { overflow: hidden; }

/* Column rows */
.dl-cols { padding: 10px 12px; display: flex; flex-direction: column; gap: 5px; }
.dl-col-row {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 9px; background: var(--surface);
}
.dl-col-row:hover { border-color: var(--brand-100); background: var(--brand-50); }
.dl-col-type {
  width: 28px; height: 28px; border-radius: 7px; flex: none;
  background: var(--canvas); color: var(--brand);
  display: flex; align-items: center; justify-content: center; font-size: 14px;
}
.dl-col-main { min-width: 0; flex: 1; }
.dl-col-label { font-size: 13.5px; font-weight: 550; color: var(--ink); display: flex; align-items: center; gap: 5px; }
.dl-col-key { font-size: 11px; color: var(--faint); }
.dl-col-off { color: var(--faint); font-size: 11px; }
.dl-req { color: var(--red); font-weight: 700; }
.dl-col-actions { display: flex; gap: 1px; flex: none; opacity: 0; transition: opacity .12s; }
.dl-col-row:hover .dl-col-actions { opacity: 1; }

.dl-col-add {
  border-top: 1px solid var(--line-2); padding: 12px 16px 16px;
  display: flex; flex-direction: column; gap: 8px;
}
.dl-req-check { font-size: 13px; color: var(--ink-2); display: flex; align-items: center; gap: 8px; cursor: pointer; }

/* Record grid */
.dl-records tbody td { padding: 10px 20px; font-size: 13px; }
.dl-records thead th { white-space: nowrap; }
.dl-cell { display: inline-block; max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }
.dl-thumb { width: 40px; height: 40px; object-fit: cover; border-radius: 7px; border: 1px solid var(--line); }
.dl-pager {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px; border-top: 1px solid var(--line-2); font-size: 12.5px; color: var(--muted);
}
.dl-pager-btns { display: flex; gap: 6px; }

/* Record editor form */
.dl-form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 16px; }
.dl-form-wide { grid-column: 1 / -1; }

/* Import mapping */
.dl-map { padding: 14px 16px 18px; }
.dl-map-hint { font-size: 12.5px; color: var(--muted); margin: 0 0 14px; }
.dl-map-hint em { font-style: normal; font-weight: 600; color: var(--ink-2); }
.dl-map-row {
  display: grid; grid-template-columns: minmax(0, 1fr) 28px minmax(0, 1fr);
  align-items: center; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--line-2);
}
.dl-map-row:last-child { border-bottom: none; }
.dl-map-label { font-size: 13.5px; font-weight: 550; color: var(--ink); display: flex; align-items: center; gap: 5px; }
.dl-map-target { min-width: 0; }
.dl-map-arrow { color: var(--faint); text-align: center; font-size: 15px; }
.dl-mode {
  display: flex; align-items: flex-start; gap: 11px; padding: 12px 14px; cursor: pointer;
  border: 1px solid var(--line); border-radius: 10px; margin-bottom: 8px;
}
.dl-mode:hover { border-color: var(--brand-100); background: var(--brand-50); }
.dl-mode input { margin-top: 3px; }
.dl-mode strong { display: block; font-size: 13.5px; color: var(--ink); }
.dl-mode span { font-size: 12.5px; color: var(--muted); }

@media (max-width: 1180px) {
  .dl-layout { grid-template-columns: minmax(0, 1fr); }
  .dl-form-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ══════════════════════════════════════════════════════════════════════════
   DYNAMIC BLOCKS — admin
   ══════════════════════════════════════════════════════════════════════════ */
.dyn-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 16px; }
.dyn-card { padding: 16px 18px 14px; display: flex; flex-direction: column; gap: 12px; }
.dyn-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.dyn-name { font-size: 15px; font-weight: 650; color: var(--ink); }
.dyn-name:hover { color: var(--brand); }
.dyn-slug { margin-top: 5px; }
.dyn-slug code { font-size: 11px; color: var(--muted); background: var(--canvas); padding: 2px 6px; border-radius: 5px; }
.dyn-el {
  flex: none; font-size: 11px; font-weight: 600; padding: 3px 9px; border-radius: 20px;
  background: var(--brand-50); color: var(--brand); display: inline-flex; align-items: center; gap: 5px;
}
.dyn-src {
  display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--ink-2);
  background: var(--canvas); border-radius: 9px; padding: 9px 12px;
}
.dyn-src.missing { background: var(--red-bg); color: var(--red); }
.dyn-src > i { color: var(--brand); }
.dyn-src.missing > i { color: var(--red); }
.dyn-recs { margin-left: auto; font-size: 11.5px; color: var(--muted); }
.dyn-warn { margin-left: auto; font-size: 11.5px; font-weight: 600; }
.dyn-meta { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 12px; color: var(--muted); }
.dyn-meta i { color: var(--faint); margin-right: 4px; }
.dyn-actions { display: flex; align-items: center; gap: 6px; border-top: 1px solid var(--line-2); padding-top: 12px; margin-top: auto; }

/* Editor: config column + sticky preview */
.dyn-edit { display: grid; grid-template-columns: minmax(0, 420px) minmax(0, 1fr); gap: 16px; align-items: start; }
.dyn-config { display: flex; flex-direction: column; gap: 16px; }
.dyn-preview-col { position: sticky; top: 0; }
.dyn-panel { padding: 0; overflow: hidden; }
.dyn-panel-head {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 16px; border-bottom: 1px solid var(--line-2); font-size: 14px;
}
.dyn-step {
  width: 22px; height: 22px; border-radius: 50%; flex: none;
  background: var(--brand); color: #fff; font-size: 12px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.dyn-panel-body { padding: 14px 16px 18px; }

.dyn-radio-row { display: flex; flex-direction: column; gap: 8px; }
.dyn-radio {
  display: flex; align-items: flex-start; gap: 11px; padding: 11px 13px; cursor: pointer;
  border: 1px solid var(--line); border-radius: 10px;
}
.dyn-radio:hover { border-color: var(--brand-100); background: var(--brand-50); }
.dyn-radio input { margin-top: 3px; }
.dyn-radio:has(input:checked) { border-color: var(--brand); background: var(--brand-50); }
.dyn-radio strong { display: block; font-size: 13.5px; color: var(--ink); }
.dyn-radio span { font-size: 12px; color: var(--muted); }

.dyn-cols { display: flex; flex-direction: column; gap: 4px; max-height: 280px; overflow-y: auto; }
.dyn-col-check {
  display: flex; align-items: center; gap: 9px; padding: 7px 10px; cursor: pointer;
  border: 1px solid transparent; border-radius: 8px; font-size: 13.5px;
}
.dyn-col-check:hover { background: var(--canvas); }

/* "Load component" row above the Custom element's template editor. */
.dyn-load-row { display: flex; gap: 8px; margin-bottom: 10px; }
.dyn-load-row select { flex: 1; }

/* The shared .rte-tokens rail is tuned for the Page Builder's cramped rich-text modal (208px,
   stealing as little width as possible from a small card). This modal is modal-xl with room to
   spare, and with three sections stacked in it (Insert, Load component, Data fields) 208px made
   the template picker and the field chips look cramped — wider here, not globally. */
#dynCustomModal .rte-tokens { flex-basis: 320px; max-width: 320px; }
#dynCustomModal .rte-token-name { font-size: 13.5px; }
#dynCustomModal .rte-token code { font-size: 12px; }

/* Summary row that opens the item-template designer modal. */
.dyn-custom-summary { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 6px; }

/* Placeholder chips over the Custom element's template editor (mirrors the column list). */
.dyn-ph-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.dyn-ph-chip {
  border: 1px solid var(--line); background: #fff; border-radius: 999px;
  font-size: 12px; padding: 3px 10px; color: #374151; cursor: pointer;
}
.dyn-ph-chip:hover { border-color: var(--brand); color: var(--brand); }
.dyn-ph-chip code { font-size: 11px; color: #9ca3af; }
.dyn-col-check:has(input:checked) { background: var(--brand-50); border-color: var(--brand-100); }
.dyn-col-name { font-weight: 550; color: var(--ink); }
.dyn-col-check .dl-col-key { margin-left: auto; }

.dyn-elements { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
/* position: relative is load-bearing, not cosmetic. Without it the absolutely positioned input
   below resolves its containing block against .main-content (the nearest positioned ancestor,
   admin.css) instead of its own label. The input then no longer moves when .content-scroll
   scrolls, so clicking a display element focused a control whose box sat outside the viewport —
   the browser scrolled it into view by scrolling .main-content itself, which is overflow:hidden.
   That pushed the header and the top of the page off-screen with no scrollbar to bring them back.
   Matches the pattern .font-opt / .radius-opt already use in admin.css. */
.dyn-element { position: relative; cursor: pointer; }
.dyn-element input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; pointer-events: none; }
.dyn-element-box {
  display: flex; flex-direction: column; gap: 3px; padding: 13px;
  border: 1px solid var(--line); border-radius: 10px; height: 100%;
}
.dyn-element-box i { font-size: 19px; color: var(--brand); margin-bottom: 3px; }
.dyn-element-box strong { font-size: 13px; color: var(--ink); }
.dyn-element-box span { font-size: 11.5px; color: var(--muted); }
.dyn-element:hover .dyn-element-box { border-color: var(--brand-100); background: var(--brand-50); }
.dyn-element input:checked + .dyn-element-box {
  border-color: var(--brand); background: var(--brand-50); box-shadow: 0 0 0 2px var(--brand-100);
}

.dyn-two { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.dyn-preview { padding: 18px; max-height: 72vh; overflow-y: auto; background: #fff; }

@media (max-width: 1240px) {
  .dyn-edit { grid-template-columns: minmax(0, 1fr); }
  .dyn-preview-col { position: static; }
}
@media (max-width: 620px) {
  .dyn-elements, .dyn-two { grid-template-columns: minmax(0, 1fr); }
}

/* ══════════════════════════════════════════════════════════════════════════
   DYNAMIC BLOCKS — rendered output (public + preview)
   ══════════════════════════════════════════════════════════════════════════ */
.cms-dyn-empty {
  padding: 30px; text-align: center; color: #6b7280; font-size: 14px;
  background: #f8fafc; border: 1px dashed #cbd5e1; border-radius: 12px;
}
.cms-dyn-table { width: 100%; margin: 0; }
.cms-dyn-table th { font-size: 12.5px; text-transform: uppercase; letter-spacing: .04em; color: #6b7280; white-space: nowrap; }
.cms-dyn-table td { vertical-align: middle; font-size: 14px; }
.cms-dyn-thumb { width: 48px; height: 48px; object-fit: cover; border-radius: 8px; }
.cms-dyn-yes { color: #16a34a; }
.cms-dyn-no { color: #9ca3af; }
.cms-dyn-label { color: #6b7280; font-size: 12.5px; }

/* Card grid. --n is set per row-count class so one rule handles every width. */
.cms-dyn-grid { display: grid; gap: 20px; grid-template-columns: repeat(var(--n, 3), minmax(0, 1fr)); }
.cms-dyn-grid.cols-1 { --n: 1; }
.cms-dyn-grid.cols-2 { --n: 2; }
.cms-dyn-grid.cols-3 { --n: 3; }
.cms-dyn-grid.cols-4 { --n: 4; }
.cms-dyn-grid.cols-5 { --n: 5; }
.cms-dyn-grid.cols-6 { --n: 6; }

.cms-dyn-card { margin: 0; }
.cms-dyn-card-img {
  aspect-ratio: 4 / 3; overflow: hidden; border-radius: 12px; background: #f1f2f4;
  position: relative;
}
.cms-dyn-card-img img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .3s; }
.cms-dyn-card:hover .cms-dyn-card-img img { transform: scale(1.04); }

/* Clickable gallery tile — signals the image opens larger. */
.cms-lb-link { display: block; width: 100%; height: 100%; cursor: zoom-in; position: relative; }
.cms-lb-zoom {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: rgba(17, 24, 39, .38); color: #fff; font-size: 20px;
  opacity: 0; transition: opacity .18s;
}
.cms-lb-link:hover .cms-lb-zoom, .cms-lb-link:focus-visible .cms-lb-zoom { opacity: 1; }
.cms-lb-link:focus-visible { outline: 3px solid var(--site, #2563eb); outline-offset: 2px; }

/* ── Lightbox overlay (lightbox.js) ─────────────────────────────────────── */
body.cms-lb-open { overflow: hidden; }
.cms-lb {
  position: fixed; inset: 0; z-index: 1100; display: none;
  align-items: center; justify-content: center;
  background: rgba(9, 12, 20, .92); padding: 40px 64px;
}
.cms-lb-stage { margin: 0; max-width: 100%; max-height: 100%; display: flex; flex-direction: column; gap: 12px; }
.cms-lb-stage img {
  max-width: 100%; max-height: 78vh; object-fit: contain;
  border-radius: 8px; background: #111; display: block; margin: 0 auto;
}
.cms-lb-stage figcaption { color: #e5e7eb; font-size: 14px; text-align: center; }
.cms-lb-close, .cms-lb-prev, .cms-lb-next {
  position: absolute; border: none; cursor: pointer; color: #fff;
  background: rgba(255, 255, 255, .12); border-radius: 50%;
  width: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
  font-size: 17px; transition: background .15s;
}
.cms-lb-close:hover, .cms-lb-prev:hover, .cms-lb-next:hover { background: rgba(255, 255, 255, .26); }
.cms-lb-close:focus-visible, .cms-lb-prev:focus-visible, .cms-lb-next:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.cms-lb-close { top: 20px; right: 20px; }
.cms-lb-prev { left: 14px; top: 50%; transform: translateY(-50%); }
.cms-lb-next { right: 14px; top: 50%; transform: translateY(-50%); }
.cms-lb-count { position: absolute; bottom: 18px; left: 0; right: 0; text-align: center; color: #9aa4b2; font-size: 12.5px; }

@media (max-width: 620px) {
  .cms-lb { padding: 20px 12px; }
  .cms-lb-prev { left: 6px; }
  .cms-lb-next { right: 6px; }
  .cms-lb-stage img { max-height: 68vh; }
}
.cms-dyn-card-body { padding: 10px 2px 0; }
.cms-dyn-card-title { font-size: 14.5px; font-weight: 600; color: #111827; }
.cms-dyn-card-meta { font-size: 13px; color: #6b7280; margin-top: 2px; }
.cms-dyn-bscard { border-radius: 12px; overflow: hidden; }
.cms-dyn-bscard .card-img-top { aspect-ratio: 16 / 10; object-fit: cover; }

.cms-dyn-list .list-group-item { padding: 14px 16px; }
.cms-dyn-list-title { font-size: 14.5px; font-weight: 600; color: #111827; }
.cms-dyn-list-meta { font-size: 13px; color: #6b7280; margin-top: 2px; }

/* Pager */
.cms-dyn-pager {
  margin-top: 24px; display: flex; flex-direction: column; align-items: center; gap: 8px;
}
.cms-dyn-pager .pagination { margin: 0; flex-wrap: wrap; justify-content: center; }
.cms-dyn-pager .page-link { color: var(--site, #2563eb); }
.cms-dyn-pager .page-item.active .page-link {
  background: var(--site, #2563eb); border-color: var(--site, #2563eb); color: #fff;
}
.cms-dyn-pager-note { font-size: 12.5px; color: #6b7280; }

/* Calendar (Support/DynamicRenderer.cs RenderCalendar + wwwroot/js/dynamic-calendar.js) */
.cms-dyn-calendar {
  background: #fff; border: 1px solid #e5e7eb; border-radius: 12px; padding: 16px;
}
.cms-dyn-calendar .fc {
  --fc-border-color: #e5e7eb;
  --fc-today-bg-color: color-mix(in srgb, var(--brand-primary, #2563eb) 8%, white);
  --fc-button-bg-color: var(--brand-primary, #2563eb);
  --fc-button-border-color: var(--brand-primary, #2563eb);
  --fc-button-hover-bg-color: var(--brand-primary-700, #1d4ed8);
  --fc-button-hover-border-color: var(--brand-primary-700, #1d4ed8);
  --fc-button-active-bg-color: var(--brand-primary-800, #1e40af);
  font-family: var(--font-primary, inherit);
}
.cms-dyn-calendar .fc-event { cursor: pointer; border: none; }
.cms-dyn-cal-badge { color: #fff; font-weight: 600; }
.cms-dyn-cal-thumb { width: 100%; height: 90px; object-fit: cover; }

@media (max-width: 900px) {
  .cms-dyn-grid { --n: 2 !important; }
}
@media (max-width: 560px) {
  .cms-dyn-grid { --n: 1 !important; }
}

/* ══════════════════════════════════════════════════════════════════════════
   SLIDERS — admin
   ══════════════════════════════════════════════════════════════════════════ */
.sl-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(360px, 1fr)); gap: 16px; }
.sl-card { padding: 0; overflow: hidden; display: flex; flex-direction: column; }
.sl-strip { display: flex; gap: 2px; height: 96px; background: var(--canvas); }
.sl-thumb { flex: 1; min-width: 0; overflow: hidden; position: relative; }
.sl-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sl-thumb.off { opacity: .4; }
.sl-thumb-none, .sl-img-none {
  width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
  color: var(--faint); font-size: 18px; background: var(--canvas);
}
.sl-thumb-more {
  flex: 0 0 54px; display: flex; align-items: center; justify-content: center;
  background: var(--ink); color: #fff; font-size: 13px; font-weight: 600;
}
.sl-strip-empty {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px;
  color: var(--faint); font-size: 13px;
}
.sl-body { padding: 14px 16px 10px; }
.sl-name { font-size: 15px; font-weight: 650; color: var(--ink); }
.sl-name:hover { color: var(--brand); }
.sl-slug { margin-top: 5px; }
.sl-slug code { font-size: 11px; color: var(--muted); background: var(--canvas); padding: 2px 6px; border-radius: 5px; }
.sl-meta { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 12px; color: var(--muted); margin-top: 9px; }
.sl-meta i { color: var(--faint); margin-right: 4px; }
.sl-actions { display: flex; align-items: center; gap: 6px; padding: 0 16px 14px; margin-top: auto; }

/* Slider editor */
.sl-edit { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: 16px; align-items: start; }
.sl-side { display: flex; flex-direction: column; gap: 16px; }
.sl-panel { padding: 0; overflow: hidden; }
.sl-panel-head {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 16px; border-bottom: 1px solid var(--line-2); font-size: 14px;
}
.sl-settings { padding: 14px 16px 18px; }

.sl-list { list-style: none; margin: 0; padding: 12px; display: flex; flex-direction: column; gap: 6px; }
.sl-item {
  display: flex; align-items: center; gap: 11px; padding: 9px 11px;
  border: 1px solid var(--line); border-radius: 10px; background: var(--surface);
}
.sl-item:hover { border-color: var(--brand-100); background: var(--brand-50); }
.sl-item.dragging { opacity: .4; }
.sl-item.inactive { opacity: .6; }
.sl-item-thumb { width: 74px; height: 48px; flex: none; border-radius: 7px; overflow: hidden; background: var(--canvas); }
.sl-item-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sl-item-main { min-width: 0; flex: 1; }
.sl-item-title { font-size: 13.5px; font-weight: 600; color: var(--ink); display: flex; align-items: center; gap: 6px; }
.sl-item-sub { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sl-item-actions { display: flex; gap: 1px; flex: none; opacity: 0; transition: opacity .12s; }
.sl-item:hover .sl-item-actions { opacity: 1; }

.sl-preview { padding: 14px; }
.sl-img-row { display: flex; gap: 8px; }
.sl-img-row .set-input { flex: 1; }

/* Slide/menu button colours: swatch-pair triggers + "Theme" reset. The trigger opens the
   shared CmsColorPicker popover (js/color-picker.js); a slashed swatch means unset —
   the button follows the theme. */
.sl-btn-colors { display: flex; align-items: center; gap: 6px; margin-top: 8px; }
.ccp-btn {
  width: 34px; height: 28px; padding: 0; border: 1px solid var(--line);
  border-radius: 7px; background: #fff; cursor: pointer; position: relative;
}
.ccp-btn.unset::after {
  content: ''; position: absolute; inset: 4px; border-radius: 4px;
  background: linear-gradient(to top left,
    transparent 44%, #d1d5db 46%, #d1d5db 54%, transparent 56%);
}
/* The literal "Transparent" choice (CssColor now accepts the keyword) needs its own mark —
   a slashed swatch already means "unset, follows the theme", which is a different thing from
   "this stop is deliberately see-through". The standard checkerboard reads as transparency
   everywhere else (image editors, browser devtools), so it's used here too. is-transparent
   wins over unset when both would otherwise apply, since the value is genuinely set. */
.ccp-btn.is-transparent::after {
  content: ''; position: absolute; inset: 4px; border-radius: 4px;
  background-image:
    linear-gradient(45deg, #d1d5db 25%, transparent 25%, transparent 75%, #d1d5db 75%),
    linear-gradient(45deg, #d1d5db 25%, transparent 25%, transparent 75%, #d1d5db 75%);
  background-size: 8px 8px;
  background-position: 0 0, 4px 4px;
}
.sl-creset {
  border: 1px solid var(--line); background: #fff; border-radius: 7px;
  font-size: 12px; padding: 4px 10px; color: #6b7280; cursor: pointer;
}
.sl-creset:hover { border-color: var(--brand); color: var(--brand); }
/* Same pattern in the menu builder's props panel (highlighted-item colours). */
.mb-colorrow { display: flex; align-items: center; gap: 6px; margin-top: 6px; }

/* The popover itself. Fixed + high z-index: anchors sit inside scroll panels and (for
   sliders) the Bootstrap modal at 1055, both of which would clip or cover an absolute
   child. 1210 slots above the media folder menus (1200), below TinyMCE (1300). */
.ccp-pop {
  position: fixed; z-index: 1210; width: 236px;
  background: #fff; border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 18px 40px rgba(17, 24, 39, .18); padding: 10px 12px;
  max-height: 70vh; overflow-y: auto;
}
.ccp-group {
  font-size: 10.5px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .05em; color: #9ca3af; margin: 8px 0 4px;
}
.ccp-group:first-child { margin-top: 0; }
.ccp-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 6px; }
.ccp-sw {
  width: 22px; height: 22px; border-radius: 6px; padding: 0;
  border: 1px solid rgba(17, 24, 39, .12); cursor: pointer;
}
.ccp-sw.on { outline: 2px solid var(--brand); outline-offset: 1px; }
/* flex-wrap: three controls (hex input + two "clear" buttons, now that Transparent joined
   Theme default) don't reliably fit the popover's 236px on one line at a readable font size —
   wrapping is a no-op when they do fit, and the fallback when they don't. */
.ccp-foot { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 10px; }
.ccp-foot .ccp-clear { flex: 1 1 80px; }
.ccp-hex { width: 36px; height: 27px; padding: 1px; border: 1px solid var(--line); border-radius: 6px; background: #fff; }
.ccp-clear {
  flex: 1; border: 1px solid var(--line); background: #fff; border-radius: 6px;
  font-size: 12px; padding: 4px 8px; color: #6b7280; cursor: pointer;
}
.ccp-clear:hover { border-color: var(--brand); color: var(--brand); }
.sl-img-preview { margin-top: 10px; height: 150px; border-radius: 10px; overflow: hidden; background: var(--canvas); }
.sl-img-preview img { width: 100%; height: 100%; object-fit: cover; display: block; }

.sl-pick-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px; max-height: 60vh; overflow-y: auto; }
.sl-pick-item { border: 1px solid var(--line); border-radius: 10px; background: #fff; padding: 0; overflow: hidden; cursor: pointer; text-align: left; }
.sl-pick-item:hover { border-color: var(--brand); box-shadow: var(--shadow-sm); }
.sl-pick-img { display: block; aspect-ratio: 4 / 3; background: var(--canvas); }
.sl-pick-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sl-pick-name {
  display: block; padding: 7px 9px; font-size: 11.5px; color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

@media (max-width: 1180px) {
  .sl-edit { grid-template-columns: minmax(0, 1fr); }
}

/* ══════════════════════════════════════════════════════════════════════════
   SLIDERS — rendered carousel (public + preview)
   ══════════════════════════════════════════════════════════════════════════ */
.cms-slider { position: relative; overflow: hidden; border-radius: 14px; background: #0f1420; }
.cms-slider .carousel-item { height: var(--cms-slide-h, clamp(320px, 52vh, 560px)); position: relative; }

/* Per-slider corner choice (SlidersApiController's "corners" prop) — same scale as the Theme
   Builder's card radius (Support/ThemeCss.RadiusValues) so "Rounded"/"Sharp"/"Pill" read the same
   way here as everywhere else, but literal rather than var(--site-radius): this is a per-block
   override, not the tenant default, so it must not move when the workspace theme changes.
   .cms-slider's own border-radius above is the fallback for slides saved before this existed —
   their wrapper carries no cms-slider-corners-* class, so it is untouched. */
.cms-slider-corners-sharp .cms-slider { border-radius: 3px; }
.cms-slider-corners-rounded .cms-slider { border-radius: 16px; }
.cms-slider-corners-pill .cms-slider { border-radius: 22px; }
.cms-slide-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.cms-slide-noimg { background: linear-gradient(135deg, var(--site, #4338ca), var(--site-2, #7c3aed)); }
.cms-slide-scrim { position: absolute; inset: 0; background: #0b1020; }

.cms-slide-body {
  position: absolute; inset: 0; display: flex;
  padding: 40px clamp(24px, 6vw, 88px);
}
.cms-slide-start { justify-content: flex-start; text-align: left; }
.cms-slide-center { justify-content: center; text-align: center; }
.cms-slide-end { justify-content: flex-end; text-align: right; }
/* Cross-axis of the same flex row as the horizontal classes above — align-items used to be
   hardcoded to center on .cms-slide-body itself; now it's one of these three, same shape as
   the horizontal variants, so vertical position is a per-slide choice rather than fixed. */
.cms-slide-valign-top { align-items: flex-start; }
.cms-slide-valign-center { align-items: center; }
.cms-slide-valign-bottom { align-items: flex-end; }
.cms-slide-inner { max-width: 640px; color: #fff; }

.cms-slide-sub {
  font-size: 12.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .1em;
  opacity: .85; margin-bottom: 10px;
}
.cms-slide-title {
  font-family: var(--site-font-head, inherit);
  font-size: clamp(26px, 4.4vw, 46px); font-weight: 700; line-height: 1.12; margin: 0 0 12px;
  color: #fff;
}
.cms-slide-desc { font-size: clamp(14.5px, 1.5vw, 17px); line-height: 1.6; opacity: .92; margin: 0 0 22px; }
.cms-slide-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.cms-slide-center .cms-slide-actions { justify-content: center; }
.cms-slide-end .cms-slide-actions { justify-content: flex-end; }

.cms-slide-btn {
  display: inline-block; font-size: 14.5px; font-weight: 600; padding: 11px 22px;
  border-radius: var(--site-radius-btn, 9px); text-decoration: none;
  transition: filter .14s, background .14s, border-color .14s;
}
/* Solid: filled background, no border — the background colour (custom or theme) carries it alone. */
.cms-slide-btn.solid.primary { background: var(--site, #4338ca); color: #fff !important; border: none; }
.cms-slide-btn.solid.secondary { background: rgba(255,255,255,.14); color: #fff !important; border: none; }
.cms-slide-btn.solid:hover { filter: brightness(1.08); }
/* Outline: transparent background, a visible border. Border colour follows the button's own text
   colour when set (SliderRenderer); otherwise it falls back to a translucent white per role. */
.cms-slide-btn.outline { background: transparent; }
.cms-slide-btn.outline.primary { color: #fff !important; border: 1px solid #fff; }
.cms-slide-btn.outline.secondary { color: #fff !important; border: 1px solid rgba(255,255,255,.45); }
.cms-slide-btn.outline:hover { background: rgba(255,255,255,.14); }

.cms-slider .carousel-indicators { margin-bottom: 14px; }
.cms-slider .carousel-indicators button { width: 26px; height: 3px; border-radius: 2px; }
.cms-slider .carousel-control-prev, .cms-slider .carousel-control-next { width: 8%; opacity: .7; }
.cms-slider .carousel-control-prev:hover, .cms-slider .carousel-control-next:hover { opacity: 1; }

.cms-slider-empty {
  padding: 40px; text-align: center; color: #6b7280; font-size: 14px;
  background: #f8fafc; border: 1px dashed #cbd5e1; border-radius: 12px;
}

/* Respect a reduced-motion preference: Bootstrap still changes slides, but without the animation. */
@media (prefers-reduced-motion: reduce) {
  .cms-slider .carousel-item { transition: none; }
  .cms-dyn-card-img img { transition: none; }
  .cms-dyn-card:hover .cms-dyn-card-img img { transform: none; }
}

@media (max-width: 720px) {
  .cms-slide-body { padding: 28px 22px; justify-content: center; text-align: center; }
  .cms-slide-actions { justify-content: center; }
  .cms-slider .carousel-control-prev, .cms-slider .carousel-control-next { display: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   RICH-TEXT EDITOR MODAL (rte.js + TinyMCE)

   One definition for both surfaces that edit component HTML:
     • the Page Builder — a text block, or a component just detached on the canvas
       (/builders/craft/craft-richtext.js)
     • the Component Library — the Edit action (/js/components.js)
   Same markup, same stylesheet, so the two can't drift apart.

   Layer order, and why the modal sits at 1070 rather than higher:

     1050  Bootstrap modal-backdrop / .tpl-drawer-scrim
     1060  .tpl-drawer                        (admin)   |  1000  Craft's data-binding modal
     1070  .rte-overlay        ← the editor card
     1080  .toast-host                        (admin)
     1300  .tox-tinymce-aux    ← TinyMCE menus, dialogs, source view (stock value)
     1400  .cmp-overlay        ← media picker, opened from the editor's image button

   Everything TinyMCE and the picker put on <body> lands OUTSIDE .rte-overlay, so it competes
   with the card's z-index instead of nesting inside it. Keeping the card low means the stock
   1300 already clears it and nothing needs an !important override.
   ══════════════════════════════════════════════════════════════════════════ */
.rte-overlay {
  position: fixed; inset: 0; z-index: 1070;
  background: rgba(17, 24, 39, .55);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.rte-box {
  background: #fff; border-radius: 14px; width: min(1320px, 96%); height: min(90vh, 900px);
  display: flex; flex-direction: column; overflow: hidden;
  box-shadow: 0 24px 60px rgba(17, 24, 39, .3);
}
/* The Component Library wraps the card contents in a <form>; it has to carry the column layout
   through so the editor still fills the remaining height. */
.rte-box > form { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.rte-head {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 18px; border-bottom: 1px solid #e5e7eb; flex: none;
}
.rte-title { font-weight: 700; font-size: 15px; color: #1b1c2e; display: inline-flex; align-items: center; gap: 8px; }
.rte-title i { color: #2563eb; }
.rte-sub { font-size: 12.5px; color: #6b7280; font-weight: 500; }
.rte-actions { margin-left: auto; display: flex; gap: 8px; }
.rte-cancel, .rte-save {
  border-radius: 8px; padding: 8px 16px; font-size: 13px; font-weight: 600; cursor: pointer;
  border: 1px solid #e5e7eb; background: #fff; color: #374151;
}
.rte-cancel:hover { background: #f3f4f6; }
.rte-save { background: #2563eb; border-color: #2563eb; color: #fff; }
.rte-save:hover { background: #1d4ed8; }
/* The editor fills the remaining height; TinyMCE sizes itself to this box. */
.rte-body { flex: 1; min-height: 0; display: flex; }
.rte-body .tox-tinymce { border: none; flex: 1; }
/* The editor column, so the placeholder rail can sit beside it without TinyMCE
   stretching across both. */
.rte-main { flex: 1; min-width: 0; display: flex; }

/* ── Placeholder rail ──────────────────────────────────────────────────────
   Site tokens an author can drop into the content. The list is fetched from
   /api/site/tokens, which is generated from TokenResolver's catalog, so it
   cannot list a token the renderer does not understand. */
.rte-tokens {
  /* 208px, down from 262px: the rail only ever shows short labels and truncated sample
     values, and every pixel it holds comes out of the editing surface. min-width kills the
     flex "auto" minimum — without it, a child's min-content width silently outvotes the
     flex-basis and the rail renders wider than asked. */
  flex: 0 0 208px; min-width: 0; max-width: 208px;
  border-left: 1px solid #e5e7eb; background: #fbfbfd;
  display: flex; flex-direction: column; min-height: 0;
}
/* "Insert" tools row at the top of the rail (icon picker). */
.rte-tools { padding: 0 10px 10px; border-bottom: 1px solid #eceef2; margin-bottom: 6px; }
.rte-icon-btn {
  width: 100%; display: flex; align-items: center; justify-content: center; gap: 7px;
  border: 1px solid #dbe2ea; border-radius: 9px; background: #fff; padding: 8px 10px;
  font-size: 12.5px; font-weight: 600; color: #1b1c2e; cursor: pointer;
}
.rte-icon-btn:hover { border-color: #2563eb; color: #2563eb; }
.rte-tokens-head {
  padding: 12px 16px 8px; font-size: 11px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: #6b7280;
}
.rte-tokens-intro { padding: 0 16px 10px; margin: 0; font-size: 11.5px; color: #6b7280; line-height: 1.5; }
.rte-tokens-list { overflow-y: auto; padding: 0 10px 14px; display: flex; flex-direction: column; gap: 4px; }
.rte-token {
  width: 100%; text-align: left; border: 1px solid transparent; border-radius: 9px;
  background: none; padding: 8px 10px; cursor: pointer; display: block;
}
.rte-token:hover { background: #fff; border-color: #dbe2ea; box-shadow: 0 1px 3px rgba(17,24,39,.06); }
.rte-token-name { display: block; font-size: 12.5px; font-weight: 600; color: #1b1c2e; }
.rte-token code {
  display: inline-block; margin-top: 3px; font-size: 11px; color: #2563eb;
  background: #eef2ff; border-radius: 5px; padding: 1px 5px;
}
.rte-token-val {
  display: block; margin-top: 4px; font-size: 11px; color: #6b7280;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rte-token-val.empty { font-style: italic; color: #9aa3ae; }

/* Narrow screens: the rail would leave the editor unusable, so it drops away. */
@media (max-width: 860px) {
  .rte-tokens { display: none; }
}

/* ── Component Library: metadata alongside the editor ─────────────────────── */
/* The builder edits content only. Here the same card also carries the component's name,
   category, icon and description, so they stay in a side rail and the editor keeps the space. */
.ce-main { flex: 1; min-width: 0; display: flex; }
.ce-side {
  flex: 0 0 420px; border-left: 1px solid #e5e7eb; background: #fafbfc;
  padding: 16px 18px; overflow-y: auto;
}
.ce-side .set-label:first-child { margin-top: 0; }
.ce-hint { display: flex; gap: 7px; font-size: 12px; color: #6b7280; margin: 10px 0 0; line-height: 1.5; }
.ce-hint i { color: #2563eb; flex: none; }

@media (max-width: 1020px) {
  /* Stack rather than squeeze: below ~1020px a 420px rail leaves the editor unusable. */
  .rte-body { flex-direction: column; }
  .ce-side { flex: 0 0 auto; border-left: none; border-top: 1px solid #e5e7eb; }
}

/* Placeholder rail group heading (craft-richtext.js). Only rendered when the catalog
   has more than one group, so a single-group rail keeps its original look. */
.rte-token-group {
  font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-3, #8b93a1); margin: 12px 0 5px; padding-top: 8px;
  border-top: 1px solid var(--line, rgba(17, 24, 39, .1));
}
.rte-token-group:first-child { margin-top: 0; padding-top: 0; border-top: none; }

/* Lightbox showing a framed document (PDF or video embed) rather than an image.
   An <img> sizes itself; an <iframe> has no intrinsic size and would collapse, so
   the framed variant is given an explicit stage. */
.cms-lb-framed .cms-lb-stage { width: min(1100px, 92vw); height: min(86vh, 900px); }
.cms-lb-framed .cms-lb-stage iframe {
  /* display is load-bearing, not decoration: the base rule below hides the frame for
     the image case, and clearing the inline style in show() hands control back to CSS —
     which would keep it hidden without this. */
  display: block;
  width: 100%; height: 100%; border: 0; border-radius: 10px; background: #fff;
}
.cms-lb-stage iframe { display: none; }

/* Dynamic block editor: column drag grips + filter rows. */
.dyn-col-grip { color: var(--muted, #9aa3ae); cursor: grab; margin-right: 2px; }
.dyn-col-check.sortable-ghost { opacity: .4; }
.dyn-filters { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px; }
.dyn-filter-row { display: grid; grid-template-columns: 1.2fr 1fr 1.2fr auto; gap: 6px; align-items: center; }
.dyn-filter-row .set-input { margin: 0; }
