/* btn3d.css — buttons that look pressable and answer when you press them.
 *
 * Three things, in order of how much they matter:
 *   1. A resting edge, so a button reads as a raised object rather than a coloured box.
 *   2. A lift on hover and a real press on :active — the press is the important one.
 *      A control that does not move when clicked feels broken on a slow connection,
 *      which is exactly when people click twice.
 *   3. A sheen that crosses on hover. Decorative, and deliberately quiet.
 *
 * SCOPE. Marketing `.btn` gets all three. App `.bt` gets the press and a smaller lift
 * and no sheen: a console is used all day, and a dashboard that glitters is tiring.
 *
 * WHAT IS DELIBERATELY LEFT ALONE:
 *   - `prefers-reduced-motion` disables every transition and transform. Motion is a
 *     genuine accessibility problem, not a taste, and this is a whole page of it.
 *   - `:disabled` / `[aria-busy]` never lift or press. A disabled control that responds
 *     to a hover is telling the person something untrue.
 *   - `:focus-visible` keeps its outline, and the ring is drawn OUTSIDE the transform so
 *     it does not shift under a keyboard user mid-focus.
 *   - No `overflow:hidden` on `.menu-btn`, `.theme-toggle` or anything that owns a
 *     popup — clipping a dropdown to its own trigger would hide the menu entirely.
 */

/* --- marketing --------------------------------------------------------------- */
.btn,
a.btn,
button.btn {
  position: relative;
  transform: translateZ(0);                    /* own layer: no repaint flicker on hover */
  transition: transform .16s cubic-bezier(.2,.7,.3,1),
              box-shadow .16s cubic-bezier(.2,.7,.3,1),
              filter .16s ease;
  will-change: transform;
}

/* The resting edge. Two shadows: a tight one for the lip, a soft one for the ground. */
.btn:not(.btn-ghost):not(:disabled) {
  box-shadow: 0 1px 0 rgba(255,255,255,.14) inset,
              0 2px 0 rgba(0,0,0,.18),
              0 4px 10px rgba(0,0,0,.14);
}

.btn:not(:disabled):hover {
  transform: translateY(-2px);
  filter: saturate(1.06) brightness(1.03);
}
.btn:not(.btn-ghost):not(:disabled):hover {
  box-shadow: 0 1px 0 rgba(255,255,255,.18) inset,
              0 4px 0 rgba(0,0,0,.20),
              0 10px 22px rgba(0,0,0,.20);
}

/* The press. Travels further than the hover lift, so the click is unmistakable. */
.btn:not(:disabled):active {
  transform: translateY(1px) scale(.985);
  transition-duration: .06s;                   /* fast down, eased back up */
}
.btn:not(.btn-ghost):not(:disabled):active {
  box-shadow: 0 1px 0 rgba(255,255,255,.10) inset,
              0 1px 0 rgba(0,0,0,.22),
              0 2px 6px rgba(0,0,0,.18);
}

/* The sheen. Only on solid marketing buttons — a ghost button has nothing to sweep. */
.btn:not(.btn-ghost):not(:disabled)::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;                        /* never eat the click */
  background: linear-gradient(105deg, transparent 38%, rgba(255,255,255,.28) 50%, transparent 62%);
  background-size: 260% 100%;
  background-position: 130% 0;
  opacity: 0;
  transition: background-position .55s cubic-bezier(.2,.7,.3,1), opacity .2s ease;
}
.btn:not(.btn-ghost):not(:disabled):hover::after { background-position: -30% 0; opacity: 1; }

/* Focus ring stays put and stays visible through the transform. */
.btn:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }

/* A button that cannot be used must not behave like one that can. */
.btn:disabled,
.btn[aria-disabled="true"],
.btn[aria-busy="true"] {
  transform: none !important;
  filter: none !important;
  box-shadow: none;
}
.btn:disabled::after,
.btn[aria-disabled="true"]::after,
.btn[aria-busy="true"]::after { content: none; }

/* --- app console ------------------------------------------------------------- */
/* Quieter on purpose: this is a tool people use for hours. */
.bt {
  transition: transform .14s cubic-bezier(.2,.7,.3,1), box-shadow .14s ease, filter .14s ease;
}
.bt:not(:disabled):hover  { transform: translateY(-1px); filter: brightness(1.04); }
.bt:not(:disabled):active { transform: translateY(1px) scale(.99); transition-duration: .05s; }
.bt.primary:not(:disabled) { box-shadow: 0 1px 0 rgba(0,0,0,.14), 0 3px 8px rgba(0,0,0,.14); }
.bt.primary:not(:disabled):hover { box-shadow: 0 2px 0 rgba(0,0,0,.16), 0 7px 16px rgba(0,0,0,.18); }
.bt.primary:not(:disabled):active { box-shadow: 0 1px 0 rgba(0,0,0,.16), 0 2px 5px rgba(0,0,0,.14); }
.bt:disabled, .bt[aria-busy="true"] { transform: none !important; filter: none !important; }

/* --- reduced motion ---------------------------------------------------------- */
/* Not a softening: everything above is switched off. */
@media (prefers-reduced-motion: reduce) {
  .btn, .btn::after, .bt {
    transition: none !important;
    animation: none !important;
  }
  .btn:hover, .btn:active, .bt:hover, .bt:active {
    transform: none !important;
  }
  .btn:not(.btn-ghost):not(:disabled)::after { content: none; }
}

/* --- coarse pointers --------------------------------------------------------- */
/* :hover sticks on touch until you tap elsewhere, so a phone would keep the lift and
   the sheen on the last button tapped. Keep the press; drop the rest. */
@media (hover: none) {
  .btn:hover  { transform: none; filter: none; }
  .btn:not(.btn-ghost):not(:disabled)::after { content: none; }
  .bt:hover   { transform: none; filter: none; }
}
