/* ======================================================================
   Bright Cloud Studio Layout Utility Framework (Pure CSS)
   DESKTOP-FIRST • max-width media queries
   ====================================================================== */

/* ======================================================================
   PROJECT TOKENS — EDIT THESE PER SITE
   ====================================================================== */
:root {
  /* Page gutters (site margins) */
  --page-gutter: clamp(16px, 4vw, 60px);

  /* Max content width — the single dial for page width. Everything that
     caps content reads this: the .container utility, and the site shell's
     .container_inside rule in website_structure.css. */
  --container-max: 1800px;

/* ======================================================================
   GUTTER SCALE (PROJECT-CONFIGURABLE)
   ======================================================================

   The single source of truth for every gutter value. The .gap-* and
   .pxc-* utilities, the row defaults, and the responsive overrides all
   read from these — so changing a value here retunes the whole site
   without touching a single class name.

   As with the spacing scale, the numbers in class names are STEPS, not
   promises: set --gutter-40 to 32px and .gap-40 becomes 32px.

   NOTE — deliberately SEPARATE from the --space-* scale below.
   The space steps are fluid (--space-40 is clamp(24px, 3vw, 40px)),
   while the fixed gutters are fixed on purpose, so that .gap-40 can
   match a comp exactly. Wiring them together would quietly make every
   fixed gutter fluid and erase the point of the .gap-fluid-* tier.

   Every value must carry a unit — a bare 0 invalidates the column
   calc() that consumes it and the column silently loses its width.
====================================================================== */

  /* Fixed steps */
  --gutter-0:  0px;
  --gutter-16: 16px;
  --gutter-24: 24px;
  --gutter-40: 40px;
  --gutter-60: 60px;

  /* Fluid steps — scale smoothly with the viewport */
  --gutter-fluid-sm: clamp(8px, 1.5vw, 16px);
  --gutter-fluid-md: clamp(12px, 2vw, 32px);
  --gutter-fluid-lg: clamp(24px, 4vw, 64px);

  /* Single-axis fluid (used by .gap-x-fluid / .gap-y-fluid) */
  --gutter-fluid-axis: clamp(12px, 2vw, 40px);

  /* Column inner padding, fluid tier — a SEPARATE scale from the gutters
     above. Inner padding runs wider than a gutter at the top end, so these
     keep their own ceilings (60/80px) rather than the gutter's 64px. */
  --col-pad-fluid-sm: clamp(8px, 1.5vw, 24px);
  --col-pad-fluid:    clamp(16px, 3vw, 60px);
  --col-pad-fluid-lg: clamp(24px, 4vw, 80px);

  /* Default row spacing (desktop) — points at the scale above */
  --row-gap-x: var(--gutter-40);
  --row-gap-y: var(--gutter-40);

  /* Default column inner padding (desktop) — edit per site if needed */
  --row-col-pad-x: var(--gutter-0);

/* ======================================================================
   SPACING SCALE (PROJECT-CONFIGURABLE)
   ======================================================================

   IMPORTANT:
   The numbers in spacing utility class names (mb-40, mt-24, etc.)
   represent spacing STEPS, not fixed pixel values.

   Changing the --space-* values below will update spacing globally
   without changing class names.

   Do NOT assume mb-40 always equals 40px.

   BY DESIGN — FLUID STEPS CONVERGE ON SMALL SCREENS
   -------------------------------------------------
   The larger steps (40/60/80) are fluid clamp() values whose lower bounds
   intentionally overlap the fixed steps below them. Consequence:

     • On narrow viewports (~≤800px) --space-40 sits at its 24px floor, so
       mb-40 and mb-24 render identically. The steps only visibly separate
       on wider screens.

   This is intentional: spacing tightens on mobile and opens up on desktop.
   If you need steps that stay distinct at EVERY width, raise the clamp
   floors (e.g. --space-40: clamp(28px, 3vw, 40px)) — see audit note C7.
====================================================================== */
  --space-0: 0;
  --space-8: 8px;
  --space-12: 12px;
  --space-16: 16px;
  --space-24: 24px;
  --space-40: clamp(24px, 3vw, 40px);
  --space-60: clamp(32px, 5vw, 60px);
  --space-80: clamp(40px, 7vw, 80px);

  /* Major section separation (responsive) */
  --space-section: clamp(32px, 6vw, 96px);
    
    
/* ======================================================================
   SINGLE-COLUMN MAX WIDTH TOKENS (EDIT PER SITE)
   ======================================================================

   Used to constrain one-column rows without affecting global containers.
   Ideal for editorial content, long-form copy, and focused sections.
====================================================================== */

--single-sm: 720px;   /* readable text width */
--single-md: 880px;   /* default content column */
--single-lg: 1040px;  /* wide single-column layouts */


}

