@charset "UTF-8";
/*!
 * Hash v1.0.0 — Core Layout & Utilities
 * Successor to Hash v0.6.9 (HashHackCode, LLP)
 *
 * PHILOSOPHY (unchanged from 0.6.9)
 * ---------------------------------------------------------------------------
 * pageGrid > header/main/footer > section#m1 > simpleGrid|customGrid|layerGrid
 * > .inner (named n{depth}-i{index}) > wrapper/elements.
 * Layout lives in the class attribute. Numbers live in style="--grid:2".
 * Looks live in style.css. Anyone who knows the 6 container words can build a page.
 *
 * WHAT IS NEW IN 1.0.0
 * ---------------------------------------------------------------------------
 * 1. @layer — hash never fights your style.css again (no !important wars).
 * 2. Responsive grid vars: --grid-lg / --grid-md / --grid-sm (and --col-*).
 *    One attribute replaces a hand written media query.
 * 3. autoGrid — card decks that reflow with no breakpoints at all.
 * 4. Two spacing axes that actually behave: --xs..--xl stays % (inline rhythm),
 *    --px-xs..--px-xl becomes fluid rem (block rhythm). Percent vertical
 *    padding resolved against WIDTH in 0.6.9 — that is why every project ended
 *    up hand writing margin-top. Add .hash-legacy to <html> to get 0.6.9 values.
 * 5. Shorthands for the pairs we type 1000s of times: .center-flex, .center-all.
 * 6. Bug fixes: .m-no now clears margin (it cleared padding), inline elements
 *    no longer get line-height:0 (every project had to unset it), hr is sane.
 * 7. Scroll/snap rails, sticky, span, container-query and a11y helpers.
 * 8. Fixed rem gaps (.gp-1..8, .gp with --gp) beside the fluid % gaps — the
 *    corpus had 145 raw `gap: 8px` declarations because gp-* only spoke %.
 * 9. .stack / .row / .sec — the three primitives every project rebuilt as
 *    "five siblings each carrying mt-xl-single" and `section { padding: 3.5% 10% }`.
 * 10. Grid children get min-inline-size:0 (the classic overflow bug), element
 *    resets are wrapped in :where() so no plugin or Gutenberg style is harmed,
 *    and ps-* / pe-* logical spacing supports the RTL themes.
 *
 * BACK COMPAT: every 0.6.9 class name still exists and still means the same
 * thing. Existing markup keeps working. Only the --px-* values changed.
 */

@layer hash.base, hash.grid, hash.util, hash.responsive, hash.motion, theme, page;

