/*! PolyFishCSS-Utilities.css | v1.0.0-rc.2-rc.1-rc.1-rc.1-rc.1-rc.1 | polyfish.org | MIT
 *
 * Single-purpose helpers for spacing, alignment, colour and visibility,
 * plus the scroll reveal and print rules. Optional: the first file to drop if
 * your project already has utilities of its own. Nothing depends on it.
 *
 * Depends on: PolyFishCSS-Core.css (reads its tokens).
 * Load order: Core -> Headers -> Content -> Footers -> Utilities.
 *
 * CONTENTS
 *   1. Spacing
 *   2. Gap
 *   3. Display and flow
 *   4. Text
 *   5. Colour
 *   6. Shape
 *   7. Scroll reveal
 *   8. Responsive visibility and print
 *
 * CONVENTIONS
 *   .pf-block / .pf-block__element / .pf-block--modifier.
 *   Components read role tokens, never palette values. See docs/tokens.
 *
 * SCOPE
 *   This is deliberately small - roughly sixty classes, not six thousand. It
 *   exists to stop you writing one-off rules for a 1rem margin, not to let you
 *   build a page out of class strings. If you find a component being assembled
 *   entirely from these, it wants to be a component.
 * 
 * LOAD LAST
 *   Several helpers tie with component rules on specificity (both a single
 *   class), so the cascade decides. Load this file after the others or a
 *   .pf-mt-0 will quietly lose to a component's own margin.
 */

@layer polyfish.core, polyfish.grid, polyfish.headers, polyfish.content, polyfish.forms, polyfish.components, polyfish.footers, polyfish.space, polyfish.effects, polyfish.utilities, polyfish.fonts, polyfish.compat;

/* ==========================================================================
   CASCADE LAYER
   ==========================================================================
   Everything below sits in `polyfish.utilities`. The layer order is declared in
   every module, so it holds no matter which order you link the files in.

   Why this matters to you: unlayered CSS beats layered CSS regardless of
   specificity. Your own stylesheet overrides any framework rule with a plain
   class selector — no `!important`, no specificity arms race, no worrying
   about whether Utilities loaded last.

     <link rel="stylesheet" href="PolyFishCSS-Core.min.css">
     <link rel="stylesheet" href="my-app.css">   <!-- wins, always -->

   If you want your CSS layered too, name a layer after the framework's:

     @layer polyfish, app;
     @layer app { .card { background: rebeccapurple; } }
   ========================================================================== */