/* End tokens ======================================================================
=================================================================================== */

/* ======================================================================
   BOX SIZING RESET — REQUIRED BY THE CONTAINER / COLUMN MATH
   ======================================================================

   Padding must be included in declared widths, or max-width and
   padding-inline compound: .container / #main > .inside would render
   (--container-max + 2 × --page-gutter) wide instead of --container-max,
   and percentage columns would overflow once padding is added.

   This reset previously lived in framework_structure.scss, which v3
   replaces — so v3 must carry it itself.
====================================================================== */
html {
  box-sizing: border-box;
}

*,
*::before,
*::after {
  box-sizing: inherit;
}


/* ======================================================================
   CONTAINERS — SAFE TO REUSE ACROSS PROJECTS
   ====================================================================== */
.container {
  margin-inline: auto;
  padding-inline: var(--page-gutter);
  max-width: var(--container-max);
}

.container-fluid {
  width: 100%;
  padding-inline: var(--page-gutter);
}


/* ======================================================================
   THE PAGE CONTAINER LIVES IN THE SITE STYLESHEET — NOT HERE
   ======================================================================

   This framework is CMS-agnostic: it owns containers, rows, columns and
   spacing utilities, but it does NOT claim any CMS-specific selector.

   In the "article = .row" model each article renders into the CMS's main
   content column, and THAT column is what carries the site's max-width,
   centring and page gutter. In Contao that is .container_inside — which
   wraps #main and the left/right columns — and the rule belongs in the
   site shell stylesheet (website_structure.css), alongside the matching
   rules for the header, prefooter and footer.

   Two selectors previously claimed it — this file and the site shell —
   at identical specificity (1,1,0), so whichever stylesheet happened to
   load last silently decided the site's content width. One owner now.

   Nothing here depends on it: with the gap engine rows use no negative
   margins, so they can never overflow their parent. Without a container
   rule, rows simply run the full width of whatever contains them.
====================================================================== */




/* AUDIT NOTE — .bleed-x
   .bleed-x applies negative margins to break out of container gutters.
   Use it for full-bleed backgrounds/sections.

   Avoid putting .bleed-x on elements inside components that already have
   their own padding (cards, modals) unless you intend for it to escape. */

/* Full-bleed helper — breaks out of the container GUTTER only. Use inside a
   full-width parent, or when --container-max ≈ the viewport. */
.bleed-x {
  margin-inline: calc(-1 * var(--page-gutter));
  padding-inline: 0;
}

/* Viewport-wide bleed — breaks out all the way to the screen edges, even when
   the content column (--container-max) is narrower than the viewport. Use it
   for full-width COLOUR BANDS, then put an inner `.container` back inside to
   re-cap the content. Relies on html { overflow-x: clip } (website_structure)
   so the 100vw never introduces a horizontal scrollbar.

     <section class="mod_article hero hero--photo bleed-full">
       <div class="container"> … </div>
     </section> */
.bleed-full {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
}

/* Full-width colour BAND with self-capping content. Put it on a section/article
   that carries a background: the band itself spans the viewport, and each of
   its DIRECT children is re-capped to the content column and gutter-padded —
   so no inner `.container` wrapper (or element group) is needed. This is what
   the native-content-element sections use: article = .band, children = the
   headline / text / image / element-group content elements. */
.band {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  padding-inline: 0;
}
.band > * {
  box-sizing: border-box;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--page-gutter);
}

/* Bleeding a COLUMN needs two corrections:

   1. padding — plain .bleed-x ties with .row > * and loses on source
      order, so the gutter padding has to be dropped at higher specificity.

   2. width — a flex item's percentage basis resolves against the row's
      content box, and margins sit OUTSIDE that box. So negative margins
      do not widen the item, they shrink its margin box to (100% - 2×gutter)
      and, because flex-grow is 0 and justify-content is flex-start, the
      whole box simply shifts left: correct bleed on the left, but two
      gutters short on the right. Paying for both margins in the basis
      makes the margin box exactly 100% again, so the band lands flush on
      both edges.

   Only full-width bleeds make sense here; .bleed-x on a fractional
   column is unsupported. */