/*
====================================================================
  TOKENS
====================================================================
*/
@layer hash.base {
  :root {
    /* 62.5% => 1rem = 10px. Keeps every existing rem value valid. */
    font-size: 62.5%;

    /* -- Inline rhythm (x axis): % of container width, as in 0.6.9 -------- */
    --xs: 1%;
    --sm: 2.5%;
    --md: 5%;
    --lg: 7.5%;
    --xl: 10%;

    /* -- Block rhythm (y axis): fluid rem. NEW in 1.0.0 ------------------- */
    --px-xs: clamp(0.8rem, 0.4vw + 0.5rem, 1.2rem);
    --px-sm: clamp(1.6rem, 0.8vw + 1rem, 2.4rem);
    --px-md: clamp(3.2rem, 2vw + 1.6rem, 4.8rem);
    --px-lg: clamp(4.8rem, 3.5vw + 2.4rem, 8rem);
    --px-xl: clamp(6.4rem, 5vw + 3.2rem, 12rem);

    /* -- Fixed rhythm (rem). Use when a design needs an exact gap, not a
          proportional one. 1rem = 10px under the 62.5% root. ---------------- */
    --sp-1: 0.4rem;
    --sp-2: 0.8rem;
    --sp-3: 1.2rem;
    --sp-4: 1.6rem;
    --sp-5: 2.4rem;
    --sp-6: 3.2rem;
    --sp-7: 4.8rem;
    --sp-8: 6.4rem;

    /* -- Layout knobs ----------------------------------------------------- */
    --grid: 1;      /* columns of a simpleGrid  (or a track list on customGrid) */
    --col: 1;       /* columns of an inner-col  (or a track list on inner-custom) */
    --min: 24rem;   /* autoGrid minimum card width */
    --stick: 0px;   /* offset used by .sticky-top */
    --bleed: var(--md);      /* page gutter used by .gutter and .sec */
    --gp: var(--sp-4);       /* free gap for .gp / .stack / .row */
    --sec-y: var(--px-md);   /* section block padding, used by .sec */
    --sec-x: var(--bleed);   /* section inline padding, used by .sec */
  }

  /* Opt back into 0.6.9 spacing: <html class="hash-legacy"> */
  :root.hash-legacy {
    --px-xs: 1%;
    --px-sm: 2.5%;
    --px-md: 5%;
    --px-lg: 7.5%;
    --px-xl: 10%;
  }

  /*
  ====================================================================
    BASE / RESET
  ====================================================================
  */
  html {
    box-sizing: border-box;
    height: 100%;
    width: 100%;
    -webkit-text-size-adjust: 100%;
  }
  *,
  *::before,
  *::after {
    box-sizing: inherit;
  }
  body {
    display: block;
    margin: 0;
    min-height: 100%;
    min-width: 100%;
  }

  /*
    Element resets are wrapped in :where() — specificity 0. A WordPress plugin,
    a Gutenberg block or your own style.css overrides any of them with a plain
    class, no !important needed. 0.6.9 reset elements at full specificity and
    the corpus paid for it with 547 !important declarations.
  */

  /* Media never overflows its grid cell */
  :where(img, svg, video, canvas, iframe) {
    max-width: 100%;
  }
  /* An inline <svg> carrying only a viewBox falls back to the SVG default of
     300x150 in every browser, so icons render at the wrong size and hero
     artwork disappears into a 300px box. Sized by its container instead. */
  :where(svg:not([width]):not([height])) {
    width: 100%;
    height: auto;
  }
  :where(img, video) {
    object-fit: cover;
  }

  /* Text rhythm */
  :where(h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5, h6, .h6) {
    margin-top: 0;
    margin-bottom: 0.5rem;
    line-height: 1.2;
  }
  :where(p, ul, ol, pre, table, blockquote) {
    margin-top: 1rem;
    margin-bottom: 0;
  }
  :where(p) {
    margin-bottom: 1rem;
  }
  :where(ul ul, ol ol, ul ol, ol ul) {
    margin-top: 0;
    margin-bottom: 0;
  }
  /* Lists inside our own layout lose their bullets; lists inside editor or
     plugin content keep them. 0.6.9 stripped every ul on the page. */
  :where(ul) {
    margin-top: 0;
  }
  :where(.pageGrid ul, .inner ul, nav ul) {
    list-style: none;
    padding-inline-start: 0;
  }

  /* 0.6.9 set line-height:0 on inline tags, which every project had to unset.
     Inline elements now simply inherit the parent line-height. */
  :where(a, b, i, strong, em, small, code) {
    line-height: inherit;
  }
  :where(sub, sup) {
    font-size: 75%;
    line-height: 0;
    position: relative;
    vertical-align: baseline;
  }
  :where(sup) { top: -0.5em; }
  :where(sub) { bottom: -0.25em; }
  :where(em) { font-style: italic; }
  :where(strong) { font-weight: 600; }
  :where(small) { font-size: 75%; }

  hr, .hr {
    border: 0;
    border-top: 1px solid currentColor;
    margin: 0;
    opacity: 0.25;
  }

  :where(a) { color: inherit; }

  :where(button, input, select, textarea) {
    font: inherit;
    color: inherit;
    /* a control's intrinsic min-content width otherwise widens its grid track
       and pushes the whole header past the viewport on mobile */
    min-inline-size: 0;
  }
  :where(button) {
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
  }

  /* Keyboard users keep their focus ring, mouse users do not see it */
  :focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 2px;
  }

  [hidden] { display: none !important; }
}

