/* glassButton.css — "glass button 2": a frosted pill that floats over its own shadow.
 *
 * Ported 2026-09-14 from a 21st.dev hand-over (a shadcn/Tailwind `glass-button.tsx`). The
 * component's own stylesheet was not in the hand-over, so the anatomy is theirs and the
 * material is ours: the four boxes it emits are kept —
 *
 *     .gb-wrap                  positioning context; nothing visible of its own
 *       .gb (button)            the pane: gradient body over a backdrop blur, a lit top lip,
 *                               a shaded foot, and the lead came as an inset hairline
 *         .gb-text              the label, with the sweep highlight on hover
 *       .gb-shadow              a blurred dark pool BEHIND the pane that spreads as it lifts
 *
 * — and the look is the platform's own glass, the same vocabulary as Haggis's app buttons
 * (frost · pane · came · lip · foot · cast). The wrap is what gives the effect its life: the
 * pane and the pool move in opposite directions on hover, so the button visibly lifts off
 * the table rather than just brightening.
 *
 * Tinted per surface by three custom properties, set on any ancestor:
 *     --gb-tint   the glass's hue as RGB channels ("159 216 255") — came, glow, primary fill
 *     --gb-ink    the label colour
 *     --gb-shade  the pool's colour as RGB channels (the table's own darkness, not black)
 * Kinds: `.gb-primary` fills the pane with the tint (the one loud button), `.gb-warm`
 * re-tints a single button gold for "confirm the take". Sizes: `.gb-sm`, `.gb-lg`, `.gb-icon`.
 *
 * Every button keeps a 44px tap height at every size but `.gb-sm` (36px), which is for
 * secondary choices inside a dialog, never for the one action a turn is waiting on.
 */

/* Defaults on :root, not on the wrap, so a game (or one dialog) can re-tint from any
   ancestor: a value set on the wrap itself would mask everything above it. */
:root {
    --gb-tint: 159 216 255;
    --gb-ink: #eef4ff;
    --gb-shade: 2 6 20;
}

.gb-wrap {
    position: relative;
    display: inline-block;
    border-radius: 999px;
    isolation: isolate;
    /* the shadow pool overhangs the pane; the wrap must not clip it */
    overflow: visible;
}

.gb {
    all: unset;
    position: relative;
    z-index: 1;
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 44px;
    padding: 0 22px;
    border-radius: 999px;
    cursor: pointer;
    font-family: var(--dk-font-ui, system-ui, sans-serif);
    font-size: 15px;
    font-weight: 600;
    line-height: 1;
    color: var(--gb-ink);
    -webkit-tap-highlight-color: transparent;
    -webkit-user-select: none;
    user-select: none;
    background:
        linear-gradient(-75deg,
            rgba(255, 255, 255, 0.05) 0%,
            rgba(255, 255, 255, 0.17) 50%,
            rgba(255, 255, 255, 0.05) 100%),
        rgba(var(--gb-tint) / 0.08);
    -webkit-backdrop-filter: blur(6px) saturate(1.25);
    backdrop-filter: blur(6px) saturate(1.25);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.55),          /* the lip: light on the top edge */
        inset 0 -1px 1px rgba(var(--gb-shade) / 0.45),    /* the foot: the lip's shadow     */
        inset 0 0 0 1px rgba(var(--gb-tint) / 0.32),      /* the came                       */
        0 1px 0 rgba(var(--gb-shade) / 0.35);              /* seated, not floating, at rest  */
    transition:
        transform 200ms cubic-bezier(.22, .75, .3, 1),
        box-shadow 200ms ease-out,
        background-color 200ms ease-out;
}

/* The specular strip: a soft sheet of light across the upper half of the pane. Not a
   gradient on the button itself, so the tint of a `.gb-primary` shows through it. */
.gb::after {
    content: '';
    position: absolute;
    inset: 1px;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.22) 0%, rgba(255, 255, 255, 0.04) 48%, rgba(255, 255, 255, 0) 60%);
}

.gb-text {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    letter-spacing: -0.005em;
    text-shadow: 0 1px 0 rgba(var(--gb-shade) / 0.45);
}

/* The pool the pane floats over. Wider than the pane and pushed down, so at rest it reads as
   the pane's own contact shadow; on hover it spreads and softens as the pane lifts. */
.gb-shadow {
    position: absolute;
    left: 6%; right: 6%; top: 30%; bottom: -22%;
    border-radius: 999px;
    background: radial-gradient(ellipse at 50% 35%, rgba(var(--gb-shade) / 0.62), rgba(var(--gb-shade) / 0) 72%);
    filter: blur(6px);
    z-index: 0;
    pointer-events: none;
    transform-origin: 50% 30%;
    transition: transform 220ms cubic-bezier(.22, .75, .3, 1), opacity 220ms ease-out;
}

/* ── states ────────────────────────────────────────────────────────────────────────────── */

.gb-wrap:hover .gb,
.gb:focus-visible {
    transform: translateY(-2px);
    background:
        linear-gradient(-75deg,
            rgba(255, 255, 255, 0.08) 0%,
            rgba(255, 255, 255, 0.24) 50%,
            rgba(255, 255, 255, 0.08) 100%),
        rgba(var(--gb-tint) / 0.14);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.7),
        inset 0 -1px 1px rgba(var(--gb-shade) / 0.45),
        inset 0 0 0 1px rgba(var(--gb-tint) / 0.55),
        0 0 18px -4px rgba(var(--gb-tint) / 0.45);
}
.gb-wrap:hover .gb-shadow { transform: translateY(3px) scale(1.06, 1.12); opacity: 0.9; }