.row > *.bleed-x {
  flex: 0 0 calc(100% + var(--page-gutter) * 2);
  padding-inline: 0;
}



/* ======================================================================
   HOW GUTTERS WORK — REAL gap + SELF-COMPENSATING COLUMNS
   ======================================================================

   THE PROBLEM WITH NAIVE gap
   --------------------------
   A plain `gap` adds space ON TOP of percentage columns:

     .col-2-3 (66.666%) + .col-1-3 (33.333%) + gap > 100%   → wraps

   THE FIX — COLUMNS PAY FOR THE GUTTER
   ------------------------------------
   Each column subtracts its own fair share of the gutter from its width:

     width = P% - gap × (1 - P)        where P is the column's fraction

   Worked example — 75/25 on a 1200px row with a 40px gap:

     .col-3-4 → 75% of 1200 - 40 × 0.25  =  900 - 10  =  890px
     .col-1-4 → 25% of 1200 - 40 × 0.75  =  300 - 30  =  270px
                                    890 + 40 + 270  =  1200px  ✓

   Any set of fractions summing to 100% fills the row exactly, and the
   leftover gutter is billed to each column in proportion to how much
   width it gives up — which is why the arithmetic always closes.

   WHY THIS BEATS THE OLD NEGATIVE-MARGIN TECHNIQUE
   ------------------------------------------------
     • Real empty space between columns, so column backgrounds, borders
       and cards actually separate (padding gutters cannot do this).
     • No negative margins, so a row can never overflow its parent and
       needs no padded container to sit in.
     • flex-basis stays a real width, so flex-wrap still works: .col-1-1
       claims its own line and N-up grids wrap naturally.
     • .trim becomes unnecessary (kept as a no-op for old markup).

   Vertical spacing between wrapped lines uses the same gap's row axis.
====================================================================== */


/* ======================================================================
   ROW ENGINE — CORE (LEAVE ALONE)
   ====================================================================== */
.row {
  display: flex;
  flex-wrap: wrap;

  /* Row-level spacing defaults (from project tokens) */
  --gap-x: var(--row-gap-x);   /* horizontal gutter between columns */
  --gap-y: var(--row-gap-y);   /* vertical gap between wrapped rows */
  --col-pad-x: var(--row-col-pad-x); /* optional inner padding inside each column */

  /* A REAL gap — genuine empty space between columns.
     Columns give the gutter back out of their own width (see the
     calc() bases below), so percentages never sum past 100%. */
  gap: var(--gap-y) var(--gap-x);
}

/* Optional inner padding, applied INSIDE the column's declared width.
   box-sizing:border-box means this insets content without changing the
   column's outer width — so no .trim compensation is ever needed. */
/* flex-basis 100% is a FALLBACK: a row child with no col-* class (Contao emits
   several of its own — .syndication, .back, and any unclassed element) would
   otherwise shrink-wrap to its content instead of taking a line. Every .col-*
   rule is later in source at equal specificity, so real columns still win. */
.row > * {
  flex: 0 1 100%;
  padding-inline: var(--col-pad-x);
  min-width: 0;
  box-sizing: border-box;
}

/* ----------------------------------------------------------------------
   CONTENT CONTAINMENT
   ----------------------------------------------------------------------
   `.row > *` sets min-width: 0 so columns can shrink below their content's
   intrinsic width — that is what keeps percentage columns honest. The
   side effect is that anything wider than the column (an uploaded image,
   an embed, an unbroken URL) will overflow it and can force horizontal
   scroll on the whole page.

   Scoped to the framework's own boxes: the layout engine created this
   exposure, so it contains it. A site-wide `img { max-width: 100% }`
   baseline, if wanted, belongs in the theme/base layer.
---------------------------------------------------------------------- */

.row > * img,
.row > * svg,
.row > * video,
.row > * canvas,
.row > * iframe,
.row > * embed,
.row > * object {
  max-width: 100%;
}

/* Preserve aspect ratio once max-width starts constraining the element */
.row > * img,
.row > * svg,
.row > * video {
  height: auto;
}

/* Long unbroken strings (URLs, tokens) wrap instead of pushing the column open */
.row > * {
  overflow-wrap: break-word;
}


