/* styles/actions.css
 * One action system: buttons, arrow links, CLI links, text links, CTA pairs. Values come
 * from the actions board (r9m4P).
 * Buttons are 44px tall. Arrow links get a 44px hit area from ::before (13px above and below,
 * 10px to each side), so the visual stays 18px and layout never shifts; add .hit-24 where
 * controls sit closer than 44px apart (3px extension, 24px floor). Focus ring comes from
 * utilities.css (:focus-visible); inverse variants set --focus-ring to mist themselves so
 * they work on any fern surface.
 * State precedence: disabled and busy suppress hover and active. Active, open and current
 * share the pressed treatment and override hover. The focus ring draws on top of all states.
 * Disabled controls drop to 0.42 opacity, lose underline and arrow motion, show
 * not-allowed and ignore pointer events; links without href lose their extended hit area.
 * Markup: use <a href> for navigation and <button> only for in-page actions. Arrow, terminal
 * and spinner icons are CSS masks of the board's exported icons (aria-hidden by
 * construction); a link that opens a new tab says so in its name. */
@layer actions {
  /* The board draws these focus rings 2px from the control (utilities.css reads it). */
  .btn,
  .arrow-link,
  .cli-link,
  .text-link {
    --focus-offset: 2px;
  }

  /* Buttons */
  .btn {
    position: relative;
    isolation: isolate;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-8);
    min-height: 44px;

    /* 1px transparent border + 19px = the board's 20px side padding. The border keeps the
       button outlined in forced colors. */
    padding: 0 19px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    font-family: var(--font-body);
    font-size: 15px;
    font-weight: 600;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color var(--dur-fast), border-color var(--dur-fast), color var(--dur-fast), box-shadow var(--dur-fast);
  }

  .btn--primary {
    --btn-pressed-fill: var(--fern-pressed);
    --btn-pressed-shadow: var(--shadow-btn-pressed);

    background: var(--fern);
    color: var(--white);
  }

  .btn--secondary {
    background: var(--white);
    border-color: var(--rule-edge);
    color: var(--ink);
  }

  .btn--inverse {
    --focus-ring: var(--mist);
    --btn-pressed-fill: var(--mint-pressed);
    --btn-pressed-shadow: var(--shadow-btn-pressed-inverse);

    background: var(--white);
    color: var(--fern);
  }

  @media (hover: hover) {
    .btn--primary:hover:not([disabled], [aria-disabled="true"], [aria-busy="true"]) {
      background: var(--fern-hover);
      box-shadow: var(--shadow-btn-hover);
    }

    .btn--secondary:hover:not([disabled], [aria-disabled="true"], [aria-busy="true"]) {
      background: var(--paper);
      border-color: var(--ink);
      box-shadow: var(--elevation-subtle);
    }

    .btn--inverse:hover:not([disabled], [aria-disabled="true"], [aria-busy="true"]) {
      background: var(--mint);
      box-shadow: var(--shadow-btn-hover-inverse);
    }
  }

  .btn--primary:active:not([disabled], [aria-disabled="true"], [aria-busy="true"]) {
    background: var(--fern-pressed);
    box-shadow: var(--shadow-btn-pressed);
  }

  .btn--secondary:active:not([disabled], [aria-disabled="true"], [aria-busy="true"]) {
    background: var(--mist);
    border-color: var(--ink);
    box-shadow: inset 0 2px 4px var(--line);
  }

  .btn--inverse:active:not([disabled], [aria-disabled="true"], [aria-busy="true"]) {
    background: var(--mint-pressed);
    box-shadow: var(--shadow-btn-pressed-inverse);
  }

  /* Press: the fill sinks to 41px tall and 4px narrower with radius 4 (the board's pressed
     cell) while the box keeps its 44px footprint, so nothing around it moves and the label
     keeps its size. The fill is an ::after inset 0.5px 1px inside the 1px border (1.5px and
     2px from the edge): whole device pixels at 2x, where a 1.5px border would round to 1px. */
  @media (prefers-reduced-motion: no-preference) {
    .btn:is(.btn--primary, .btn--inverse):active:not([disabled], [aria-disabled="true"], [aria-busy="true"]) {
      background: transparent;
      box-shadow: none;
      transition: none;
    }

    .btn:is(.btn--primary, .btn--inverse):active:not([disabled], [aria-disabled="true"], [aria-busy="true"])::after {
      content: "";
      position: absolute;
      inset: 0.5px 1px;
      z-index: -1;
      border-radius: var(--radius-sm);
      background: var(--btn-pressed-fill);
      box-shadow: var(--btn-pressed-shadow);
    }
  }

  /* Busy keeps its width and exposes aria-busy. Swap the label to "Loading…" in markup. */
  .btn[aria-busy="true"] {
    font-weight: 500;
  }

  .btn--inverse[aria-busy="true"] {
    background: var(--mist);
  }

  .btn[aria-busy="true"]::before {
    content: "";
    flex: none;
    width: 16px;
    height: 16px;
    background: currentcolor;
    mask: url("/assets/figures/ds/loader-circle.svg") center / contain no-repeat;
    animation: btn-spin 800ms linear infinite;
  }

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

  /* Arrow links: an 18px text link with a hover chip. The chip's padding is offset with
     negative margin, so the text never moves. */
  /* Either may be a <button>: drop the native button chrome. */
  .arrow-link,
  .cli-link {
    position: relative;
    display: inline-flex;
    align-items: center;
    border: 0;
    background: none;
    font-family: var(--font-body);
    font-size: 15px;
    font-weight: 600;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--dur-fast), color var(--dur-fast);
  }

  .arrow-link {
    --hit-extend: 13px;

    gap: 6px;
    padding: 0;
    border-radius: 2px;
  }

  .arrow-link.hit-24 {
    --hit-extend: 3px;
  }

  .arrow-link::before {
    content: "";
    position: absolute;
    inset: calc(-1 * var(--hit-extend)) -10px;
  }

  .arrow-link::after {
    content: "";
    flex: none;
    width: 16px;
    height: 16px;
    background: currentcolor;
    mask: url("/assets/figures/ds/arrow-right.svg") center / contain no-repeat;
    transition: transform var(--dur-fast);
  }

  .arrow-link--dark,
  .arrow-link--fern {
    --chip: var(--mint);
    --chip-text: var(--fern);
    --chip-pressed: var(--fern);
    --chip-pressed-text: var(--white);
  }

  .arrow-link--dark {
    color: var(--ink);
  }

  .arrow-link--fern {
    color: var(--fern);
  }

  .arrow-link--light,
  .arrow-link--muted {
    --focus-ring: var(--mist);
    --chip: var(--white-25);
    --chip-text: var(--white);
    --chip-pressed: var(--white);
    --chip-pressed-text: var(--fern);
  }

  .arrow-link--light {
    color: var(--white);
  }

  .arrow-link--muted {
    color: var(--white-70);
    font-weight: 400;
  }

  .arrow-link--muted::after {
    width: 14px;
    height: 14px;
  }

  /* Hover and pressed draw the 6 x 10 chip; the arrow moves 4px right inside it. */
  @media (hover: hover) {
    .arrow-link:hover:not([disabled], [aria-disabled="true"]) {
      padding: 6px 10px;
      margin: -6px -10px;
      border-radius: var(--radius-sm);
      background: var(--chip);
      color: var(--chip-text);
    }
  }

  .arrow-link:is(:active, [aria-expanded="true"], [aria-current="page"]):not([disabled], [aria-disabled="true"]) {
    padding: 6px 10px;
    margin: -6px -10px;
    border-radius: var(--radius-sm);
    background: var(--chip-pressed);
    color: var(--chip-pressed-text);
  }

  @media (hover: hover) and (prefers-reduced-motion: no-preference) {
    .arrow-link:hover:not([disabled], [aria-disabled="true"])::after {
      transform: translateX(4px);
    }

    .arrow-link:hover:not([disabled], [aria-disabled="true"]) {
      padding-right: 14px;
      margin-right: -14px;
    }
  }

  @media (prefers-reduced-motion: no-preference) {
    .arrow-link:is(:active, [aria-expanded="true"], [aria-current="page"]):not([disabled], [aria-disabled="true"])::after {
      transform: translateX(4px);
    }

    .arrow-link:is(:active, [aria-expanded="true"], [aria-current="page"]):not([disabled], [aria-disabled="true"]) {
      padding-right: 14px;
      margin-right: -14px;
    }
  }

  /* CLI links: terminal icon, 8px gap. The chip padding is offset with negative margin.
     --cli-link-icon swaps the leading icon (a mask url) for an icon-and-label action. */
  .cli-link {
    --hit-extend: 10px;
    --cli-link-icon: url("/assets/figures/ds/terminal.svg");
    --chip: var(--mint);
    --chip-pressed: var(--fern);
    --chip-pressed-text: var(--white);

    gap: var(--space-8);
    padding: 3px 6px;
    margin: -3px -6px;
    border-radius: var(--radius-sm);
    color: var(--ink);
  }

  .cli-link.hit-24 {
    --hit-extend: 0px;
  }

  .cli-link::before {
    content: "";
    position: absolute;
    inset: calc(-1 * var(--hit-extend)) 0;
  }

  .cli-link::after {
    content: "";
    order: -1;
    flex: none;
    width: 16px;
    height: 16px;
    background: currentcolor;
    mask: var(--cli-link-icon) center / contain no-repeat;
  }

  /* Copy variant (<button data-cli-copy>): label and "Copied!" share one grid cell, so the
     width never shifts. js/cli-copy.js adds .is-copied for about two seconds. */
  .cli-link[data-cli-copy] {
    display: inline-grid;
    grid-template-columns: 16px auto;
    align-items: center;
    column-gap: var(--space-8);
    text-align: left;
  }

  .cli-link[data-cli-copy]::after {
    grid-column: 1;
    grid-row: 1;
  }

  .cli-link__label,
  .cli-link__copied {
    grid-column: 2;
    grid-row: 1;
  }

  .cli-link__copied {
    visibility: hidden;
  }

  .cli-link.is-copied .cli-link__label {
    visibility: hidden;
  }

  .cli-link.is-copied .cli-link__copied {
    visibility: visible;
  }

  .cli-link--inverse {
    --focus-ring: var(--mist);
    --chip: var(--white-25);
    --chip-pressed: var(--white);
    --chip-pressed-text: var(--fern);

    border-radius: 6px;
    color: var(--white);
  }

  @media (hover: hover) {
    .cli-link:hover:not([disabled], [aria-disabled="true"]) {
      background: var(--chip);
    }
  }

  .cli-link:active:not([disabled], [aria-disabled="true"]) {
    background: var(--chip-pressed);
    color: var(--chip-pressed-text);
  }

  /* Inline text link: fern 500 with an underline (the board cannot draw underlines; the line
     keeps links distinguishable from ink body text, which fern alone is not). Hover draws a
     6 x 8 mist chip in ink 600 that replaces the underline. Visited is magenta; browsers
     allow only color on :visited. Use on classed links; bare <a> in prose is already
     underlined by reset.css. */
  .text-link {
    border-radius: 1px;
    color: var(--fern);
    font-weight: 500;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
    transition: background-color var(--dur-fast);
  }

  .text-link:visited {
    color: var(--magenta);
  }

  /* Inverse is not drawn on the board: it inherits the surface color and weight. */
  .text-link--inverse {
    --focus-ring: var(--mist);

    padding: 1px 3px;
    margin: -1px -3px;
    border-radius: var(--radius-sm);
    color: inherit;
    font-weight: inherit;
  }

  .text-link--inverse:visited {
    color: inherit;
  }

  @media (hover: hover) {
    .text-link:not(.text-link--inverse):hover {
      padding: 6px 8px;
      margin: -6px -8px;
      border-radius: var(--radius-sm);
      background: var(--mist);
      color: var(--ink);
      font-weight: 600;
      text-decoration: none;
    }

    .text-link--inverse:hover {
      background: var(--white-25);
      text-decoration-thickness: 2px;
    }
  }

  .text-link:active:not([aria-disabled="true"]) {
    background: var(--fern);
    color: var(--white);
  }

  .text-link--inverse:active:not([aria-disabled="true"]) {
    background: var(--white);
    color: var(--fern);
  }

  /* CTA pair: primary action plus a secondary arrow link, 24px apart. Inherits every state
     from its members. The fern pair takes inverse button and light arrow link members and
     sets the mist focus ring for any bare member. */
  .cta-pair {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-16) var(--space-24);
  }

  .cta-pair--fern {
    --focus-ring: var(--mist);
  }

  /* Disabled: opacity alone is not the cue. Underline and arrow motion go too. Links
     without href are not interactive, so the extended hit area goes as well (a <button>
     keeps it; a disabled one ignores pointer events). */
  .btn:is([disabled], [aria-disabled="true"]),
  .arrow-link:is([disabled], [aria-disabled="true"]),
  .cli-link:is([disabled], [aria-disabled="true"]),
  .text-link:is([disabled], [aria-disabled="true"]) {
    opacity: 0.42;
    cursor: not-allowed;
    pointer-events: none;
    box-shadow: none;
    transform: none;
    text-decoration: none;
  }

  .arrow-link:is([disabled], [aria-disabled="true"])::after {
    transform: none;
  }

  .arrow-link:not([href], button)::before,
  .cli-link:not([href], button)::before {
    content: none;
  }

  @media (forced-colors: active) {
    .btn {
      border-color: ButtonText;
    }

    .arrow-link::after,
    .cli-link::after,
    .btn[aria-busy="true"]::before {
      background: CanvasText;
      forced-color-adjust: none;
    }
  }
}
