/**
 * QGDS two-column content layout.
 *
 * Layout + grid come from QGDS / Bootstrap (see inc/qgds-content-layout.html.twig);
 * this file only adds the behaviours QGDS does not: a sticky side-navigation
 * column on desktop, a readability cap on the main content measure, and a
 * scroll offset so in-page anchor jumps don't land flush against the viewport
 * top (or under the Drupal admin toolbar for logged-in editors).
 *
 * The QGDS site header is NOT sticky (it scrolls away with the page — see
 * css/qgds/qrida.css), so the sticky nav only needs a small offset from the
 * viewport top. Editors get Drupal's fixed admin toolbar, so the offset is
 * bumped under body.toolbar-fixed.
 */

:root {
  /* Offset used for both the sticky side nav and anchor scroll-margin. */
  --qrida-content-sticky-offset: 1.5rem;
  /* Comfortable reading measure for the single-column body, which has no side
     navigation beside it and so is centred in the container. */
  --qrida-content-measure: 48rem;
  /* Reading measure for the text inside the two-column body. Applied to the
     rich-text regions rather than to the column, so the components that carry
     their own grid keep the column width.

     640px at the default root size, which is the line the previous build
     produced: the measure does not rise here, the column does. Sampling 16
     comparable body paragraphs across six pages, 640px lines run 69 to 83
     characters of the 16px body face (median 77) against 77 to 88 (median 83)
     at 44rem, so 40rem is the widest value that keeps a typical line inside the
     80 characters WCAG 2.1 SC 1.4.8 asks for. The current site runs about 148. */
  --qrida-reading-measure: 40rem;
  /* Guard cap on the two-column body. The QGDS container itself stops at
     1376px, so the col-lg-9 track is at most 976px and this never bites today;
     it is here so a wider container cannot let the body run away, and the auto
     margins below keep any residual balanced rather than dumped on the right. */
  --qrida-content-column: 61rem;
  /* Measure for a listing, which is scanned rather than read line by line, so
     it takes a wider column than prose. 832px at the default root size, where
     the current site sits at 837px. */
  --qrida-listing-measure: 52rem;
}

/* Drupal admin toolbar is fixed for editors: clear it. */
body.toolbar-fixed {
  --qrida-content-sticky-offset: 5rem;
}

/* ---------------------------------------------------------------------------
 * Sticky side navigation (desktop only). On mobile the nav stacks above the
 * content (DOM order) and stays in flow.
 * ------------------------------------------------------------------------- */