/* DEPRECATED — .trim existed to cancel the old negative row margins.
   The gap engine has no negative margins, so this is now a no-op.
   Kept so existing markup does not break. Safe to delete later. */
.row.trim {
  margin-inline: 0;
}


/* ======================================================================
   COLUMN WIDTH UTILITIES — HOW flex: 0 0 X% WORKS
   ======================================================================

   flex is shorthand for:
     flex-grow | flex-shrink | flex-basis

   Example:
     flex: 0 0 50%;

   Means:
     - flex-grow:   0  → do NOT grow larger than the base size
     - flex-shrink: 0  → do NOT shrink smaller than the base size
     - flex-basis:  50% → base width is 50% of the row

   Why we use this:
     - Guarantees predictable column widths
     - Prevents stretching or squishing
     - Works cleanly with flex-wrap, gaps, and .trim
     - Avoids layout drift when spacing changes

   IMPORTANT:
     These classes control WIDTH ONLY.
     Prefer controlling spacing at the ROW level (gap utilities).
     Optional inner padding is available via the .pxc-* utilities.

====================================================================== */


/* ======================================================================
   COLUMN WIDTHS
   ====================================================================== */

/* AUDIT NOTE — WHY THESE ARE calc() AND NOT PLAIN PERCENTAGES
   Each column subtracts its own share of the gutter, so a set of
   fractions summing to 100% fits the row EXACTLY with the gap included.
   Plain percentages would sum to 100% + gap and wrap the last column.

   The multiplier is always (1 - P). Adding a new width means adding its
   pair: e.g. a 10% column → calc(10% - var(--gap-x) * 0.9).

   --gap-x must always carry a unit (0px, never 0) or the whole calc()
   is invalid and the column silently loses its width.
   ====================================================================== */
/* Each basis is  P% - gap × (1 - P)  — the column's own share of the
   gutter, subtracted from its width. See the gutter explainer above. */
/* .col divides whatever space is left between however many there are, so
   it behaves like a fraction and stacks with them at 600 (see below).
   .col-auto is an explicit opt-out — "size me to my content" — so it is
   deliberately left OUT of every stacking rule. An icon or a button beside
   a heading should stay beside it on a phone; if you want it to stack,
   use a fraction instead. */
.col       { flex: 1 1 0; }
.col-auto  { flex: 0 0 auto; }
.col-1-1   { flex: 0 0 100%; }                                    /* full width — takes its own line */
.col-3-4   { flex: 0 0 calc(75%     - var(--gap-x, 0px) * 0.25);  }
.col-2-3   { flex: 0 0 calc(200% / 3 - var(--gap-x, 0px) / 3);     }
.col-3-5   { flex: 0 0 calc(60%     - var(--gap-x, 0px) * 0.4);   }
.col-1-2   { flex: 0 0 calc(50%     - var(--gap-x, 0px) * 0.5);   }
.col-2-5   { flex: 0 0 calc(40%     - var(--gap-x, 0px) * 0.6);   }
.col-1-3   { flex: 0 0 calc(100% / 3 - var(--gap-x, 0px) * 2 / 3); }
.col-30    { flex: 0 0 calc(30%     - var(--gap-x, 0px) * 0.7);   }
.col-1-4   { flex: 0 0 calc(25%     - var(--gap-x, 0px) * 0.75);  }
.col-20    { flex: 0 0 calc(20%     - var(--gap-x, 0px) * 0.8);   }

/* Fixed ma-widths */

.single-sm,
.single-md,
.single-lg {
  max-width: var(--single-md); /* overridden per class */
  width: 100%;
}

.single-sm { max-width: var(--single-sm); }
.single-md { max-width: var(--single-md); }
.single-lg { max-width: var(--single-lg); }


/* ======================================================================
   GAP DECISION GUIDE (READ THIS BEFORE ADDING NEW SPACING)
   ======================================================================

   Use this guide to choose the RIGHT gap utility.
   Do not invent new gap values unless absolutely necessary.

   DEFAULT (most sections):
     gap-fluid
     → Responsive, balanced spacing across all screen sizes

   TIGHT / DENSE LAYOUTS:
     gap-fluid-sm  OR  gap-16
     → Icon grids, specs, compact UI sections

   SPACIOUS / PREMIUM SECTIONS:
     gap-fluid-lg  OR  gap-40 / gap-60
     → Hero sections, editorial layouts, feature showcases

   AXIS-SPECIFIC CONTROL:
     gap-x-0/16/24/40/60/fluid  and  gap-y-0/16/24/40/60/fluid
     → When horizontal and vertical rhythm should differ. Combine with a
       gap-* class: `row gap-24 gap-y-60` is 24 across, 60 down.

   PRECISION / MATCHING DESIGNS:
     gap-16 / gap-24 / gap-40
     → When spacing must match comps exactly

   RULE OF THUMB:
     If unsure, use `gap-fluid`.

====================================================================== */


