/* Button. The press feedback lives here, so every button in the product feels
   the same and a skin can only change colour, not behaviour.
   DESIGN.md section 4 (Buttons) and section 9.2 (micro-interactions). */

@layer components {
  .btn {
    --btn-bg: var(--surface-2);
    --btn-fg: var(--text);
    --btn-border: var(--border);

    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-height: calc(44px * var(--ui-scale));               /* touch target; DESIGN.md section 7 */
    /* Roomier than it was (6px/15px), after v2's `0.85rem 1.5rem`. The
       min-height still governs the box; what this buys is horizontal air
       around a mono label, which needs more of it than a body-font one. */
    padding: var(--space-3) var(--space-6);
    border: 1px solid var(--btn-border);
    border-radius: var(--btn-radius);
    background: var(--btn-bg);
    /* The default and secondary grounds are translucent, so what is behind
       them gets blurred - the label never does, which is the whole reason this
       is `backdrop-filter` and not `filter`. The opaque and transparent
       variants below switch it off rather than paying for a layer that cannot
       show. */
    backdrop-filter: var(--glass-filter);
    color: var(--btn-fg);
    /* MONO, TRACKED, SQUARE (owner, 2026-10-05: "capture button styling from
       the example"). The v2 sheet sets every button in the mono face with
       0.08em of tracking and no radius at all - anka's filled-and-outlined
       pairing - and that shape is most of what separates its chrome from the
       rounded, body-font buttons this product shipped with.

       What is NOT taken from the example is the colour. v2's filled button is
       ink-on-background, near-white; this product's `--primary` is the accent,
       and `DESIGN.md` section 5 rule 5 gives a page exactly one of those. The
       hero CTA stays the accent it has always been, so the variants keep
       meaning what they mean. Shape, face, tracking and motion are the
       example's; the palette is still the product's. */
    font: inherit;
    font-family: var(--font-mono);
    letter-spacing: 0.08em;
    font-weight: 500;
    line-height: 1.2;
    text-decoration: none;          /* a .btn may be an <a>; it is still a button */
    white-space: nowrap;            /* a CTA never wraps to two lines */
    cursor: pointer;
    position: relative;
    transition:
      transform var(--dur-2) var(--ease-spring),
      background-color var(--dur-2) var(--ease-out),
      border-color var(--dur-2) var(--ease-out),
      color var(--dur-2) var(--ease-out);
  }

  /* The lift is v2's: 2px, not the 1px this had. At one pixel on a square
     button the gesture reads as a rendering wobble rather than as a
     response. */
  .btn:hover:not(:disabled) {
    transform: translateY(calc(var(--motion, 1) * -2px));
    background: color-mix(in oklab, var(--btn-bg) 92%, var(--text));
  }

  /* Press: faster in, spring out. data-pressed mirrors :active for touch. */
  .btn:active:not(:disabled),
  .btn[data-pressed]:not(:disabled) {
    transform: scale(calc(1 - var(--motion, 1) * 0.03));
    transition-duration: var(--dur-1);
    transition-timing-function: var(--ease-out);
  }

  /* The ring blooms from the edge rather than snapping into place. */
  .btn:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 3px;
    transition: outline-offset var(--dur-2) var(--ease-out);
  }

  .btn:disabled,
  .btn[aria-disabled="true"] {
    opacity: 0.55;
    cursor: not-allowed;
    transform: none;
  }

  .btn--primary {
    --btn-bg: var(--accent);
    --btn-fg: var(--text-on-accent);
    --btn-border: transparent;
    backdrop-filter: none;            /* a filled accent hides its backdrop completely */
    font-weight: 600;
  }

  /* Outlined, per DESIGN.md section 4. Ten call sites across dialogs, the
     store, sales, custom types and the timeline editor already asked for this
     class and there was no rule for it, so every "secondary" action in the
     product rendered as the filled default and the variant meant nothing.

     The ground is `--surface-1`, not `transparent`, which is a deliberate
     reading of "outlined" rather than a departure from it: the hairline still
     carries the variant, but a fully transparent button on this skin puts the
     star field behind its label, and the owner hit that on `+ New component` and
     asked for "semi-transparent black with a thin border" (2026-09-10), then
     generalised it to every UI element (2026-09-11). The border stays lifted
     off `--border` so secondary still reads as outlined against the plane it
     sits on rather than as a second filled button. */
  /* RE-AIMED AT v2 (owner, 2026-10-05: "the rest of the buttons with the
     outline dont match the buttons in the v2 example").

     Measured against the example, two things differed and both are here. The
     ground was `--surface-1` - a 78%-opaque dark fill with a 6px backdrop
     blur behind it - where v2's outlined button is simply TRANSPARENT; and
     the hover brightened that fill while leaving the border alone, where v2
     does the opposite and brightens the border to full ink. An outlined
     button whose outline does not respond on hover is a filled button with a
     line around it.

     THIS SUPERSEDES THE 2026-09-10 RULING, at the owner's instruction. The
     paragraph that used to be here recorded them asking for "semi-transparent
     black with a thin border" after a fully transparent `+ New component` put the
     star field behind its label. That risk is real and has not gone away -
     what has changed is that the owner has now seen both and chosen the
     example's. If a label is ever hard to read over the sky again, the fix is
     a faint ground on THIS rule, not a return to a filled button.

     `.btn--primary` is deliberately untouched: "i like the current [keep
     writing] button so leave it alone for now". */
  .btn--secondary {
    --btn-bg: transparent;
    --btn-fg: var(--text);
    --btn-border: color-mix(in oklab, var(--text) 35%, transparent);
    /* No ground, so nothing to blur - a blur here would soft-focus a
       rectangle of page with nothing drawn over it. */
    backdrop-filter: none;
  }

  /* The border is what responds, and the ground stays out of it. The base
     rule brightens `--btn-bg` toward the ink, which over `transparent` still
     lays down an 8% wash; v2 lays down none. */
  .btn--secondary:hover:not(:disabled) {
    background: transparent;
    --btn-border: var(--text);
  }

  .btn--danger {
    --btn-bg: var(--danger);
    --btn-fg: var(--text-on-accent);
    --btn-border: transparent;
    backdrop-filter: none;            /* a filled accent hides its backdrop completely */
  }

  .btn--ghost {
    --btn-bg: transparent;
    --btn-border: transparent;
    color: var(--text-muted);
    /* A ghost has no ground at all, so a blur here would put a soft-focus
       rectangle on the page with nothing drawn over it - the effect reads as
       a rendering fault rather than as glass. */
    backdrop-filter: none;
  }
  .btn--ghost:hover:not(:disabled) { color: var(--text); background: var(--surface-2); }

  .btn--block { width: 100%; }
  /* The small button keeps its height - `.desk-panel__head` floors itself on
     this same expression so the quiet band's three heads stay level - and
     takes the roomier horizontal padding in proportion. */
  .btn--sm { min-height: calc(32px * var(--ui-scale)); padding: var(--space-1) var(--space-4); font-size: var(--text-sm); }

  /* Loading keeps the label and its width; it never becomes a bare spinner. */
  .btn__spinner {
    width: 1em;
    height: 1em;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: btn-spin 700ms linear infinite;
  }
  @keyframes btn-spin { to { transform: rotate(360deg); } }

  @media (prefers-reduced-motion: reduce) {
    .btn { transition: background-color var(--dur-2), color var(--dur-2); }
    .btn:hover:not(:disabled), .btn:active:not(:disabled) { transform: none; }
    .btn__spinner { animation: none; border-top-color: currentColor; opacity: 0.6; }
  }
}