@media (min-width: 992px) {
  .qld-content-layout__nav .qld-side-navigation {
    position: sticky;
    top: var(--qrida-content-sticky-offset);
    /* Keep a very long TOC scrollable rather than clipped off-screen. */
    max-height: calc(100vh - var(--qrida-content-sticky-offset) - 1.5rem);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}

/* ---------------------------------------------------------------------------
 * Anchor landings. The preprocess injects ids on the body <h2>s; give them a
 * scroll offset so the heading isn't flush with the top of the viewport.
 * ------------------------------------------------------------------------- */

.qld-content-layout .qld-content-body :where(h2, h3, h4)[id] {
  scroll-margin-top: var(--qrida-content-sticky-offset);
}

/* ---------------------------------------------------------------------------
 * Readability.
 *
 * Two things were being asked of one max-width, and they pull apart. Prose
 * wants a capped line. The components in the same body (image-and-text decks,
 * card listings, accordions, tiles) want the column. Capping the column served
 * the prose and starved the components: with col-lg-8 leaving a twelfth column
 * empty and a 768px cap sitting flush left inside an 896px column, 288px of a
 * 1440px page sat blank to the right of the text while the intro deck wrapped
 * one sentence over seven lines in 304px.
 *
 * So the two jobs are now split. The column fills its grid track, which puts
 * its content edge on the page gutter and mirrors the 64px to the left of the
 * side nav. The reading measure moves onto the rich-text regions inside it.
 * ------------------------------------------------------------------------- */

.qld-content-layout .qld-content-body {
  max-width: var(--qrida-content-measure);
  /* Establish a query container so the paragraph components below can respond
     to the measure rather than to the viewport. See the note on @container. */
  container-type: inline-size;
  container-name: qrida-measure;
}

.qld-content-layout--single .qld-content-body {
  margin-inline: auto;
}

/* Two-column layout: the body takes the whole col-lg-9 track. */
.qld-content-layout--split .qld-content-body {
  max-width: var(--qrida-content-column);
  margin-inline: auto;
}

/* Reading measure, applied to the text rather than to the layout. .text-content
   is the theme's rich-text field wrapper and .field--type-webform the webform
   field wrapper, so this catches prose, headings and form controls and leaves
   grids, images, cards and accordions on the column. It is a max-width, so
   anything already narrower than the measure (deck copy, card bodies, the
   text-and-buttons blurb) is untouched at every viewport. */
.qld-content-layout--split .qld-content-body :is(.text-content, .field--type-webform) {
  max-width: var(--qrida-reading-measure);
}

/* A few components emit body copy as a bare <p> rather than through
   .text-content, which would otherwise make the line length a function of which
   component happened to wrap the text: 816px in a text-and-buttons column on
   /program/rural-agricultural-development-grants, 944px in an accordion lead-in
   on /disaster-recovery-connect. Give those the same line.

   Only <p>. Headings are left out on purpose, because they are not reading
   lines: an accordion header spans its control row, and the section heading
   over a card grid is centred on the grid. Lists are left out because the wide
   ones are layout lists (ul.nav-pills tab strips, ul.people-list-ul), not
   prose; the prose ones sit inside .text-content and are already capped. */
.qld-content-layout--split .qld-content-body p {
  max-width: var(--qrida-reading-measure);
}

/* Listing and tool pages (the FAQ and program listings, the calculators page)
   are built from components that emit their own container and grid and were
   designed to span the page, as they still do on the current site. They take
   neither the reading measure nor the measure query container, so their
   internal col-* splits resolve against the page the way they always have. */
.qld-content-layout--wide .qld-content-body {
  max-width: none;
  container-type: normal;
  container-name: none;
}

/* The FAQ listing is the one full-width component that is a single column of
   long text rows rather than a grid, so the page width it gets here would be a
   worse measure than either the previous build or the current site. Cap the
   wrapper, which carries the heading, the program filter and the accordion, so
   all three share one measure, and centre it under the full-width sections
   above. A max-width, so the narrow-viewport behaviour is unchanged. */
.qld-content-layout--wide .paragraph-all-faqs .faqs-wrapper {
  max-width: var(--qrida-listing-measure);
  margin-inline: auto;
}

/* ---------------------------------------------------------------------------
 * Grids inside the measure.
 *
 * Bootstrap's col-* breakpoints key off the VIEWPORT, but this column is capped
 * at --qrida-content-measure however wide the window is. On a 1440px screen the
 * xl split in paragraph--faqs--default.html.twig (col-xl-4 + col-xl-7
 * offset-xl-1) therefore resolves against 768px, giving a 213px title column
 * that wraps "Frequently asked questions" onto three lines beside a 395px
 * accordion. Fifteen paragraph templates carry the same latent problem, so it
 * is fixed once here rather than per template.
 *
 * At today's 48rem measure this query always matches, so the effect is
 * currently the same as stacking unconditionally. It earns its keep only if the
 * measure is ever widened past lg, at which point real two-column splits come
 * back on their own. That is intended, not accidental.
 * ------------------------------------------------------------------------- */

@container qrida-measure (max-width: 61.9375rem) {
  .qld-content-body .paragraph .row > [class*="col-xl-"],
  .qld-content-body .paragraph .row > [class*="col-lg-"] {
    width: 100%;
    flex: 0 0 auto;
    margin-left: 0; /* neutralises offset-xl-1 and friends */
  }
}

/* Paragraph components emit their own .container, which lands inside the
   already-guttered content body and applies a full gutter (32px) where a nested
   container should apply a half gutter. The .row's -1rem margin then leaves the
   row 736px wide inside a 768px measure. Restore the half gutter so rows span
   the full measure; the columns keep their own 1rem padding, so text rhythm is
   unchanged.

   Every nested container, not only `.paragraph > .container`. Half the
   components in this body do not put the `paragraph` class on the element that
   holds the container: the image-and-text deck wrapper is `.paragraph-image-text`
   with no bare `paragraph` class, and the rich-text sections on
   /fisheries-support and /feedback-complaints sit the other way round, with the
   container wrapping the paragraph as a direct child of the body. Those kept
   the 32px gutter, so their prose sat at x=432 while the tiles, accordion and
   text-info sections on the same page sat at 416: one of the two roots of the
   ragged left edge, and the reason /fisheries-support showed three distinct
   left edges and /feedback-complaints four. */
.qld-content-layout:not(.qld-content-layout--wide) .qld-content-body .container {
  max-width: none;
  width: 100%;
  padding-inline: var(--space-lg);
}

/* Below the two-column breakpoint there is only one gutter's worth of room.
   The page container already spends 16px of a 390px screen on each side, and
   the nested container spent a second 16px on top of it, so body copy ran
   32..358 (326px) where the current site runs 18..372 (354px), and a list
   inside a panel came out at 230px, about 28 characters. The nested gutter is
   the one to drop: the page's own is what keeps text off the screen edge.

   The exceptions are the components that paint a surface. For those the nested
   container's padding is not a gutter at all, it is the panel's inset: without
   it the grey tiles panel on /program/first-start-loan would seat its cards on
   its own background edge. The list is the section-rhythm file's set of
   self-spacing components plus .paragraph-tiles, which is every paragraph
   wrapper in the theme that carries a background. */
@media (max-width: 991.98px) {
  .qld-content-layout:not(.qld-content-layout--wide)
    .qld-content-body
    :not(
      .paragraph-tiles,
      .paragraph-intro,
      .paragraph-text-cards,
      .paragraph-carousel-image,
      .paragraph-carousel-video
    )
    > .container,
  .qld-content-layout:not(.qld-content-layout--wide) .qld-content-body > .container {
    padding-inline: 0;
  }
}

/* ---------------------------------------------------------------------------
 * "Last updated" line.
 *
 * page.html.twig emits .qld-content-dates-wrap after both page.content and
 * page.content_below. It is therefore not necessarily adjacent to the layout:
 * a view or block in content_below can sit between them. Determine the layout
 * state from their shared .qld-main-content parent instead of relying on an
 * adjacent-sibling selector, then align the date with the applicable content
 * measure.
 *
 * The offset is the nav column plus the insets between the grid track and the
 * text: 25% of the row, then 1rem of column padding, 1rem of the component
 * container and 1rem of its column, which is 3rem. Two fixed corrections apply
 * to that. The percentage resolves against the wrap's content box, which is
 * 2rem narrower than the row (the row carries -1rem margins), so 25% of it
 * falls 0.5rem short; and the wrap's own left edge sits 1rem further in than
 * the row's. 3rem + 0.5rem - 1rem gives the 2.5rem constant. Both corrections
 * are fixed, so this lands on the body text exactly at every width from lg up.
 * ------------------------------------------------------------------------- */

/* Corrected selector, and why the previous one never fired: page.html.twig
 * emits .qld-content-dates-wrap after both page.content and page.content_below,
 * so it is not necessarily the layout's next sibling. Anything rendered into
 * content_below sits between them, and on this site something always does.
 * Measured on program, page, FAQ and contact pages, the adjacent-sibling form
 * matched nothing at all, so every rule below it was dead and the date stamp
 * sat at the page gutter under the side navigation on every node page.
 * Reading the layout state from the shared .qld-main-content parent instead
 * does not care what comes between them. */

@media (min-width: 992px) {
  .qld-main-content:has(.qld-content-layout--split) > .qld-content-dates-wrap .qld-content-dates {
    margin-inline-start: calc(25% + 2.5rem);
  }

  /* Single-column pages centre the body, so centre the line under it too. The
     measure less 4rem is the body's own two nested gutters (the component
     container and its column), which is where the text starts. */
  .qld-main-content:has(.qld-content-layout--single) > .qld-content-dates-wrap .qld-content-dates {
    max-width: calc(var(--qrida-content-measure) - 4rem);
    margin-inline: auto;
  }

  /* The FAQ listing is the one wide page whose content is capped and centred
     rather than run to the page gutter (see the .faqs-wrapper rule above), so
     the line follows it. Every other wide page already runs its content to the
     container edge, where the line sits by default. */
  .qld-main-content:has(.qld-content-layout--wide .paragraph-all-faqs) > .qld-content-dates-wrap .qld-content-dates {
    max-width: var(--qrida-listing-measure);
    margin-inline: auto;
  }
}

/* ---------------------------------------------------------------------------
 * Pasted typography.
 *
 * 67 published pages set their body copy in the wrong typeface, because the
 * text was pasted out of Word or Outlook and carried the inline font-family,
 * font-size and color with it. Measured in the browser, /news/12m-flood-
 * assistance-queensland-primary-producers-small-business alone renders 82 runs
 * of Calibri and Arial at 14.67px and 15.33px, next to the design system's Noto
 * Sans at 16px, so the typeface visibly changes mid-page and the smallest of
 * the pasted sizes is under the 16px the rest of the site sets.
 *
 * Re-pasting all of it as plain text is the editorial fix, but 195 pages carry
 * Word artefacts, so the theme has to hold the line meanwhile. An inline style
 * beats an author rule, so these have to carry !important to reach it; they are
 * scoped to the body column so nothing the theme itself sets inline (banner
 * background images, the carousel) is in range.
 *
 * Only the three properties that were pasted. Inline layout, spacing and
 * background styles are left alone: editors do use them deliberately, and the
 * complaint is about type, not about markup in general.
 * ------------------------------------------------------------------------- */

/* The typeface belongs to the design system on every element, headings and
   captions included. */
.qld-content-body [style*="font-family"] {
  font-family: inherit !important;
}

/* Size only on flow text. A heading with an inline size is still a heading, and
   inheriting here would collapse it to the size of the paragraph under it. */
.qld-content-body
  :is(p, span, li, td, th, div, a, strong, em, b, i, small, blockquote)[style*="font-size"] {
  font-size: inherit !important;
}

/* Colour on flow text, back to the body token rather than to inherit, so a run
   nested inside another coloured run still lands on the design value.
 *
 * Two carve-outs. Anything that also sets a background inline is a deliberate
 * callout box, where the pair has to stay together or the text can end up
 * invisible on its own background. And anything inside a link keeps the link
 * colour: a pasted <span style="color:#0000ff"> inside an <a> is the link's own
 * styling arriving the long way round, and neutralising it would leave a link
 * that reads as plain text. */
.qld-content-body
  :is(p, span, li, td, th, div, strong, em, b, i, blockquote)[style*="color"]:not(
    [style*="background"],
    a *
  ) {
  color: var(--qld-body-color, #353535) !important;
}

/* A link that was pasted with its old colour on it. blue and #5959ff (an email
   address on /node/1095) both sit outside the palette, and blue in particular
   is the one colour a reader reads as "link I have not visited" rather than as
   this site's link. Buttons keep whatever they were given: an inline colour on
   a .btn is deliberate, not a paste artefact. */
.qld-content-body a[style*="color"]:not([style*="background"], .btn) {
  color: var(--qld-link-color, #005eb8) !important;
}