/* ======================================================================
   GAP UTILITIES — EDIT AVAILABLE SIZES AS NEEDED
   ====================================================================== */
.gap-0  { --gap-x: var(--gutter-0);  --gap-y: var(--gutter-0); }
.gap-16 { --gap-x: var(--gutter-16); --gap-y: var(--gutter-16); }
.gap-24 { --gap-x: var(--gutter-24); --gap-y: var(--gutter-24); }
.gap-40 { --gap-x: var(--gutter-40); --gap-y: var(--gutter-40); }
.gap-60 { --gap-x: var(--gutter-60); --gap-y: var(--gutter-60); }

/* ======================================================================
   FLUID GAP UTILITIES (CLAMP-BASED)
   ======================================================================

   Use these when spacing should scale smoothly across screen sizes.
   Prefer these for marketing and editorial layouts.

   Tiers:
     - sm: tight, dense layouts
     - md: most sections  (.gap-fluid and .gap-fluid-md are the same thing)
     - lg: spacious, premium layouts
*/

.gap-fluid-sm {
  --gap-x: var(--gutter-fluid-sm);
  --gap-y: var(--gutter-fluid-sm);
}

/* .gap-fluid is the original name; .gap-fluid-md is an alias so the three
   tiers read consistently (sm / md / lg). Both are supported — existing
   markup using .gap-fluid keeps working. */
.gap-fluid,
.gap-fluid-md {
  --gap-x: var(--gutter-fluid-md);
  --gap-y: var(--gutter-fluid-md);
}

.gap-fluid-lg {
  --gap-x: var(--gutter-fluid-lg);
  --gap-y: var(--gutter-fluid-lg);
}

/* ======================================================================
   SINGLE-AXIS GAPS
   ======================================================================

   Use these when horizontal and vertical rhythm should differ — a card
   grid often wants tight gutters between columns but more separation
   between wrapped rows. Combine with a .gap-* class, or use alone.

     <div class="row gap-24 gap-y-60">   24 across, 60 down

   THE TWO AXES ARE NOT EQUIVALENT — worth understanding before reaching
   for gap-x-*:

     --gap-y  affects ONLY the space between wrapped lines. Nothing else
              reads it, so it can never disturb a column's width.

     --gap-x  is read TWICE: by the row's gap, and by every column's width
              calc (flex-basis: P% - gap × (1-P)). Changing it therefore
              resizes the columns to compensate — which is exactly what
              keeps a row summing to 100% — but it is the bigger lever.

   Both are safe; gap-y-* is simply the more contained of the two.
====================================================================== */

/* Horizontal only — the space between columns on a line */
.gap-x-0     { --gap-x: var(--gutter-0); }
.gap-x-16    { --gap-x: var(--gutter-16); }
.gap-x-24    { --gap-x: var(--gutter-24); }
.gap-x-40    { --gap-x: var(--gutter-40); }
.gap-x-60    { --gap-x: var(--gutter-60); }
.gap-x-fluid { --gap-x: var(--gutter-fluid-axis); }

/* Vertical only — the space between wrapped lines */
.gap-y-0     { --gap-y: var(--gutter-0); }
.gap-y-16    { --gap-y: var(--gutter-16); }
.gap-y-24    { --gap-y: var(--gutter-24); }
.gap-y-40    { --gap-y: var(--gutter-40); }
.gap-y-60    { --gap-y: var(--gutter-60); }
.gap-y-fluid { --gap-y: var(--gutter-fluid-axis); }


/* ======================================================================
   COLUMN INNER PADDING UTILITIES (optional inner inset)
   ====================================================================== */

.pxc-0  { --col-pad-x: var(--gutter-0); }
.pxc-16 { --col-pad-x: var(--gutter-16); }
.pxc-24 { --col-pad-x: var(--gutter-24); }
.pxc-40 { --col-pad-x: var(--gutter-40); }
.pxc-60 { --col-pad-x: var(--gutter-60); }