/*
====================================================================
  GRID CONTAINERS
====================================================================
*/
@layer hash.grid {
  .titleGrid,
  .simpleGrid,
  .customGrid,
  .complexGrid,
  .layerGrid,
  .autoGrid,
  .inner-col,
  .inner-custom,
  .inner-complex,
  .inner-layer,
  .inner-auto {
    width: 100%;
    display: grid;
    grid-template-rows: max-content;
    position: relative;
  }

  .inner { position: relative; }

  /*
    A grid/flex child defaults to min-width:auto, so one long word or a wide
    table blows the column out instead of scrolling. This is the single most
    common layout bug in the corpus.
  */
  :where(.simpleGrid, .customGrid, .autoGrid, .inner-col, .inner-custom,
         .inner-auto, .inner-flex, .inner-flex-col, .row, .stack) > * {
    min-inline-size: 0;
  }

  .simpleGrid { grid-template-columns: repeat(var(--grid, 1), 1fr); }
  .customGrid { grid-template-columns: var(--grid, 1fr); }

  .inner-col { grid-template-columns: repeat(var(--col, 1), 1fr); }
  .inner-custom { grid-template-columns: var(--col, 1fr); }

  /* Card decks with no breakpoints: style="--min:28rem"
     --min is re-declared here for the same reason as --gp: it must not leak
     from an outer autoGrid into a nested one. */
  .autoGrid,
  .inner-auto {
    --min: 24rem;
    grid-template-columns: repeat(auto-fit, minmax(min(var(--min), 100%), 1fr));
  }

  /* Stack everything in one cell (hero + overlay) */
  .layerGrid,
  .inner-layer {
    grid-template-columns: 1fr;
    grid-template-rows: 1fr;
  }
  .layerGrid > *,
  .inner-layer > * {
    grid-row: 1;
    grid-column: 1;
  }

  .inner-flex {
    display: flex;
    width: 100%;
  }
  .inner-flex-col {
    display: flex;
    flex-direction: column;
    width: 100%;
  }

  /*
    The two missing primitives. One `.stack` replaces the idiom of five
    siblings each carrying mt-xl-single; `.row` replaces
    inner-flex + center-y-flex + a gap class.
    Tune with --gp:  <div class="stack" style="--gp:2.4rem">
  */
  /*
    Each of these re-declares --gp on itself. Custom properties inherit, so
    without the reset a `style="--gp:6.4rem"` on an outer .stack would silently
    become the gap of every .stack nested inside it. Set --gp where you want it;
    inline style still wins on the element that carries it.
  */
  .stack {
    --gp: var(--sp-4);
    display: flex;
    flex-direction: column;
    width: 100%;
    gap: var(--gp);
  }
  .row {
    --gp: var(--sp-4);
    display: flex;
    align-items: center;
    gap: var(--gp);
  }
  .row-top { align-items: flex-start; }
  .row-wrap { flex-wrap: wrap; }

  /*
    Inside a stack or a row the gap is the rhythm, so the default block margins
    on typographic children would double it up. :where() keeps this at
    specificity 0 — any project rule still wins.
  */
  :where(.stack, .row) > :where(p, h1, h2, h3, h4, h5, h6, ul, ol, pre, blockquote, table, figure) {
    margin-block: 0;
  }

  /*
    Section rhythm. Replaces `section { padding: 3.5% 10% }` plus its four
    breakpoint overrides — the corpus had eight different versions of it.
    <section id="m2" class="sec">            default rhythm
    <section id="m3" class="sec" style="--sec-y:var(--px-xl)">
  */
  .sec {
    --sec-y: var(--px-md);
    --sec-x: var(--bleed);
    padding-block: var(--sec-y);
    padding-inline: var(--sec-x);
  }
  .sec-flat { --sec-y: 0; }
  .sec-tight { --sec-y: var(--px-sm); }
  .sec-tall { --sec-y: var(--px-xl); }

  /* Aspect ratios — stops layout shift on images and embeds */
  .ratio-1x1 { aspect-ratio: 1 / 1; }
  .ratio-4x3 { aspect-ratio: 4 / 3; }
  .ratio-3x2 { aspect-ratio: 3 / 2; }
  .ratio-16x9 { aspect-ratio: 16 / 9; }
  .ratio-21x9 { aspect-ratio: 21 / 9; }
  :where(.ratio-1x1, .ratio-4x3, .ratio-3x2, .ratio-16x9, .ratio-21x9) > * {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
  /*
    A ratio box derives its height from its width, so it must not be stretched
    by its grid row or flex line — otherwise the row height wins and the ratio
    is silently ignored. :where() keeps this at specificity 0, so any alignment
    utility (center-y-single, stretch-y-all…) still overrides it.
  */
  :where(.ratio-1x1, .ratio-4x3, .ratio-3x2, .ratio-16x9, .ratio-21x9) {
    align-self: start;
  }

  /* Overlay layer for layerGrid heroes — was copied into style.css per project */
  .overlay {
    position: absolute;
    inset: 0;
    background: var(--overlay, rgba(0, 0, 0, 0.45));
    pointer-events: none;
  }

  /* Track placement */
  .inner-title,
  .span-full { grid-column: 1 / -1; }
  .span-2 { grid-column: span 2; }
  .span-3 { grid-column: span 3; }
  .span-4 { grid-column: span 4; }
  .span-5 { grid-column: span 5; }
  .span-6 { grid-column: span 6; }
  .row-span-2 { grid-row: span 2; }
  .row-span-3 { grid-row: span 3; }

  /* Horizontal rails — the drag slider / snap carousel pattern */
  .scroll-x {
    display: flex;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
  }
  .scroll-x::-webkit-scrollbar { display: none; }
  .scroll-y {
    overflow-y: auto;
    overflow-x: hidden;
  }
  .snap-x {
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
  }
  .snap-item { scroll-snap-align: center; }
  .snap-start { scroll-snap-align: start; }

  /* Container queries: put .cq on a card, size its insides by the card */
  .cq { container-type: inline-size; }

  /*
    Wide content that must scroll instead of widening the page. Wrap a table in
    it: <div class="table-scroll" tabindex="0"><table class="table">…
    tabindex makes the region reachable by keyboard, which is required once a
    region scrolls.
  */
  .table-scroll {
    max-inline-size: 100%;
    overflow-x: auto;
    overscroll-behavior-x: contain;
  }
  .table-scroll > table { min-inline-size: max-content; }
}

/*
====================================================================
  ALIGNMENT
====================================================================
*/
@layer hash.util {
  /* -- Grid: all children ------------------------------------------------ */
  .start-x-all { justify-items: start; }
  .center-x-all { justify-items: center; }
  .end-x-all { justify-items: end; }
  .stretch-x-all { justify-items: stretch; }
  .start-y-all { align-items: start; }
  .center-y-all { align-items: center; }
  .end-y-all { align-items: end; }
  .stretch-y-all { align-items: stretch; }
  .center-all { place-items: center; }

  /* Track alignment inside the container (0.6.9 add-on, now core) */
  .start-y { align-content: start; }
  .center-y { align-content: center; }
  .end-y { align-content: end; }
  .between-y { align-content: space-between; }

  /* -- Grid: one child --------------------------------------------------- */
  .start-x-single { justify-self: start; }
  .center-x-single { justify-self: center; }
  .end-x-single { justify-self: end; }
  .start-y-single { align-self: start; }
  .center-y-single { align-self: center; }
  .end-y-single { align-self: end; }
  .center-single { place-self: center; }

  /* -- Flex -------------------------------------------------------------- */
  .start-x-flex { justify-content: flex-start; }
  .center-x-flex { justify-content: center; }
  .end-x-flex { justify-content: flex-end; }
  .start-y-flex { align-items: flex-start; }
  .center-y-flex { align-items: center; }
  .end-y-flex { align-items: flex-end; }
  .stretch-y-flex { align-items: stretch; }
  .baseline-flex { align-items: baseline; }
  .flex-between { justify-content: space-between; }
  .flex-around { justify-content: space-around; }
  .flex-evenly { justify-content: space-evenly; }

  /* The pair we type most: center-x-flex + center-y-flex */
  .center-flex {
    justify-content: center;
    align-items: center;
  }

  /* A .stack is a flex column, so an inline-flex child (a pill, a chip, an
     icon box) stretches to full width unless it opts out. */
  .self-start { align-self: flex-start; }
  .self-center { align-self: center; }
  .self-end { align-self: flex-end; }
  .self-stretch { align-self: stretch; }

  .wrap { flex-wrap: wrap; }
  .nowrap-flex { flex-wrap: nowrap; }
  .row-reverse { flex-direction: row-reverse; }
  .col-reverse { flex-direction: column-reverse; }
  .fill { flex: 1 1 auto; min-width: 0; }
  .fill-no { flex: 0 0 auto; }

  /*
  ====================================================================
    GAP
    Column gap uses the inline (%) scale, row gap uses the block (rem)
    scale. In 0.6.9 a % row-gap collapsed to 0 on auto-height rows.
  ====================================================================
  */
  .gp-xs { gap: var(--px-xs) var(--xs); }
  .gp-sm { gap: var(--px-sm) var(--sm); }
  .gp-md { gap: var(--px-md) var(--md); }
  .gp-lg { gap: var(--px-lg) var(--lg); }
  .gp-xl { gap: var(--px-xl) var(--xl); }

  .gpx-xs { column-gap: var(--xs); }
  .gpx-sm { column-gap: var(--sm); }
  .gpx-md { column-gap: var(--md); }
  .gpx-lg { column-gap: var(--lg); }
  .gpx-xl { column-gap: var(--xl); }

  .gpy-xs { row-gap: var(--px-xs); }
  .gpy-sm { row-gap: var(--px-sm); }
  .gpy-md { row-gap: var(--px-md); }
  .gpy-lg { row-gap: var(--px-lg); }
  .gpy-xl { row-gap: var(--px-xl); }

  /*
    Fixed gaps. gp-xs..xl are proportional (% of width) and are right for page
    rhythm; these are right when the design says "8px between the icon and the
    label". The corpus contained 145 raw `gap: 8px` declarations because this
    scale did not exist.
  */
  .gp-1 { gap: var(--sp-1); }   /*  4px */
  .gp-2 { gap: var(--sp-2); }   /*  8px */
  .gp-3 { gap: var(--sp-3); }   /* 12px */
  .gp-4 { gap: var(--sp-4); }   /* 16px */
  .gp-5 { gap: var(--sp-5); }   /* 24px */
  .gp-6 { gap: var(--sp-6); }   /* 32px */
  .gp-7 { gap: var(--sp-7); }   /* 48px */
  .gp-8 { gap: var(--sp-8); }   /* 64px */

  /* Escape hatch: any gap without a new class — style="--gp:1.3rem" */
  .gp { gap: var(--gp); }

  .gp-no { gap: 0 !important; }

  /*
  ====================================================================
    PADDING — single element
  ====================================================================
  */
  .p-xs-single { padding: var(--px-xs) var(--xs); }
  .p-sm-single { padding: var(--px-sm) var(--sm); }
  .p-md-single { padding: var(--px-md) var(--md); }
  .p-lg-single { padding: var(--px-lg) var(--lg); }
  .p-xl-single { padding: var(--px-xl) var(--xl); }

  .pt-xs-single { padding-top: var(--px-xs); }
  .pt-sm-single { padding-top: var(--px-sm); }
  .pt-md-single { padding-top: var(--px-md); }
  .pt-lg-single { padding-top: var(--px-lg); }
  .pt-xl-single { padding-top: var(--px-xl); }

  .pb-xs-single { padding-bottom: var(--px-xs); }
  .pb-sm-single { padding-bottom: var(--px-sm); }
  .pb-md-single { padding-bottom: var(--px-md); }
  .pb-lg-single { padding-bottom: var(--px-lg); }
  .pb-xl-single { padding-bottom: var(--px-xl); }

  .pr-xs-single { padding-right: var(--xs); }
  .pr-sm-single { padding-right: var(--sm); }
  .pr-md-single { padding-right: var(--md); }
  .pr-lg-single { padding-right: var(--lg); }
  .pr-xl-single { padding-right: var(--xl); }

  .pl-xs-single { padding-left: var(--xs); }
  .pl-sm-single { padding-left: var(--sm); }
  .pl-md-single { padding-left: var(--md); }
  .pl-lg-single { padding-left: var(--lg); }
  .pl-xl-single { padding-left: var(--xl); }

  .px-xs-single { padding-inline: var(--xs); }
  .px-sm-single { padding-inline: var(--sm); }
  .px-md-single { padding-inline: var(--md); }
  .px-lg-single { padding-inline: var(--lg); }
  .px-xl-single { padding-inline: var(--xl); }

  /* Logical inline start/end — these flip in RTL, unlike pl-* / pr-*.
     Use them in the themes that ship style-rtl.css. */
  .ps-xs-single { padding-inline-start: var(--xs); }
  .ps-sm-single { padding-inline-start: var(--sm); }
  .ps-md-single { padding-inline-start: var(--md); }
  .ps-lg-single { padding-inline-start: var(--lg); }
  .ps-xl-single { padding-inline-start: var(--xl); }
  .pe-xs-single { padding-inline-end: var(--xs); }
  .pe-sm-single { padding-inline-end: var(--sm); }
  .pe-md-single { padding-inline-end: var(--md); }
  .pe-lg-single { padding-inline-end: var(--lg); }
  .pe-xl-single { padding-inline-end: var(--xl); }
  .ms-sm-single { margin-inline-start: var(--sm); }
  .ms-md-single { margin-inline-start: var(--md); }
  .me-sm-single { margin-inline-end: var(--sm); }
  .me-md-single { margin-inline-end: var(--md); }
  .ms-auto { margin-inline-start: auto; }
  .me-auto { margin-inline-end: auto; }

  .py-xs-single { padding-block: var(--px-xs); }
  .py-sm-single { padding-block: var(--px-sm); }
  .py-md-single { padding-block: var(--px-md); }
  .py-lg-single { padding-block: var(--px-lg); }
  .py-xl-single { padding-block: var(--px-xl); }

  /*
  ====================================================================
    PADDING — every direct child
    :where() keeps specificity at 0 so a component class always wins.
  ====================================================================
  */
  :where(.p-xs-all) > * { padding: var(--px-xs) var(--xs); }
  :where(.p-sm-all) > * { padding: var(--px-sm) var(--sm); }
  :where(.p-md-all) > * { padding: var(--px-md) var(--md); }
  :where(.p-lg-all) > * { padding: var(--px-lg) var(--lg); }
  :where(.p-xl-all) > * { padding: var(--px-xl) var(--xl); }

  :where(.pt-xs-all) > * { padding-top: var(--px-xs); }
  :where(.pt-sm-all) > * { padding-top: var(--px-sm); }
  :where(.pt-md-all) > * { padding-top: var(--px-md); }
  :where(.pt-lg-all) > * { padding-top: var(--px-lg); }
  :where(.pt-xl-all) > * { padding-top: var(--px-xl); }

  :where(.pb-xs-all) > * { padding-bottom: var(--px-xs); }
  :where(.pb-sm-all) > * { padding-bottom: var(--px-sm); }
  :where(.pb-md-all) > * { padding-bottom: var(--px-md); }
  :where(.pb-lg-all) > * { padding-bottom: var(--px-lg); }
  :where(.pb-xl-all) > * { padding-bottom: var(--px-xl); }

  :where(.pr-xs-all) > * { padding-right: var(--xs); }
  :where(.pr-sm-all) > * { padding-right: var(--sm); }
  :where(.pr-md-all) > * { padding-right: var(--md); }
  :where(.pr-lg-all) > * { padding-right: var(--lg); }
  :where(.pr-xl-all) > * { padding-right: var(--xl); }

  :where(.pl-xs-all) > * { padding-left: var(--xs); }
  :where(.pl-sm-all) > * { padding-left: var(--sm); }
  :where(.pl-md-all) > * { padding-left: var(--md); }
  :where(.pl-lg-all) > * { padding-left: var(--lg); }
  :where(.pl-xl-all) > * { padding-left: var(--xl); }

  :where(.px-sm-all) > * { padding-inline: var(--sm); }
  :where(.px-md-all) > * { padding-inline: var(--md); }
  :where(.py-sm-all) > * { padding-block: var(--px-sm); }
  :where(.py-md-all) > * { padding-block: var(--px-md); }

  /*
  ====================================================================
    MARGIN — single element
  ====================================================================
  */
  .m-xs-single { margin: var(--px-xs) var(--xs); }
  .m-sm-single { margin: var(--px-sm) var(--sm); }
  .m-md-single { margin: var(--px-md) var(--md); }
  .m-lg-single { margin: var(--px-lg) var(--lg); }
  .m-xl-single { margin: var(--px-xl) var(--xl); }

  .mt-xs-single { margin-top: var(--px-xs); }
  .mt-sm-single { margin-top: var(--px-sm); }
  .mt-md-single { margin-top: var(--px-md); }
  .mt-lg-single { margin-top: var(--px-lg); }
  .mt-xl-single { margin-top: var(--px-xl); }

  .mb-xs-single { margin-bottom: var(--px-xs); }
  .mb-sm-single { margin-bottom: var(--px-sm); }
  .mb-md-single { margin-bottom: var(--px-md); }
  .mb-lg-single { margin-bottom: var(--px-lg); }
  .mb-xl-single { margin-bottom: var(--px-xl); }

  .mr-xs-single { margin-right: var(--xs); }
  .mr-sm-single { margin-right: var(--sm); }
  .mr-md-single { margin-right: var(--md); }
  .mr-lg-single { margin-right: var(--lg); }
  .mr-xl-single { margin-right: var(--xl); }

  .ml-xs-single { margin-left: var(--xs); }
  .ml-sm-single { margin-left: var(--sm); }
  .ml-md-single { margin-left: var(--md); }
  .ml-lg-single { margin-left: var(--lg); }
  .ml-xl-single { margin-left: var(--xl); }

  .my-xs-single { margin-block: var(--px-xs); }
  .my-sm-single { margin-block: var(--px-sm); }
  .my-md-single { margin-block: var(--px-md); }
  .my-lg-single { margin-block: var(--px-lg); }
  .my-xl-single { margin-block: var(--px-xl); }

  .mx-xs-single { margin-inline: var(--xs); }
  .mx-sm-single { margin-inline: var(--sm); }
  .mx-md-single { margin-inline: var(--md); }
  .mx-lg-single { margin-inline: var(--lg); }
  .mx-xl-single { margin-inline: var(--xl); }

  /*
  ====================================================================
    MARGIN — every direct child
  ====================================================================
  */
  :where(.m-xs-all) > * { margin: var(--px-xs) var(--xs); }
  :where(.m-sm-all) > * { margin: var(--px-sm) var(--sm); }
  :where(.m-md-all) > * { margin: var(--px-md) var(--md); }
  :where(.m-lg-all) > * { margin: var(--px-lg) var(--lg); }
  :where(.m-xl-all) > * { margin: var(--px-xl) var(--xl); }

  :where(.mt-xs-all) > * { margin-top: var(--px-xs); }
  :where(.mt-sm-all) > * { margin-top: var(--px-sm); }
  :where(.mt-md-all) > * { margin-top: var(--px-md); }
  :where(.mt-lg-all) > * { margin-top: var(--px-lg); }
  :where(.mt-xl-all) > * { margin-top: var(--px-xl); }

  :where(.mb-xs-all) > * { margin-bottom: var(--px-xs); }
  :where(.mb-sm-all) > * { margin-bottom: var(--px-sm); }
  :where(.mb-md-all) > * { margin-bottom: var(--px-md); }
  :where(.mb-lg-all) > * { margin-bottom: var(--px-lg); }
  :where(.mb-xl-all) > * { margin-bottom: var(--px-xl); }

  :where(.mr-xs-all) > * { margin-right: var(--xs); }
  :where(.mr-sm-all) > * { margin-right: var(--sm); }
  :where(.mr-md-all) > * { margin-right: var(--md); }
  :where(.mr-lg-all) > * { margin-right: var(--lg); }
  :where(.mr-xl-all) > * { margin-right: var(--xl); }

  :where(.ml-xs-all) > * { margin-left: var(--xs); }
  :where(.ml-sm-all) > * { margin-left: var(--sm); }
  :where(.ml-md-all) > * { margin-left: var(--md); }
  :where(.ml-lg-all) > * { margin-left: var(--lg); }
  :where(.ml-xl-all) > * { margin-left: var(--xl); }

  /* Zeroing — .m-no cleared padding in 0.6.9. It clears margin now. */
  .p-no { padding: 0 !important; }
  .m-no { margin: 0 !important; }

  /*
  ====================================================================
    SIZE / POSITION / DISPLAY HELPERS
  ====================================================================
  */
  .hAuto { height: auto; }
  .wAuto { width: auto; }
  .m-auto { margin: 0 auto; }
  .mx-auto { margin-inline: auto; }
  .ml-auto { margin-left: auto; }
  .mr-auto { margin-right: auto; }

  .w-full { width: 100%; }
  .h-full { height: 100%; }
  .w-fit { width: fit-content; }
  .h-fit { height: fit-content; }
  .h-screen { height: 100dvh; }
  .min-h-screen { min-height: 100dvh; }
  .gutter { padding-inline: var(--bleed); }
  .wrapper-max { max-width: var(--max, 144rem); margin-inline: auto; }

  .rel { position: relative; }
  .abs { position: absolute; }
  .fix { position: fixed; }
  .sticky-top {
    position: sticky;
    top: var(--stick, 0px);
    z-index: 5;
  }
  .inset-0 { inset: 0; }
  .z-1 { z-index: 1; }
  .z-2 { z-index: 2; }
  .z-3 { z-index: 3; }
  .z-4 { z-index: 4; }
  .z-5 { z-index: 5; }

  .clip { overflow: hidden; }
  .clip-x { overflow-x: hidden; }

  .hide { display: none !important; }
  .invisible { visibility: hidden; }
  .pointer-no { pointer-events: none; }
  .select-no { user-select: none; -webkit-user-select: none; }

  /* Screen reader only — for icon-only buttons */
  .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  /*
  ====================================================================
    TEXT UTILITIES
  ====================================================================
  */
  .left { text-align: left; }
  .center { text-align: center; }
  .right { text-align: right; }
  .justify-text { text-align: justify; }
  .nowrap { white-space: nowrap; }
  .balance { text-wrap: balance; }
  .pretty { text-wrap: pretty; }
  .upper { text-transform: uppercase; }
  .lower { text-transform: lowercase; }
  .caps { text-transform: capitalize; }

  .truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .clamp-1,
  .clamp-2,
  .clamp-3,
  .clamp-4 {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .clamp-1 { -webkit-line-clamp: 1; }
  .clamp-2 { -webkit-line-clamp: 2; }
  .clamp-3 { -webkit-line-clamp: 3; }
  .clamp-4 { -webkit-line-clamp: 4; }
}

/*
====================================================================
  RESPONSIVE
  --grid-lg / --grid-md / --grid-sm override --grid at that width.
  Same for --col-*. Falls back down the chain, so setting only
  --grid-sm keeps the desktop value everywhere above 577px.

  <div class="simpleGrid" style="--grid:4; --grid-md:2; --grid-sm:1;">
====================================================================
*/
@layer hash.responsive {
  /* xl screen — the only min-width tier. Use it to ADD columns on big
     monitors; everything else in the library works downwards. */
  @media (min-width: 1440px) {
    .simpleGrid { grid-template-columns: repeat(var(--grid-xl, var(--grid, 1)), 1fr); }
    .customGrid { grid-template-columns: var(--grid-xl, var(--grid, 1fr)); }
    .inner-col { grid-template-columns: repeat(var(--col-xl, var(--col, 1)), 1fr); }
    .inner-custom { grid-template-columns: var(--col-xl, var(--col, 1fr)); }
    .hide-xl { display: none !important; }
    .show-xl { display: revert !important; }
  }

  /* lg screen */
  @media (max-width: 1012px) {
    .simpleGrid { grid-template-columns: repeat(var(--grid-lg, var(--grid, 1)), 1fr); }
    .customGrid { grid-template-columns: var(--grid-lg, var(--grid, 1fr)); }
    .inner-col { grid-template-columns: repeat(var(--col-lg, var(--col, 1)), 1fr); }
    .inner-custom { grid-template-columns: var(--col-lg, var(--col, 1fr)); }
    .autoGrid,
    .inner-auto { grid-template-columns: repeat(auto-fit, minmax(min(var(--min-lg, var(--min, 24rem)), 100%), 1fr)); }

    .single-lg {
      height: auto;
      grid-template-columns: 1fr !important;
    }
    .stack-lg { flex-direction: column; }
    .hide-lg { display: none !important; }
    .show-lg { display: revert !important; }
    .center-lg { text-align: center; }
    .center-x-all-lg { justify-items: center; }
    .center-flex-lg { justify-content: center; align-items: center; }
    .order-first-lg { order: -1; }
  }

  /* md screen */
  @media (max-width: 768px) {
    .simpleGrid { grid-template-columns: repeat(var(--grid-md, var(--grid-lg, var(--grid, 1))), 1fr); }
    .customGrid { grid-template-columns: var(--grid-md, var(--grid-lg, var(--grid, 1fr))); }
    .inner-col { grid-template-columns: repeat(var(--col-md, var(--col-lg, var(--col, 1))), 1fr); }
    .inner-custom { grid-template-columns: var(--col-md, var(--col-lg, var(--col, 1fr))); }
    .autoGrid,
    .inner-auto { grid-template-columns: repeat(auto-fit, minmax(min(var(--min-md, var(--min, 24rem)), 100%), 1fr)); }

    .single-md {
      height: auto;
      grid-template-columns: 1fr !important;
    }
    .stack-md { flex-direction: column; }
    .hide-md { display: none !important; }
    .show-md { display: revert !important; }
    .center-md { text-align: center; }
    .center-x-all-md { justify-items: center; }
    .center-flex-md { justify-content: center; align-items: center; }
    .order-first-md { order: -1; }
    .span-full-md { grid-column: 1 / -1; }
  }

  /* sm screen */
  @media (max-width: 577px) {
    .simpleGrid { grid-template-columns: repeat(var(--grid-sm, var(--grid-md, var(--grid-lg, var(--grid, 1)))), 1fr); }
    .customGrid { grid-template-columns: var(--grid-sm, var(--grid-md, var(--grid-lg, var(--grid, 1fr)))); }
    .inner-col { grid-template-columns: repeat(var(--col-sm, var(--col-md, var(--col-lg, var(--col, 1)))), 1fr); }
    .inner-custom { grid-template-columns: var(--col-sm, var(--col-md, var(--col-lg, var(--col, 1fr)))); }
    .autoGrid,
    .inner-auto { grid-template-columns: repeat(auto-fit, minmax(min(var(--min-sm, var(--min, 24rem)), 100%), 1fr)); }

    .single-sm {
      height: auto;
      grid-template-columns: 1fr !important;
    }
    .stack-sm { flex-direction: column; }
    .hide-sm { display: none !important; }
    .show-sm { display: revert !important; }
    .center-sm { text-align: center; }
    .center-x-all-sm { justify-items: center; }
    .center-flex-sm { justify-content: center; align-items: center; }
    .order-first-sm { order: -1; }
    .span-full-sm { grid-column: 1 / -1; }
    .wrap-sm { flex-wrap: wrap; }
  }

  /* Container query collapse — for cards that live in unknown widths */
  @container (max-width: 480px) {
    .single-cq { grid-template-columns: 1fr !important; }
    .stack-cq { flex-direction: column; }
    .hide-cq { display: none !important; }
  }
}