@layer polyfish.utilities {
  /* ==========================================================================
     #SPACING LIVES IN THE SPACE MODULE
     ==========================================================================
     Padding, margin, gap and grid-track utilities used to be here. They moved
     to PolyFishCSS-Space.css when that surface grew past a handful of classes,
     and they are not duplicated back: two modules declaring the same class is
     a maintenance trap, because the day they stop agreeing is the day someone
     spends an afternoon in devtools.
  
     If you load Utilities you almost certainly want Space too.
     ========================================================================== */
  
  /* Display and flow */
  .pf-block { display: block; }
  .pf-inline-block { display: inline-block; }
  .pf-flex { display: flex; }
  .pf-inline-flex { display: inline-flex; }
  .pf-grid-d { display: grid; }
  .pf-none { display: none; }
  
  .pf-wrap { flex-wrap: wrap; }
  .pf-nowrap { flex-wrap: nowrap; }
  /* Named -flex-col rather than -col: Grid owns .pf-col for its twelve-column
     system, and two modules cannot claim the same class. */
  .pf-flex-col { flex-direction: column; }
  .pf-flex-row { flex-direction: row; }
  .pf-items-start { align-items: flex-start; }
  .pf-items-center { align-items: center; }
  .pf-items-end { align-items: flex-end; }
  .pf-justify-start { justify-content: flex-start; }
  .pf-justify-center { justify-content: center; }
  .pf-justify-between { justify-content: space-between; }
  .pf-justify-end { justify-content: flex-end; }
  .pf-grow { flex: 1 1 auto; }
  .pf-shrink-0 { flex: none; }
  
  /* Text */
  .pf-text-start { text-align: start; }
  .pf-text-center { text-align: center; }
  .pf-text-end { text-align: end; }
  .pf-text-xs { font-size: var(--pf-text-xs); }
  .pf-text-sm { font-size: var(--pf-text-sm); }
  .pf-text-lg { font-size: var(--pf-text-lg); }
  .pf-text-xl { font-size: var(--pf-text-xl); }
  /* The display steps had tokens but no utilities, so a heading that needed one
     had to reach for an inline style — which the CSP forbids. */
  .pf-text-2xl { font-size: var(--pf-text-2xl); }
  .pf-text-3xl { font-size: var(--pf-text-3xl); }
  .pf-text-4xl { font-size: var(--pf-text-4xl); }
  .pf-text-5xl { font-size: var(--pf-text-5xl); }
  .pf-display { font-family: var(--pf-font-display); letter-spacing: -0.02em; }
  .pf-mono { font-family: var(--pf-font-mono); }
  .pf-weight-500 { font-weight: 500; }
  .pf-weight-600 { font-weight: 600; }
  .pf-weight-700 { font-weight: 700; }
  .pf-balance { text-wrap: balance; }
  .pf-measure { max-width: var(--pf-measure); }
  .pf-measure-none { max-width: none; }
  
  /* Colour */
  .pf-fg-accent { color: var(--pf-accent); }
  .pf-fg-accent-2 { color: var(--pf-accent-2); }
  .pf-fg-paper { color: var(--pf-base-50); }
  .pf-fg-muted { color: var(--pf-text-muted); }
  .pf-bg-deep { background: var(--pf-base-900); }
  .pf-bg-base { background: var(--pf-base-800); }
  .pf-bg-surface { background: var(--pf-surface); }
  .pf-bg-accent-wash { background: var(--pf-hue-1-wash); }
  .pf-bg-accent-2-wash { background: var(--pf-hue-2-wash); }
  .pf-bg-mesh { background-image: var(--pf-mesh); }
  
  /* Sticky offsets, for sidebars and toolbars. --top-lg clears a sticky nav. */
  .pf-sticky { position: sticky; align-self: start; }
  .pf-sticky-top { top: 2rem; }
  .pf-sticky-nav { top: 6rem; }
  
  /* Shape */
  .pf-round { border-radius: var(--pf-radius); }
  .pf-round-lg { border-radius: var(--pf-radius-lg); }
  .pf-round-pill { border-radius: var(--pf-radius-pill); }
  .pf-bordered { border: 1px solid var(--pf-border); }
  .pf-bordered-accent { border: 1px solid var(--pf-border-strong); }
  .pf-lift { box-shadow: var(--pf-lift); }
  .pf-overflow-hidden { overflow: hidden; }
  
  
  /* ==========================================================================
     #SIZING, POSITION AND LAYERS
     ========================================================================== */
  
  /**
   * The helpers a layout reaches for once and would otherwise get a one-off
   * rule: widths as fractions of the container, a few heights, position and
   * z-index, overflow, object-fit and aspect-ratio.
   */
  .pf-w-full { width: 100%; }
  .pf-w-auto { width: auto; }
  .pf-w-half { width: 50%; }
  .pf-w-min { width: min-content; }
  .pf-w-max { width: max-content; }
  .pf-w-fit { width: fit-content; }
  .pf-max-w-none { max-width: none; }
  .pf-max-w-xs { max-width: 20rem; }
  .pf-max-w-sm { max-width: 24rem; }
  .pf-max-w-md { max-width: 32rem; }
  .pf-max-w-lg { max-width: 42rem; }
  .pf-max-w-xl { max-width: 56rem; }
  
  .pf-h-full { height: 100%; }
  .pf-h-screen { height: 100vh; height: 100dvh; }
  .pf-min-h-0 { min-height: 0; }
  .pf-min-w-0 { min-width: 0; }
  
  .pf-relative { position: relative; }
  .pf-absolute { position: absolute; }
  .pf-fixed { position: fixed; }
  .pf-static { position: static; }
  .pf-inset-0 { inset: 0; }
  .pf-top-0 { top: 0; }
  .pf-right-0 { inset-inline-end: 0; }
  .pf-bottom-0 { bottom: 0; }
  .pf-left-0 { inset-inline-start: 0; }
  
  .pf-z-0 { z-index: 0; }
  .pf-z-10 { z-index: 10; }
  .pf-z-20 { z-index: 20; }
  .pf-z-40 { z-index: 40; }
  .pf-z-60 { z-index: 60; }
  
  .pf-overflow-auto { overflow: auto; }
  .pf-overflow-x-auto { overflow-x: auto; }
  .pf-overflow-visible { overflow: visible; }
  
  .pf-object-cover { object-fit: cover; }
  .pf-object-contain { object-fit: contain; }
  .pf-aspect-square { aspect-ratio: 1 / 1; }
  .pf-aspect-video { aspect-ratio: 16 / 9; }
  
  /* ==========================================================================
     #TYPOGRAPHY HELPERS
     ========================================================================== */
  
  .pf-uppercase { text-transform: uppercase; letter-spacing: 0.06em; }
  .pf-capitalize { text-transform: capitalize; }
  .pf-normal-case { text-transform: none; }
  .pf-underline { text-decoration: underline; text-underline-offset: 0.22em; }
  .pf-no-underline { text-decoration: none; }
  .pf-italic { font-style: italic; }
  .pf-tabular { font-variant-numeric: tabular-nums; }
  .pf-leading-tight { line-height: var(--pf-leading-tight); }
  .pf-leading-snug { line-height: var(--pf-leading-snug); }
  .pf-leading-normal { line-height: var(--pf-leading); }
  .pf-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  
  /**
   * Line clamp. -webkit-box is still the interoperable way to do this; the
   * standard `line-clamp` is listed first so browsers that support it use it.
   */
  .pf-clamp-2,
  .pf-clamp-3 { display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden; }
  .pf-clamp-2 { line-clamp: 2; -webkit-line-clamp: 2; }
  .pf-clamp-3 { line-clamp: 3; -webkit-line-clamp: 3; }
  
  /* ==========================================================================
     #BORDERS, OPACITY, CURSOR
     ========================================================================== */
  
  .pf-border-0 { border: 0; }
  .pf-border-t { border-top: 1px solid var(--pf-border); }
  .pf-border-b { border-bottom: 1px solid var(--pf-border); }
  .pf-round-none { border-radius: 0; }
  .pf-round-sm { border-radius: var(--pf-radius-sm); }
  .pf-circle { border-radius: 50%; }
  
  .pf-opacity-50 { opacity: 0.5; }
  .pf-opacity-75 { opacity: 0.75; }
  .pf-cursor-pointer { cursor: pointer; }
  .pf-select-none { user-select: none; }
  .pf-pointer-none { pointer-events: none; }
  
  /* ==========================================================================
     #DEPTH, MOTION AND TRANSFORMS
     ========================================================================== */
  
  .pf-shadow-sm { box-shadow: var(--pf-shadow-sm); }
  .pf-shadow { box-shadow: var(--pf-shadow); }
  .pf-shadow-lg { box-shadow: var(--pf-lift); }
  .pf-shadow-none { box-shadow: none; }
  .pf-ring { box-shadow: var(--pf-ring); }
  
  .pf-transition { transition: all var(--pf-speed) var(--pf-ease); }
  .pf-transition-colors {
    transition: background-color var(--pf-speed) var(--pf-ease),
      border-color var(--pf-speed) var(--pf-ease), color var(--pf-speed) var(--pf-ease);
  }
  
  /**
   * Hover affordances. Each pairs a transform with a transition and is scoped
   * to (hover: hover), so a touch device does not get a state it can only enter
   * by pressing and holding.
   */
  @media (hover: hover) {
    .pf-hover-lift { transition: transform var(--pf-speed) var(--pf-ease), box-shadow var(--pf-speed) var(--pf-ease); }
    .pf-hover-lift:hover { transform: translateY(-2px); box-shadow: var(--pf-shadow); }
    .pf-hover-border { transition: border-color var(--pf-speed) var(--pf-ease); }
    .pf-hover-border:hover { border-color: var(--pf-border-strong); }
    .pf-hover-bright { transition: opacity var(--pf-speed) var(--pf-ease); }
    .pf-hover-bright:hover { opacity: 1; }
  }
  
  /* ==========================================================================
     #DIVIDE AND RULES
     ========================================================================== */
  
  /**
   * A border between children rather than around them. Saves the
   * :last-child override that every hand-written list rule ends up needing.
   */
  .pf-divide-y > * + * { border-top: 1px solid var(--pf-border); }
  .pf-divide-x > * + * { border-inline-start: 1px solid var(--pf-border); }
  .pf-vr {
    width: 1px;
    align-self: stretch;
    min-height: 1.5em;
    background: var(--pf-border);
    flex: none;
  }
  
  /* ==========================================================================
     #CONTAINER QUERIES
     ========================================================================== */
  
  /**
   * A component in a narrow sidebar and the same component in a wide main
   * column are the same width problem, and a viewport media query cannot tell
   * them apart. Container queries can.
   *
   *   <div class="pf-container-q">
   *     <article class="pf-card pf-cq-row"> ... </article>
   *   </div>
   *
   * .pf-cq-row lays the card out horizontally once ITS OWN container is at
   * least 30rem wide, wherever that container sits on the page. This is the
   * piece that makes a modular framework genuinely reusable: a component stops
   * needing to know where it was dropped.
   *
   * Support is Chrome 105, Safari 16, Firefox 110 and up. Older engines keep
   * the stacked layout, which is the correct fallback rather than a broken one.
   */
  .pf-container-q { container-type: inline-size; }
  
  @container (min-width: 30rem) {
    .pf-cq-row { flex-direction: row; align-items: center; }
    .pf-cq-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .pf-cq-side { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
    .pf-cq-show { display: initial; }
    .pf-cq-hide { display: none; }
  }
  @container (min-width: 48rem) {
    .pf-cq-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .pf-cq-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
  }
  
  /* ==========================================================================
     #RESPONSIVE VARIANTS
     ========================================================================== */
  
  /**
   * Mobile first, Bootstrap-style infixes rather than Tailwind's escaped colon:
   * .pf-md-hidden applies from 768px up, .pf-hidden applies everywhere.
   *
   *   sm 576px   md 768px   lg 992px   xl 1200px
   *
   * Only the properties that genuinely change per breakpoint are generated -
   * display, direction, alignment, text alignment, width and order. Generating
   * the whole utility set at five breakpoints is how a stylesheet reaches
   * 300 KB, and a build step becomes mandatory to trim it again.
   */@media (min-width: 576px) {
    .pf-sm-hidden { display: none; }
    .pf-sm-block { display: block; }
    .pf-sm-flex { display: flex; }
    .pf-sm-grid-d { display: grid; }
    .pf-sm-inline-flex { display: inline-flex; }
    .pf-sm-flex-col { flex-direction: column; }
    .pf-sm-flex-row { flex-direction: row; }
    .pf-sm-text-left { text-align: start; }
    .pf-sm-text-center { text-align: center; }
    .pf-sm-text-right { text-align: end; }
    .pf-sm-items-center { align-items: center; }
    .pf-sm-items-start { align-items: flex-start; }
    .pf-sm-justify-between { justify-content: space-between; }
    .pf-sm-justify-center { justify-content: center; }
    .pf-sm-w-full { width: 100%; }
    .pf-sm-w-auto { width: auto; }
    .pf-sm-order-first { order: -1; }
    .pf-sm-order-last { order: 99; }
    .pf-sm-span-full { grid-column: 1 / -1; }
  }
  @media (min-width: 768px) {
    .pf-md-hidden { display: none; }
    .pf-md-block { display: block; }
    .pf-md-flex { display: flex; }
    .pf-md-grid-d { display: grid; }
    .pf-md-inline-flex { display: inline-flex; }
    .pf-md-flex-col { flex-direction: column; }
    .pf-md-flex-row { flex-direction: row; }
    .pf-md-text-left { text-align: start; }
    .pf-md-text-center { text-align: center; }
    .pf-md-text-right { text-align: end; }
    .pf-md-items-center { align-items: center; }
    .pf-md-items-start { align-items: flex-start; }
    .pf-md-justify-between { justify-content: space-between; }
    .pf-md-justify-center { justify-content: center; }
    .pf-md-w-full { width: 100%; }
    .pf-md-w-auto { width: auto; }
    .pf-md-order-first { order: -1; }
    .pf-md-order-last { order: 99; }
    .pf-md-span-full { grid-column: 1 / -1; }
  }
  @media (min-width: 992px) {
    .pf-lg-hidden { display: none; }
    .pf-lg-block { display: block; }
    .pf-lg-flex { display: flex; }
    .pf-lg-grid-d { display: grid; }
    .pf-lg-inline-flex { display: inline-flex; }
    .pf-lg-flex-col { flex-direction: column; }
    .pf-lg-flex-row { flex-direction: row; }
    .pf-lg-text-left { text-align: start; }
    .pf-lg-text-center { text-align: center; }
    .pf-lg-text-right { text-align: end; }
    .pf-lg-items-center { align-items: center; }
    .pf-lg-items-start { align-items: flex-start; }
    .pf-lg-justify-between { justify-content: space-between; }
    .pf-lg-justify-center { justify-content: center; }
    .pf-lg-w-full { width: 100%; }
    .pf-lg-w-auto { width: auto; }
    .pf-lg-order-first { order: -1; }
    .pf-lg-order-last { order: 99; }
    .pf-lg-span-full { grid-column: 1 / -1; }
  }
  @media (min-width: 1200px) {
    .pf-xl-hidden { display: none; }
    .pf-xl-block { display: block; }
    .pf-xl-flex { display: flex; }
    .pf-xl-grid-d { display: grid; }
    .pf-xl-inline-flex { display: inline-flex; }
    .pf-xl-flex-col { flex-direction: column; }
    .pf-xl-flex-row { flex-direction: row; }
    .pf-xl-text-left { text-align: start; }
    .pf-xl-text-center { text-align: center; }
    .pf-xl-text-right { text-align: end; }
    .pf-xl-items-center { align-items: center; }
    .pf-xl-items-start { align-items: flex-start; }
    .pf-xl-justify-between { justify-content: space-between; }
    .pf-xl-justify-center { justify-content: center; }
    .pf-xl-w-full { width: 100%; }
    .pf-xl-w-auto { width: auto; }
    .pf-xl-order-first { order: -1; }
    .pf-xl-order-last { order: 99; }
    .pf-xl-span-full { grid-column: 1 / -1; }
  }
  
  /* ==========================================================================
     #SCROLL REVEAL
     ========================================================================== */
  
  /**
   * .pf-reveal / .pf-reveal-soft
   *
   * Content comes into focus as it enters the viewport, using scroll-driven
   * animations - no script, no IntersectionObserver, nothing to initialise.
   *
   * Two guards, both load-bearing:
   *
   *   @supports (animation-timeline: view())  keeps the animation out of
   *   engines that would apply the keyframes without ever advancing them,
   *   which would leave the element stuck at opacity 0 forever.
   *
   *   prefers-reduced-motion: no-preference  means motion is opt-in from the
   *   user's settings rather than opt-out.
   *
   * The un-animated state is the visible one. That ordering is the whole safety
   * argument: every failure mode ends with the content on screen.
   */
  @supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
      .pf-reveal {
        animation: pf-reveal-in linear both;
        animation-timeline: view();
        animation-range: entry 5% cover 26%;
      }
      .pf-reveal-soft {
        animation: pf-fade-in linear both;
        animation-timeline: view();
        animation-range: entry 0% cover 22%;
      }
    }
  }
  @keyframes pf-reveal-in {
    from { opacity: 0; transform: translateY(1.75rem); }
    to   { opacity: 1; transform: none; }
  }
  @keyframes pf-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
  }
  
  /* Responsive visibility */
  @media (max-width: 860px) {
    .pf-hide-sm { display: none !important; }
  }
  @media (min-width: 861px) {
    .pf-hide-lg { display: none !important; }
  }
  /* ========================================================================
     PRINT
     ========================================================================
     A printed page is a different medium, not a screenshot of a screen. Dark
     backgrounds waste ink and render grey; navigation is dead weight; a link
     that says "read more" is useless on paper because the address is gone.

     This block is written for the case a documentation or article page is
     actually printed or saved as a PDF, which for a publication is a real
     thing readers do.
     ======================================================================== */

  /* Hidden on screen, shown on paper. The counterpart lives in the print
     block below. */
  .pf-print-only { display: none; }

  @media print {
    /* Force the light palette. A printer given a dark background either
       floods the page or drops it, and neither is readable. */
    :root {
      --pf-bg: #ffffff;
      --pf-bg-deep: #ffffff;
      --pf-surface: transparent;
      --pf-surface-raised: transparent;
      --pf-text: #000000;
      --pf-text-muted: #333333;
      --pf-accent: #000000;
      --pf-accent-2: #000000;
      --pf-border: #999999;
      --pf-border-strong: #666666;
      --pf-mesh: none;
      --pf-cut: 0px;
    }

    *,
    *::before,
    *::after {
      background: transparent !important;
      box-shadow: none !important;
      color: #000 !important;
      text-shadow: none !important;
    }

    body { font-size: 11pt; line-height: 1.45; }

    /* Chrome that means nothing on paper. */
    .pf-nav,
    .pf-topbar,
    .pf-footer,
    .pf-cta,
    .pf-skip,
    .pf-totop,
    .pf-sidenav,
    .pf-bottombar,
    .pf-drawer,
    .pf-pagination,
    .pf-tabs__label,
    .pf-scroller,
    .pf-breadcrumb,
    [data-pf-theme-toggle],
    .pf-code__copy { display: none !important; }

    /* Tabs and accordions hide content behind a control that cannot be
       clicked on paper, so print every panel. */
    .pf-tabs__panel { display: block !important; }
    .pf-accordion details { display: block !important; }
    .pf-accordion summary { font-weight: 600; }

    /* The address is the useful part of a link once the page is paper. */
    .pf-prose a[href^="http"]::after,
    main a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.85em; word-break: break-all; }
    a[href^="#"]::after,
    .pf-btn[href]::after { content: none; }

    /* Structure that survives without colour. */
    .pf-card,
    .pf-plan,
    .pf-alert,
    .pf-code,
    .pf-table-wrap { border: 1px solid #999 !important; }

    .pf-alert__title { font-weight: 700; }
    .pf-code pre { white-space: pre-wrap; word-break: break-word; }

    /* Page breaks. A heading stranded at the foot of a page and a table split
       across two are the two things that make a printed reference unusable. */
    h1, h2, h3, h4 { break-after: avoid-page; page-break-after: avoid; }
    figure, table, .pf-card, .pf-alert, .pf-code, blockquote { break-inside: avoid; page-break-inside: avoid; }
    .pf-section { break-before: auto; padding-block: 0.6cm 0; }
    thead { display: table-header-group; }
    tr { break-inside: avoid; }

    /* Give the sheet its own margins rather than the browser's default. */
    @page { margin: 1.6cm 1.4cm; }

    .pf-container,
    .pf-container--wide,
    .pf-container--narrow { max-width: none; padding-inline: 0; }

    .pf-hero { padding-block: 0 0.6cm; }
    .pf-grid, .pf-split, .pf-shell { display: block; }
    .pf-grid > * + *, .pf-split > * + * { margin-block-start: 0.5cm; }

    /* The print-only helper pair, for a note or a URL that belongs on paper
       and nowhere else. */
    .pf-print-only { display: revert !important; }
    .pf-no-print { display: none !important; }
  }
}