/* Fluid column padding (default) */
.pxc-fluid {
  --col-pad-x: var(--col-pad-fluid);
}

/* Fluid column padding — SMALL */
.pxc-fluid-sm {
  --col-pad-x: var(--col-pad-fluid-sm);
}

/* Fluid column padding — LARGE (optional) */
.pxc-fluid-lg {
  --col-pad-x: var(--col-pad-fluid-lg);
}


/* ======================================================================
   RESPONSIVE OVERRIDES — DESKTOP FIRST (MAX-WIDTH) • SIMPLIFIED
   ======================================================================

   SIMPLIFIED RESPONSIVE MODEL (CMS-FRIENDLY)
   -----------------------------------------
   We auto-stack fraction columns on smaller screens.

   - Desktop: .col-1-2, .col-2-3, etc. behave as expected
   - Tablet and down: fraction columns become full width (stacked)
   - No md:* / sm:* classes required

   ESCAPE HATCH
   ------------
   If you need a row to KEEP columns side-by-side on tablet/mobile,
   add .no-stack to the row:

     <div class="row no-stack">...</div>

====================================================================== */

/* Tablet and down: stack fraction columns by default */
@media (max-width: 992px) {

  /* Default behavior: stack, unless the row opts out */
  .row:not(.no-stack) > .col-1-3,
  .row:not(.no-stack) > .col-2-3,
  .row:not(.no-stack) > .col-3-4,
  .row:not(.no-stack) > .col-3-5,
  .row:not(.no-stack) > .col-2-5,
  .row:not(.no-stack) > .col-30,
  .row:not(.no-stack) > .col-20 {
    flex: 0 0 100%;
  }
  /* NOTE: .col-1-2 and .col-1-4 are intentionally NOT in this list.
     Both already sit at (or step through) a comfortable 2-up on tablet,
     so they hold there and stack at 600 instead — see the "COLUMNS THAT
     HOLD 2-UP ON TABLET" block below. Use .no-stack to keep any row
     side-by-side at every width. */
}


/* ======================================================================
   MIXED-RATIO PAIRS — EQUALIZE BEFORE STACKING
   ======================================================================

   Unequal two-column pairs (75/25, 66/33, 60/40) shouldn't jump straight
   from their ratio to a full stack — the minor column gets uncomfortably
   narrow on tablet. Instead they step through an even 50/50 (still 2-up)
   before stacking:

     ratio (desktop)  →  50/50 (≤992)  →  stacked (≤600)

   Detection is automatic via :has(): a row is treated as a mixed pair
   ONLY when it holds BOTH partners, so a 3-up of .col-1-3 or a 4-up of
   .col-1-4 is unaffected. Specificity (5 classes) beats the auto-stacker
   above (3), and the :not(.no-stack) guard keeps the escape hatch working.

   These target two-column pairs; adding a third column to the same row is
   unsupported (both partner selectors would still apply at 50%).
====================================================================== */

/* Tablet: equalize the pair to 50/50 (still side-by-side) */
@media (max-width: 992px) {
  .row:not(.no-stack):has(> .col-3-4):has(> .col-1-4) > .col-3-4,
  .row:not(.no-stack):has(> .col-3-4):has(> .col-1-4) > .col-1-4,
  .row:not(.no-stack):has(> .col-2-3):has(> .col-1-3) > .col-2-3,
  .row:not(.no-stack):has(> .col-2-3):has(> .col-1-3) > .col-1-3,
  .row:not(.no-stack):has(> .col-3-5):has(> .col-2-5) > .col-3-5,
  .row:not(.no-stack):has(> .col-3-5):has(> .col-2-5) > .col-2-5 {
    flex: 0 0 calc(50% - var(--gap-x, 0px) * 0.5);
  }
}

/* Mobile: now stack the pair to full width */
@media (max-width: 600px) {
  .row:not(.no-stack):has(> .col-3-4):has(> .col-1-4) > .col-3-4,
  .row:not(.no-stack):has(> .col-3-4):has(> .col-1-4) > .col-1-4,
  .row:not(.no-stack):has(> .col-2-3):has(> .col-1-3) > .col-2-3,
  .row:not(.no-stack):has(> .col-2-3):has(> .col-1-3) > .col-1-3,
  .row:not(.no-stack):has(> .col-3-5):has(> .col-2-5) > .col-3-5,
  .row:not(.no-stack):has(> .col-3-5):has(> .col-2-5) > .col-2-5 {
    flex: 0 0 100%;
  }
}

