/* stylelint-disable custom-property-pattern -- The --_cb-*-vis column-guide
 * variables use a leading-underscore "private" convention; intentional and
 * local to this file (editor column-guide overlay only). */

/* ── Columns layout component ───────────────────────────────────────────── */

/* The responsive cascade (per-viewport --cb-*-effective values) is generated
 * from the Canvas viewport widths (theme.canvas.yml) and injected as an
 * inline <style> by canvas_builder_page_attachments(), including the base
 * (mobile) defaults — kept there rather than here so the generated tag stays
 * self-contained and ordered (base first, then media-query overrides); this
 * linked stylesheet loads after that tag, so base rules here would silently
 * win every breakpoint. See \Drupal\canvas_builder\Viewports.
 *
 * The layout MODE (columns | grid) is also per-viewport: twig resolves it
 * into data-cb-mode-{vp} attributes, and the generated <style> tag carries
 * the mode-dependent declarations (grid-template-columns, alignment) keyed
 * on them, since mode can flip per breakpoint. Only mode-agnostic rules stay
 * in this file. The cb-columns--columns / --grid classes reflect the BASE
 * (mobile) mode and are only used for the editor empty-state hints below. */

.cb-columns {
  display: grid;
}

/* CSS-variable gap (css_vars engine). Under a classes engine the gap is a
   framework utility class instead (data-cb-gap-engine="classes"), so this
   rule doesn't match and the framework class is the sole `gap` source. */
.cb-columns:not([data-cb-gap-engine="classes"]) {
  gap: var(--cb-gap-effective);
}

.cb-columns > * {
  /* Neutralize Bootstrap's row-cols-N utility (classes engine, section.twig):
   * it sets `width: N%` on direct children, designed for its flex .row/.col
   * system. .cb-columns is unconditionally CSS Grid — grid-template-columns
   * (the generated <style> tag) is the SOLE track-width authority under
   * every engine — but unlike row-cols-N's `flex` declarations (inert
   * outside a flex container), its `width` percentage is a plain box-model
   * property and applies regardless of display mode, re-dividing each
   * already-correctly-sized grid track by N again. Mirrors the `.g-*`
   * gutter/`.gap-*` inertness split above, for width instead of gap. */
  width: auto !important;
  min-width: 0; /* prevent grid blowout on long words or fixed-width children */
}

/* Column content wrapper (one Column SDC per visual column): a grid item that
 * stacks its child components. Consumes the SAME --cb-gap-effective the
 * columns row does (inherited down from .cb-columns, incl. under the classes
 * engine — section.twig always emits the CSS-var tokens now, even when a
 * framework gap class is also applied to .cb-columns itself), so one "Gap"
 * value spaces both between columns AND between components stacked inside a
 * single column — including a 1-column section, which has no other columns
 * to space at all. Unconditional: unlike .cb-columns's own `gap` rule above,
 * there's no framework-class counterpart for this to conflict with. */
.cb-col-slot {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: var(--cb-gap-effective);
}

/* ── "Stretch last column" (fill an uneven last row) ─────────────────────── */
/* When fill_last is enabled (Review tab), the LAST column spans the rest of
 * its row at breakpoints where items don't divide evenly — e.g. 4 items in
 * 3 columns wraps "3 + [1 stretched full width]" instead of "3 + 1". Pure
 * CSS, per-viewport, count-agnostic:
 *   rem  = --cb-col-items mod --cb-columns-effective (0 → row is even)
 *   span = 1 + (cols - rem) * sign(rem)  → 1 (no-op) when rem=0, else fills
 *          the remainder of the last row
 * Targets the last IN-FLOW child (last column on the front end; last Canvas
 * wrapper in the editor — never the out-of-flow .cb-columns-guide overlay),
 * via :nth-last-child(1 of :not(.cb-columns-guide)). Requires CSS mod()/
 * sign() (Chrome 125+, Safari 15.4+, Firefox 118+); unsupported browsers get
 * an invalid calc and the last column keeps its normal width — a no-op. */
