@layer utilities {
  :root {
    --inline-space: 1ch;
    --inline-space-half: calc(var(--inline-space) / 2);
    --inline-space-double: calc(var(--inline-space) * 2);

    --block-space: 1rem;
    --block-space-half: calc(var(--block-space) / 2);
    --block-space-third: calc(var(--block-space) / 3);
    --block-space-quarter: calc(var(--block-space) / 4);
    --block-space-double: calc(var(--block-space) * 2);

    --font-x-small-responsive: clamp(0.65rem, 1.5cqi, 0.75rem);
    --font-small-responsive: clamp(0.75rem, 1.8cqi, 0.875rem);
    --font-small-medium-responsive: clamp(0.8rem, 2cqi, 1.05rem);
    --font-medium-responsive: clamp(0.9rem, 2.25cqi, 1.25rem);
    --font-large-responsive: clamp(1.15rem, 3.5cqi, 1.6rem);
    --font-x-large-responsive: clamp(1.6rem, 4.5cqi, 2.8rem);
    --font-xx-large-responsive: clamp(2rem, 5.75cqi, 3.4rem);
    --font-xxx-large-responsive: clamp(2.15rem, 6.25cqi, 3.6rem);
  }

  /* Text */
  .txt-small {
    font-size: 0.8rem;
  }
  .txt-medium {
    font-size: 1rem;
  }
  .txt-large {
    font-size: 1.4rem;
  }
  .txt-x-large {
    font-size: 1.8rem;
  }
  .txt-xx-large {
    font-size: 2.8rem;
  }
  .txt-xxx-large {
    font-size: 3.2rem;
  }

  .txt-x-small--responsive {
    font-size: var(--font-x-small-responsive);
  }
  .txt-small--responsive {
    font-size: var(--font-small-responsive);
  }
  .txt-small-medium--responsive {
    font-size: var(--font-small-medium-responsive);
  }
  .txt-medium--responsive {
    font-size: var(--font-medium-responsive);
  }
  .txt-large--responsive {
    font-size: var(--font-large-responsive);
  }
  .txt-x-large--responsive {
    font-size: var(--font-x-large-responsive);
  }
  .txt-xx-large--responsive {
    font-size: var(--font-xx-large-responsive);
  }
  .txt-xxx-large--responsive {
    font-size: var(--font-xxx-large-responsive);
  }

  .txt-align-center {
    text-align: center;
  }
  .txt-align-start {
    text-align: start;
  }
  .txt-align-end {
    text-align: end;
  }
  .txt-center-mobile {
    @media (max-width: 50rem) {
      text-align: center;
    }
  }

  .txt-ink {
    color: var(--color-ink);
  }
  .txt-reversed {
    color: var(--color-ink-reversed);
  }
  .txt-negative {
    color: var(--color-red);
    transition: color 150ms ease;
  }
  :is(a, button):hover > .txt-negative,
  :is(a, button).txt-negative:hover {
    color: var(--color-red-dark);
  }
  .txt-subtle {
    color: var(--color-ink-subtle);
  }
  .txt-green {
    /* color: var(--color-green); */
    color: var(--color-green);
    transition: color 150ms ease;
  }
  :is(a, button):hover > .txt-green,
  :is(a, button).txt-green:hover {
    color: var(--color-green-dark);
  }
  .txt-green--dark {
    color: var(--color-green-dark);
  }
  /* Bright yellow is for status marks (the ? icon, decorations) that echo the
     yellow underline; running warning text uses .warning-hint (text.css) or
     .txt-yellow--dark, which stay readable on light backgrounds. */
  .txt-yellow {
    color: var(--color-yellow);
  }
  .txt-yellow--dark {
    color: var(--color-yellow-dark);
  }
  .txt-red {
    color: var(--color-red);
    transition: color 150ms ease;
  }
  :is(a, button):hover > .txt-red,
  :is(a, button).txt-red:hover {
    color: var(--color-red-dark);
  }
  .txt-link {
    color: var(--color-blue);
  }
  .txt-hover {
    transition: color 0.2s ease !important;
  }
  .txt-hover:hover {
    color: var(--color-blue) !important;
  }
  .txt-muted {
    color: var(--color-ink-muted);
  }
  .txt-undecorated {
    text-decoration: none;
  }
  .txt-tight-lines {
    line-height: 1.2;
  }
  .txt-normal {
    font-weight: 400;
    font-style: normal;
  }
  .txt-bold {
    font-weight: 500;
  }
  .txt-very-bold {
    font-weight: 700;
  }
  .txt-nowrap {
    white-space: nowrap;
  }
  .txt-uppercase {
    text-transform: uppercase;
  }
  .link {
    color: var(--color-blue);
    text-decoration: underline;
    text-decoration-skip-ink: auto;
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
  }

  /* Green link (e.g. on green confirmation panels) — keeps the .link reset */
  .link--green {
    color: var(--color-green-dark);
  }

  /* Yellow link (e.g. on yellow warning banners) — keeps the .link reset */
  .link--yellow {
    color: var(--color-yellow-dark);
  }

  /* Link rendered as plain dark text that stays put on hover (e.g. table cells) */
  .link-dark,
  .link-dark:hover,
  .link-dark:focus,
  .link-dark:active {
    color: var(--color-ink-body);
  }

  /* Text decoration */
  .underline {
    text-decoration: underline;
  }
  .underline-thick {
    text-decoration-thickness: 0.2rem;
  }
  .underline-green {
    text-decoration-color: var(--color-green);
  }
  .underline-yellow {
    text-decoration-color: var(--color-yellow);
  }
  .underline-red {
    text-decoration-color: var(--color-red);
  }

  /* Flexbox and Grid */
  .justify-end {
    justify-content: end;
  }
  .justify-start {
    justify-content: start;
  }
  .justify-center {
    justify-content: center;
  }
  .justify-space-between {
    justify-content: space-between;
  }
  .justify-center-mobile {
    @media (max-width: 50rem) {
      justify-content: center;
    }
  }

  .align-center {
    align-items: center;
  }
  .align-start {
    align-items: start;
  }
  .align-end {
    align-items: end;
  }

  .align-self-start {
    align-self: start;
  }

  .contain {
    container: inline-size;
  }

  .flex {
    display: flex;
  }
  .flex-inline {
    display: inline-flex;
  }
  .flex-column {
    flex-direction: column;
  }
  .flex-wrap {
    flex-wrap: wrap;
  }

  .flex-col-mobile {
    @media (max-width: 50rem) {
      flex-direction: column;
    }
  }

  .flex-item-grow {
    flex-grow: 1;
  }
  .flex-item-shrink {
    flex-shrink: 1;
  }
  .flex-item-no-shrink {
    flex-shrink: 0;
  }
  .flex-item-justify-start {
    margin-inline-end: auto;
  }
  .flex-item-justify-end {
    margin-inline-start: auto;
  }

  /* minmax(0, …) instead of bare 1fr: a bare 1fr track refuses to shrink below
     its content's min-content, so one long unbreakable string blows the whole
     grid past the viewport on narrow screens. */
  .grid {
    display: grid;
    column-gap: var(--column-gap, var(--inline-space));
    row-gap: var(--row-gap, var(--block-space));
    grid-template-columns: minmax(0, 1fr);
  }

  @media (min-width: 40rem) {
    .grid.grid-2 {
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .grid.grid-3 {
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }
  }

  @media (min-width: 80rem) {
    .grid.grid-3 {
      grid-template-columns: repeat(3, minmax(0, 1fr));
    }
  }

  .gap {
    column-gap: var(--column-gap, var(--inline-space));
    row-gap: var(--row-gap, var(--block-space));
  }

  .gap-half {
    column-gap: var(--inline-space-half);
    row-gap: var(--block-space-half);
  }

  .gap-double {
    column-gap: var(--inline-space-double);
    row-gap: var(--block-space-double);
  }

  /* Sizing */
  .full-width {
    inline-size: 100%;
  }
  .min-width {
    min-inline-size: 0;
  }
  .half-width {
    inline-size: 50%;
  }
  .max-width {
    max-inline-size: 100%;
  }
  .min-content {
    inline-size: min-content;
  }
  .max-inline-size {
    max-inline-size: 100%;
  }
  .max-inline-25 {
    max-inline-size: 25rem;
  }

  /* Content width utilities - match layout widths */
  .content-width {
    inline-size: min(80ch, 100%);
    margin-inline: auto;
  }
  .content-width-narrow {
    inline-size: min(60ch, 100%);
    margin-inline: auto;
  }

  .content-width-reading {
    /* 67ch of the .prose reading font — clamp(1rem, 2.5cqi, 1.4rem) × 0.572ch/em,
       spelled out font-independently so bylines, tag rows and CTAs sharing the
       class align exactly with the prose column regardless of their own font. */
    inline-size: min(clamp(38.3rem, 95.8cqi, 53.65rem), 100%);
    margin-inline: auto;
  }

  .content-width-medium {
    inline-size: min(90ch, 100%);
    margin-inline: auto;
  }

  .content-width-wide {
    inline-size: min(120ch, 100%);
    margin-inline: auto;
  }

  /* Overflow */
  .overflow-x {
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
  }
  .overflow-y {
    overflow-y: auto;
    scroll-snap-type: y mandatory;
    scroll-behavior: smooth;
  }
  .overflow-clip {
    text-overflow: clip;
    white-space: nowrap;
    overflow: hidden;
  }
  .overflow-ellipsis {
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
  }

  .overflow-hide-scrollbar::-webkit-scrollbar {
    @media (pointer: course) {
      display: none;
    }
  }

  .overflow-line-clamp {
    -webkit-line-clamp: var(--lines, 2);
    -webkit-box-orient: vertical;
    display: -webkit-box;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: normal;
  }

  /* Padding */
  /* Applies standard padding on all sides (vertical: 1rem, horizontal: 1ch) */
  .pad {
    padding: var(--block-space) var(--inline-space);
  }
  .pad-double-large-screens {
    padding: var(--block-space-double) var(--inline-space-double);

    @media (max-width: 50rem) {
      padding: var(--block-space) var(--inline-space);
    }
  }

  /* Applies double padding on all sides (vertical: 2rem, horizontal: 2ch) */
  .pad-double {
    padding: var(--block-space-double) var(--inline-space-double);
  }

  /* Applies standard padding to top and bottom (1rem) */
  .pad-block {
    padding-block: var(--block-space);
  }
  .pad-block-double {
    padding-block: var(--block-space-double);
  }
  /* Applies standard padding to top only (1rem) */
  .pad-block-start {
    padding-block-start: var(--block-space);
  }
  /* Applies standard padding to bottom only (1rem) */
  .pad-block-end {
    padding-block-end: var(--block-space);
  }
  /* Applies half padding to top and bottom (0.5rem) */
  .pad-block-half {
    padding-block: var(--block-space-half);
  }
  .pad-block-third {
    padding-block: var(--block-space-third);
  }
  /* Applies half padding to top only (0.5rem) */
  .pad-block-start-half {
    padding-block-start: var(--block-space-half);
  }

  /* Applies standard padding to left and right (1ch) */
  .pad-inline {
    padding-inline: var(--inline-space);
  }
  .pad-inline-double {
    padding-inline: var(--inline-space-double);
  }
  /* Applies standard padding to left only (1ch) */
  .pad-inline-start {
    padding-inline-start: var(--inline-space);
  }
  /* Applies standard padding to right only (1ch) */
  .pad-inline-end {
    padding-inline-end: var(--inline-space);
  }
  /* Applies half padding to left and right (0.5ch) */
  .pad-inline-half {
    padding-inline: var(--inline-space-half);
  }
  /* Applies double padding to left and right (2ch) */
  .pad-inline-double {
    padding-inline: var(--inline-space-double);
  }

  /* Removes all padding */
  .unpad {
    padding: 0;
  }

  /* Responsive padding that decreases on narrower screens */
  .pad-responsive {
    padding-block: var(--block-space);
    padding-inline: clamp(var(--space-xxs), 3vw, calc(var(--block-space) * 2));
  }

  /* Margins */
  .margin {
    margin: var(--block-space) var(--inline-space);
  }
  .margin-block {
    margin-block: var(--block-space);
  }

  .margin-block-double {
    margin-block: var(--block-space-double);
  }
  .margin-block-half {
    margin-block: var(--block-space-half);
  }
  .margin-block-start {
    margin-block-start: var(--block-space);
  }
  .margin-block-start-half {
    margin-block-start: var(--block-space-half);
  }
  .margin-block-start-third {
    margin-block-start: var(--block-space-third);
  }
  .margin-block-end {
    margin-block-end: var(--block-space);
  }
  .margin-block-end-half {
    margin-block-end: var(--block-space-half);
  }
  .margin-block-end-double {
    margin-block-end: var(--block-space-double);
  }
  .margin-block-start-double {
    margin-block-start: var(--block-space-double);
  }

  .margin-inline {
    margin-inline: var(--inline-space);
  }
  .margin-inline-start {
    margin-inline-start: var(--inline-space);
  }
  .margin-inline-start-half {
    margin-inline-start: var(--inline-space-half);
  }
  .margin-inline-end {
    margin-inline-end: var(--inline-space);
  }
  .margin-inline-end-half {
    margin-inline-end: var(--inline-space-half);
  }
  .margin-inline-half {
    margin-inline: var(--inline-space-half);
  }
  .margin-inline-double {
    margin-inline: var(--inline-space-double);
  }
  .margin-inline-start-double {
    margin-inline-start: var(--inline-space-double);
  }

  .margin-none {
    margin: 0;
  }
  .margin-none-block {
    margin-block: 0;
  }
  .margin-none-block-start {
    margin-block-start: 0;
  }
  .margin-none-block-end {
    margin-block-end: 0;
  }

  .margin-none-inline {
    margin-inline: 0;
  }
  .margin-none-inline-start {
    margin-inline-start: 0;
  }
  .margin-none-inline-end {
    margin-inline-end: 0;
  }

  .center {
    margin-inline: auto;
  }
  .center-block {
    margin-block: auto;
  }

  /* Position */
  .position-relative {
    position: relative;
  }
  .position-sticky {
    position: sticky;
  }
  .position-absolute-top-right {
    position: absolute;
    top: -1rem;
    right: -1rem;
  }

  /* Fills */
  .fill {
    background-color: var(--color-bg);
  }
  .fill-black {
    background-color: var(--color-ink);
  }
  .fill-white {
    background-color: var(--color-ink-reversed);
  }
  .fill-shade {
    background-color: var(--color-gray-light);
  }
  .fill-shade--subtle {
    background-color: var(--color-gray-lightest);
  }
  .fill-selected {
    background-color: var(--color-blue-light);
  }
  .fill-green {
    background-color: var(--color-green-light);
  }
  .fill-yellow {
    background-color: var(--color-yellow-light);
  }
  .fill-red {
    background-color: var(--color-red-lightest);
  }
  .fill-transparent {
    background-color: transparent;
  }

  .translucent {
    opacity: var(--opacity, 0.5);
  }

  /* Borders */
  .border {
    border: var(--border);
  }
  .border-top {
    border-top: var(--border);
  }
  .border-bottom {
    border-bottom: var(--border);
  }
  .borderless {
    border: 0;
  }

  /* Border colors */
  .border-ink {
    border-color: var(--color-ink);
  }
  .border-reversed {
    border-color: var(--color-ink-reversed);
  }
  .border-negative {
    border-color: var(--color-red);
  }
  .border-subtle {
    border-color: var(--color-gray-dark);
  }
  .border-green {
    border-color: var(--color-green);
  }
  .border-link {
    border-color: var(--color-blue);
  }
  .border-yellow {
    border-color: var(--color-yellow);
  }
  .border-red {
    border-color: var(--color-red);
  }
  .border-muted {
    border-color: var(--color-ink-muted);
  }

  /* Border radius */
  .border-radius {
    border-radius: var(--panel-border-radius, 1em);
  }

  .border-radius--small {
    border-radius: var(--border-radius, 1em);
  }

  /* Shadows */
  .shadow {
    box-shadow:
      0 0 0 1px oklch(var(--lch-always-black) / 0.02),
      0 0.2em 1.6em -0.8em oklch(var(--lch-always-black) / 0.2),
      0 0.4em 2.4em -1em oklch(var(--lch-always-black) / 0.3),
      0 0.4em 0.8em -1.2em oklch(var(--lch-always-black) / 0.4),
      0 0.8em 1.2em -1.6em oklch(var(--lch-always-black) / 0.5),
      0 1.2em 1.6em -2em oklch(var(--lch-always-black) / 0.6);

    html[data-theme="dark"] & {
      background-color: var(--color-surface);
      box-shadow:
        0 0 0 1px oklch(var(--lch-always-black) / 0.42),
        0 0.2em 1.6em -0.8em oklch(var(--lch-always-black) / 0.6),
        0 0.4em 2.4em -1em oklch(var(--lch-always-black) / 0.7),
        0 0.4em 0.8em -1.2em oklch(var(--lch-always-black) / 0.8),
        0 0.8em 1.2em -1.6em oklch(var(--lch-always-black) / 0.9),
        0 1.2em 1.6em -2em oklch(var(--lch-always-black) / 1);
    }

    @media (prefers-color-scheme: dark) {
      html:not([data-theme]) & {
        background-color: var(--color-surface);
        box-shadow:
          0 0 0 1px oklch(var(--lch-always-black) / 0.42),
          0 0.2em 1.6em -0.8em oklch(var(--lch-always-black) / 0.6),
          0 0.4em 2.4em -1em oklch(var(--lch-always-black) / 0.7),
          0 0.4em 0.8em -1.2em oklch(var(--lch-always-black) / 0.8),
          0 0.8em 1.2em -1.6em oklch(var(--lch-always-black) / 0.9),
          0 1.2em 1.6em -2em oklch(var(--lch-always-black) / 1);
      }
    }
  }

  .shadow--small {
    box-shadow: var(--shadow-small);
  }

  /* Separators */
  .separator {
    border-block-end: var(--border);
  }

  .separator--dark {
    border-block-end: var(--border-size) solid var(--color-gray-dark);
  }

  /* Spinners */
  .spinner {
    position: relative;

    &::before {
      --mask: no-repeat radial-gradient(#000 68%, #0000 71%);
      --dot-size: 1.25em;

      -webkit-mask: var(--mask), var(--mask), var(--mask);
      -webkit-mask-size: 28% 45%;
      animation: submitting 1.3s infinite linear;
      aspect-ratio: 8/5;
      background: currentColor;
      content: "";
      inline-size: var(--dot-size);
      inset: 50% 0.25em;
      margin-block: calc((var(--dot-size) / 3) * -1);
      margin-inline: calc((var(--dot-size) / 2) * -1);
      position: absolute;
    }
  }

  .spinner-circle {
    display: inline-block;
    inline-size: 1em;
    block-size: 1em;
    border: 2px solid currentColor;
    border-radius: 50%;
    border-block-start-color: transparent;
    animation: spin 0.75s linear infinite;
  }

  @keyframes spin {
    to {
      transform: rotate(360deg);
    }
  }

  /* Accessibility */
  /* Keyboard-only "skip to content" link: parked off-screen until focused. */
  .skip-link {
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: 0;
    z-index: 100;
    padding: var(--block-space-half) var(--inline-space);
    background-color: var(--color-bg);
    color: var(--color-blue);
    transform: translateY(-150%);
  }

  .skip-link:focus {
    transform: translateY(0);
  }

  .for-screen-reader {
    block-size: 1px;
    clip-path: inset(50%);
    inline-size: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
  }

  /* Visibility */
  [hidden] {
    display: none;
  }

  /* Hotkey hints and other pointer-only affordances */
  .hide-on-touch {
    @media (any-hover: none) {
      display: none;
    }
  }

  /* The dock itself is display:none below 70ch, so controls that only open the
     dock (preview eyes) would be dead affordances there — hide them too. */
  .hide-below-dock {
    @media (max-width: 70ch) {
      display: none;
    }
  }
  [contents] {
    display: contents;
  }

  /* Make forms inside flex align-center containers transparent to layout */
  .flex.align-center > form {
    display: contents;
  }

  /* Cursor */
  .cursor-pointer {
    cursor: pointer;
  }
  .handle {
    cursor: move;
  }

  /* Progress bar */
  .progress {
    block-size: 0.5rem;
    background: var(--color-gray);
    border-radius: var(--border-radius);
    overflow: hidden;
  }

  .progress-bar {
    block-size: 100%;
    background: linear-gradient(
      90deg,
      var(--color-green),
      color-mix(in oklch, var(--color-green), white 20%)
    );
    transition: inline-size 0.3s ease;
  }

  /* Simple format inline - removes margin from p tags inside simple_format */
  .simple-format-inline p {
    margin: 0;
  }

  /* Simple format - flush first paragraph against the wrapper top, preserve
     inner paragraph spacing and natural bottom margin for separation from
     following content. */
  .simple-format > p:first-child {
    margin-block-start: 0;
  }

  /* Lists */
  /* Removes the default list indentation; markers stay flush with the text */
  .list-flush {
    padding-inline-start: 0;
    list-style-position: inside;
  }

  /* Colorize filters */
  .colorize--white {
    filter: invert(1);
  }

  .colorize--black {
    filter: invert(0);
  }

  .color-sustainability {
    color: var(--color-green);
  }
}