/* ======================================================================
   TYPOGRAPHY IS NOT THIS FILE'S JOB
   ======================================================================

   THE BOUNDARY
   ------------
   This framework owns LAYOUT: containers, rows, columns, gutters, and the
   spacing UTILITIES you apply to blocks (mb-*, mt-*, section-space).

   It does NOT own type. Paragraph, list, blockquote and heading rhythm —
   margins, line-height, size — belong to the site's typography layer
   (website.scss), which already defines them.

   WHY THERE IS NO RESET HERE ANY MORE
   -----------------------------------
   This file used to declare:

       p, ul, ol, blockquote { margin: 0; }

   …with a .rte flow rule meant to restore the rhythm. The .rte rule was
   commented out, so the reset destroyed spacing and replaced nothing.
   Worse, a bare `p` selector here ties on specificity (0,0,1) with the
   type layer's own `p` rule, so which one won depended purely on CSS
   load order in the Contao layout — the same markup could space
   correctly on one site and collapse on another.

   Removing the reset resolves that: the type layer is the single owner,
   and nothing here competes with it.

   IF YOU NEED TO ZERO A MARGIN, do it in the type layer, or use the
   spacing utilities on a wrapper — never re-add an element reset here.
====================================================================== */


/* ----------------------------------------------------------------------
   THE ONE TYPE-ADJACENT RULE THAT IS GENUINELY LAYOUT
   ----------------------------------------------------------------------

   A trailing bottom margin on the last element inside a column adds
   phantom space below the content but INSIDE the column box. That is
   invisible on plain text, but obvious once a column has a background
   or border (cards), where it reads as uneven padding.

   Scoped to this framework's own boxes rather than resetting elements
   globally, so the type layer keeps full control of rhythm everywhere
   else. (Same approach Bootstrap uses for card bodies.)
---------------------------------------------------------------------- */

/* Contao wraps rich text in a .rte div, so the column's own :last-child is that
   wrapper — whose trailing <p> keeps its margin. Reach one level further so the
   reset lands on the element that actually carries it. */
.row > * > :last-child,
.row > * > :last-child > :last-child {
  margin-bottom: 0;
}


/* ----------------------------------------------------------------------
   OPTIONAL FLOW VARIANTS
   ----------------------------------------------------------------------

   Opt-in rhythm overrides for rich-text wrappers. These are arguably
   typography too and are candidates to move to the type layer — kept
   here for now because existing markup may reference them.
---------------------------------------------------------------------- */

.rte-tight > * + * {
  margin-top: 0.75em;
}

.rte-loose > * + * {
  margin-top: 1.5em;
}


/* ----------------------------------------------------------------------
   GUIDANCE FOR THE TEAM
   ----------------------------------------------------------------------

   - Do NOT put margin utilities (mb-*, mt-*) on <p> tags — paragraph
     rhythm comes from the type layer.
   - DO use margin utilities on SECTIONS, BLOCKS and columns.

   Example (correct):

     <div class="mb-40">
       <p>Paragraph one</p>
       <p>Paragraph two</p>
     </div>

   Example (avoid):

     <p class="mb-24">Paragraph one</p>
     <p class="mb-24">Paragraph two</p>

====================================================================== */

/* Margin bottom */
.mb-0  { margin-bottom: var(--space-0); }
.mb-8  { margin-bottom: var(--space-8); }
.mb-12 { margin-bottom: var(--space-12); }
.mb-16 { margin-bottom: var(--space-16); }
.mb-24 { margin-bottom: var(--space-24); }
.mb-40 { margin-bottom: var(--space-40); }
.mb-60 { margin-bottom: var(--space-60); }
.mb-80 { margin-bottom: var(--space-80); }

/* Margin top */
.mt-0  { margin-top: var(--space-0); }
.mt-8  { margin-top: var(--space-8); }
.mt-12 { margin-top: var(--space-12); }
.mt-16 { margin-top: var(--space-16); }
.mt-24 { margin-top: var(--space-24); }
.mt-40 { margin-top: var(--space-40); }
.mt-60 { margin-top: var(--space-60); }
.mt-80 { margin-top: var(--space-80); }

/* Optional: margin block (top + bottom together) */
.my-24 { margin-block: var(--space-24); }
.my-60 { margin-block: var(--space-60); }