.cb-columns--fill-last > :nth-last-child(1 of :not(.cb-columns-guide)) {
  --cb-rem: mod(var(--cb-col-items, 1), var(--cb-columns-effective, 1));
  --cb-last-span: calc(1 + (var(--cb-columns-effective, 1) - var(--cb-rem)) * sign(var(--cb-rem)));

  grid-column: span var(--cb-last-span);
}

/* ── Reversed column order ─────────────────────────────────────────────── */
/* --cb-reverse-effective (0|1, per-viewport, from the generated <style> tag)
 * flips VISUAL order only: 0 → natural order:0; 1 → orders descend 16…1 so
 * the first child renders last. Works for side-by-side columns and stacked
 * rows alike (grid auto-placement follows order-modified document order).
 * DOM order — and thus screen readers/keyboard focus — is unchanged. 16
 * rules match the max column count. Mode-agnostic on purpose: reverse is
 * only offered in columns mode, but a viewport that flipped to grid still
 * honours an explicitly stored reverse rather than silently dropping it. */

.cb-columns > :nth-child(1) {
  order: calc(var(--cb-reverse-effective, 0) * 16);
}

.cb-columns > :nth-child(2) {
  order: calc(var(--cb-reverse-effective, 0) * 15);
}

.cb-columns > :nth-child(3) {
  order: calc(var(--cb-reverse-effective, 0) * 14);
}

.cb-columns > :nth-child(4) {
  order: calc(var(--cb-reverse-effective, 0) * 13);
}

.cb-columns > :nth-child(5) {
  order: calc(var(--cb-reverse-effective, 0) * 12);
}

.cb-columns > :nth-child(6) {
  order: calc(var(--cb-reverse-effective, 0) * 11);
}

.cb-columns > :nth-child(7) {
  order: calc(var(--cb-reverse-effective, 0) * 10);
}

.cb-columns > :nth-child(8) {
  order: calc(var(--cb-reverse-effective, 0) * 9);
}

.cb-columns > :nth-child(9) {
  order: calc(var(--cb-reverse-effective, 0) * 8);
}

.cb-columns > :nth-child(10) {
  order: calc(var(--cb-reverse-effective, 0) * 7);
}

.cb-columns > :nth-child(11) {
  order: calc(var(--cb-reverse-effective, 0) * 6);
}

.cb-columns > :nth-child(12) {
  order: calc(var(--cb-reverse-effective, 0) * 5);
}

.cb-columns > :nth-child(13) {
  order: calc(var(--cb-reverse-effective, 0) * 4);
}

.cb-columns > :nth-child(14) {
  order: calc(var(--cb-reverse-effective, 0) * 3);
}

.cb-columns > :nth-child(15) {
  order: calc(var(--cb-reverse-effective, 0) * 2);
}

.cb-columns > :nth-child(16) {
  order: calc(var(--cb-reverse-effective, 0) * 1);
}

/* ── Editor / preview visual hints ────────────────────────────────────── */
/* When a Columns component has no children yet (freshly dropped, items slot
 * empty), render N visible column areas using the same custom properties as
 * the real layout, so editors can see where to drop content. Uses
 * :not(:has(> *)) (no direct element children) so Twig whitespace/HTML
 * comments don't suppress the visual. */

/* Empty-state hint always shows equal-column bands regardless of layout
 * preset (repeating-linear-gradient can't represent variable fr widths). */
.cb-editing .cb-columns--columns:not(:has(> *)) {
  /* Every token has a fallback so this renders even without the Radix theme
     or the generated per-viewport style tag — notably Canvas's library
     THUMBNAIL iframe, where a 3-column look stands in for the unresolved
     column count. */
  --_cb-gap-vis: max(var(--cb-gap-effective, 12px), 2px);
  --_cb-cols-vis: var(--cb-columns-effective, 3);
  --_cb-col-vis: calc((100% - (var(--_cb-cols-vis) - 1) * var(--_cb-gap-vis)) / var(--_cb-cols-vis));
  /* Tall enough that the "choose a layout" overlay stays entirely within an
     empty section; once content is added the section resumes its natural
     height. */
  min-height: 260px;
  border-radius: var(--radius-1, 2px);
  outline: 1px dashed var(--gray-a6, rgb(13, 18, 28, 0.2));
  outline-offset: -1px;
  background-image: repeating-linear-gradient(to right, var(--gray-a3, rgb(13, 18, 28, 0.07)) 0, var(--gray-a3, rgb(13, 18, 28, 0.07)) var(--_cb-col-vis), transparent var(--_cb-col-vis), transparent calc(var(--_cb-col-vis) + var(--_cb-gap-vis)));
}