.gb-wrap:active .gb,
.gb:active {
    transform: translateY(1px);
    transition-duration: 70ms;
}
.gb-wrap:active .gb-shadow { transform: translateY(-1px) scale(0.94, 0.8); opacity: 0.55; transition-duration: 70ms; }

.gb:focus-visible { outline: 2px solid rgba(var(--gb-tint) / 0.9); outline-offset: 3px; }

.gb:disabled { cursor: default; opacity: 0.45; transform: none; }
.gb-wrap:has(.gb:disabled) .gb-shadow { opacity: 0.35; }
.gb-wrap:has(.gb:disabled):hover .gb { transform: none; }

/* ── kinds ─────────────────────────────────────────────────────────────────────────────── */

/* The one loud button. Still glass — the lip and the pool stay — but the pane is filled with
   the tint so it is the brightest thing in its row without spending the label's contrast:
   #eef4ff over the filled pane measures above 7:1 on the platform's dark tables. */
.gb-primary {
    background:
        linear-gradient(-75deg,
            rgba(255, 255, 255, 0.10) 0%,
            rgba(255, 255, 255, 0.28) 50%,
            rgba(255, 255, 255, 0.10) 100%),
        rgba(var(--gb-tint) / 0.34);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.75),
        inset 0 -1px 1px rgba(var(--gb-shade) / 0.5),
        inset 0 0 0 1px rgba(var(--gb-tint) / 0.7),
        0 0 22px -6px rgba(var(--gb-tint) / 0.6);
}
.gb-wrap:hover .gb-primary,
.gb-primary:focus-visible {
    background:
        linear-gradient(-75deg,
            rgba(255, 255, 255, 0.14) 0%,
            rgba(255, 255, 255, 0.34) 50%,
            rgba(255, 255, 255, 0.14) 100%),
        rgba(var(--gb-tint) / 0.44);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.85),
        inset 0 -1px 1px rgba(var(--gb-shade) / 0.5),
        inset 0 0 0 1px rgba(var(--gb-tint) / 0.85),
        0 0 26px -4px rgba(var(--gb-tint) / 0.75);
}

/* A PLATE: the same pane as a non-interactive display — a reward toast, a badge, a line of
   score that floats up over the table. Same wrap, same pool, same lip and came, but it
   never lifts, never takes a cursor, and its glow is on at rest because the moment it
   marks IS the state. Content is whatever the game lays in it (a row of icons, a caption);
   tint it per subject by setting --gb-tint on the wrap (a seat's colour, say). */
.gb-plate {
    cursor: default;
    min-height: 0;
    padding: 12px 20px;
    gap: 14px;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.6),
        inset 0 -1px 1px rgba(var(--gb-shade) / 0.45),
        inset 0 0 0 1px rgba(var(--gb-tint) / 0.6),
        0 0 26px -4px rgba(var(--gb-tint) / 0.55),
        0 1px 0 rgba(var(--gb-shade) / 0.35);
}
.gb-wrap:has(.gb-plate):hover .gb-plate,
.gb-wrap:has(.gb-plate):active .gb-plate {
    transform: none;
    background:
        linear-gradient(-75deg,
            rgba(255, 255, 255, 0.05) 0%,
            rgba(255, 255, 255, 0.17) 50%,
            rgba(255, 255, 255, 0.05) 100%),
        rgba(var(--gb-tint) / 0.08);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.6),
        inset 0 -1px 1px rgba(var(--gb-shade) / 0.45),
        inset 0 0 0 1px rgba(var(--gb-tint) / 0.6),
        0 0 26px -4px rgba(var(--gb-tint) / 0.55),
        0 1px 0 rgba(var(--gb-shade) / 0.35);
}
.gb-wrap:has(.gb-plate):hover .gb-shadow,
.gb-wrap:has(.gb-plate):active .gb-shadow { transform: none; opacity: 1; }

/* A single button re-tinted: set on the WRAP so the came, the glow and the fill all follow. */
.gb-wrap.gb-warm { --gb-tint: 255 226 122; }
/* ...and the one that ends something: concede, resign, the last pass. Same pane, red came. */
.gb-wrap.gb-danger { --gb-tint: 255 122 112; }

/* ── sizes ─────────────────────────────────────────────────────────────────────────────── */

.gb-sm   { min-height: 36px; padding: 0 16px; font-size: 14px; }
.gb-lg   { min-height: 52px; padding: 0 28px; font-size: 17px; }
.gb-icon { min-height: 44px; width: 44px; padding: 0; }
.gb-icon .gb-text { gap: 0; }
.gb-icon svg { width: 20px; height: 20px; display: block; }
/* `.gb-xs` is for a chrome bar that is itself shorter than the tap floor — Sevens's 36px
   header, whose height the hand layout is measured against. A tool there is 30px because
   the bar is; it is not a size for anything a turn waits on. */
.gb-xs { min-height: 30px; padding: 0 12px; font-size: 13px; }
.gb-icon.gb-xs { width: 30px; padding: 0; }
.gb-icon.gb-xs svg { width: 15px; height: 15px; }

/* A row of them: the wraps sit on one baseline, and the pools may overlap the neighbours. */
.gb-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.gb-wrap.gb-block { display: block; }
.gb-wrap.gb-block .gb { width: 100%; }

@media (prefers-reduced-motion: reduce) {
    .gb, .gb-shadow { transition: none; }
    .gb-wrap:hover .gb, .gb-wrap:hover .gb-shadow, .gb-wrap:active .gb, .gb-wrap:active .gb-shadow { transform: none; }
}