/* Use for consistent spacing between major sections */
.section-space { margin-block: var(--space-section); }
.section-space-top { margin-top: var(--space-section); }
.section-space-bottom { margin-bottom: var(--space-section); }


/* Optional: tighten default spacing on smaller screens (global)
   NOTE: Because we use clamp() utilities, you may not need these.
   Keep these only if your team wants more predictable rhythm. */
   
/* centering */
.center_text {
    text-align: center;
}

/* margin-INLINE only. The `margin: auto` shorthand also set the block axis,
   which silently zeroed every bottom/top margin utility on the same element
   (auto resolves to 0 in normal flow) and, on a flex column, opted the item
   out of cross-axis stretch so it no longer matched its siblings in height. */
.center_element {
    margin-inline: auto;
}

.hor_center {
    justify-content: center;
}


.vert_center {
    align-items: center;
}

.vert_top {
    align-items: flex-start;
}

.vert_bottom {
    align-items: flex-end;
}


/* Element / text alignment (Toolbox: align-left / align-right) */
.align-left,
.align-left img {
    text-align: left;
    margin-inline: 0 auto;
}

.align-right,
.align-right img {
    text-align: right;
    margin-inline: auto 0;
}


@media (max-width: 768px) {
  :root {
    --row-gap-x: var(--gutter-24);
    --row-gap-y: var(--gutter-24);
  }
}

/* ----------------------------------------------------------------------
   MOBILE COLUMN ORDER
   ----------------------------------------------------------------------
   Rows read left-to-right on desktop but top-to-bottom once stacked, so a
   "text beside image" row can end up with the wrong one first on a phone.
   .mobile_col_reverse flips the stacking order without touching the desktop
   layout or the source order (which stays correct for screen readers).
---------------------------------------------------------------------- */
.mobile_col_reverse {
  flex-direction: row;
}

@media (max-width: 600px) {
  .mobile_col_reverse {
    flex-direction: column-reverse;
  }
}


@media (max-width: 480px) {
  :root {
    --row-gap-x: var(--gutter-16);
    --row-gap-y: var(--gutter-16);
  }
}


/* ======================================================================
   COLUMNS THAT HOLD 2-UP ON TABLET  (→ 2 → 1)
   ======================================================================

   EVERY two-column layout now follows the SAME ramp: it reaches an even
   50/50 on tablet, and only stacks on phones.

     .col-1-2 pair   50/50  (> 992)  →  50/50  (≤ 992)  →  1-up  (≤ 600)
     75/25 pair      75/25  (> 992)  →  50/50  (≤ 992)  →  1-up  (≤ 600)
     66/33 pair      66/33  (> 992)  →  50/50  (≤ 992)  →  1-up  (≤ 600)
     60/40 pair      60/40  (> 992)  →  50/50  (≤ 992)  →  1-up  (≤ 600)
     .col-1-4 grid   4-up   (> 992)  →  2-up   (≤ 992)  →  1-up  (≤ 600)

   Previously .col-1-2 sat in the blanket 992 stacker, so a plain 50/50
   stacked EARLIER than a 75/25 — the simpler layout collapsed sooner,
   which is backwards. Both now hold 2-up to 600.

   This is WHY .col-1-2 and .col-1-4 are left out of the blanket 992
   auto-stacker above. The :not(.no-stack) guard keeps the escape hatch
   working: a .row.no-stack holds its columns side-by-side at every width.

   Thirds (.col-1-3 ×3) still stack at 992 — three columns cannot reach an
   even 2-up without orphaning one, so they go straight to 1-up.
====================================================================== */
@media (max-width: 992px) {
  /* A quarter promotes to a half on tablet — UNLESS the row also holds a
     .col-1-2, which is already 50%. Three 50% items fill one line exactly
     and orphan the third at half width, so those rows stack instead. */
  .row:not(.no-stack):not(:has(> .col-1-2)) > .col-1-4 {
    flex: 0 0 calc(50% - var(--gap-x, 0px) * 0.5);
  }
  .row:not(.no-stack):has(> .col-1-2) > .col-1-4,
  .row:not(.no-stack):has(> .col-1-4) > .col-1-2 { flex: 0 0 100%; }
}

@media (max-width: 600px) {
  .row:not(.no-stack) > .col-1-2,
  .row:not(.no-stack) > .col-1-4,
  .row:not(.no-stack) > .col { flex: 0 0 100%; }
}