.cb-editing .cb-columns--grid:not(:has(> *)) {
  min-height: 260px;
  border-radius: var(--radius-1, 2px);
  outline: 1px dashed var(--gray-a6, rgb(13, 18, 28, 0.2));
  outline-offset: -1px;
  background-color: var(--gray-a2, rgb(13, 18, 28, 0.03));
}

/* Individual column/grid slots that are empty (have no child elements).
 * Applies when the wrapper has children but a particular slot is still empty. */
.cb-editing .cb-columns > *:not(:has(> *)) {
  min-height: 60px;
  outline: 1px dashed var(--gray-a5, rgb(13, 18, 28, 0.12));
  outline-offset: -1px;
  background-color: var(--gray-a2, rgb(13, 18, 28, 0.03));
}

/* ── Editor live layout guide ──────────────────────────────────────────── */
/* Transient overlay injected by the editor JS (layout-widgets.js) while the
 * author adjusts count / layout preset / gap / order / min item width. It
 * mirrors the real grid via the SAME custom properties as the component
 * itself (in grid mode the JS copies the resolved auto-fit track list
 * instead), so guide cells always sit on the live tracks at the current
 * breakpoint. Never rendered on published pages. */

/* Overlays the grid at z-index:1 so it's visible over any background;
 * pointer-events:none keeps clicks reaching the Canvas slot underneath. */
.cb-columns:has(> .cb-columns-guide) {
  position: relative;
}

.cb-columns-guide {
  position: absolute;
  z-index: 1;
  display: grid;
  grid-template-columns: var(--cb-template-effective, var(--cb-columns-template, repeat(var(--cb-columns-effective), 1fr)));
  counter-reset: cb-guide-col;
  pointer-events: none;
  inset: 0;
  /* Match the REAL gap on .cb-columns, whatever engine set it. Under the
   * css_vars engine that's --cb-gap-effective; under the classes engine
   * (e.g. Bootstrap's gap-N) it's a framework utility class instead, which
   * never populates --cb-gap-effective. `inherit` reads the parent's actual
   * computed `gap`, so the guide's tracks line up under either engine. */
  gap: inherit;
}

.cb-columns-guide > i {
  position: relative;
  min-height: 24px;
  counter-increment: cb-guide-col;
  border-radius: 0;
  outline: 1px dashed rgb(234, 88, 12, 0.55);
  outline-offset: -1px;
  background: rgb(234, 88, 12, 0.08);
}

.cb-columns-guide > i::after {
  position: absolute;
  top: 4px;
  right: 4px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  content: counter(cb-guide-col);
  text-align: center;
  color: #fff;
  border-radius: 3px;
  background: rgb(234, 88, 12, 0.85);
  font-family: system-ui, sans-serif;
  font-size: 10px;
  font-weight: 600;
  line-height: 16px;
}

/* ── Equal-height columns ────────────────────────────────────────────── */
/* The grid track already stretches its column (align-items default); these
   rules hand that height down through the Column SDC's internals so a lone
   component in each column can fill the track and sibling cards/tiles line
   up. Under a non-stretch valign the boxes are content-sized, so 100% of
   them resolves to the content height and the rules are inert. :only-child
   keeps multi-component columns stacking naturally. */
.cb-columns > * > .cb-col-slot {
  height: 100%;
}
.cb-columns > * > .cb-col-slot > :only-child {
  height: 100%;
}
