/* ===========================================================================
   GG UI — design tokens + primitive styles.
   Plain CSS on purpose: no build step, no preprocessing. Loaded with a normal
   <link>, so it paints before the Tailwind browser runtime finishes compiling.
   =========================================================================== */

/* ===========================================================================
   ⬇  CHANGE YOUR BRAND HERE  ⬇
   Edit the --brand-* ramp below and the ENTIRE kit re-themes: every button,
   badge, focus ring, chart tint, border beam, header and footer. Nothing else
   hardcodes the colour — components only ever reference --primary/--accent,
   which are mapped into Tailwind as bg-primary / text-accent / etc.

   Values are R G B channel triplets (not hex) so any rule can apply alpha:
   rgb(var(--primary) / 0.3)
   =========================================================================== */
:root {
    --brand-25: 254 240 235;
    --brand-50: 254 231 222;
    --brand-100: 253 208 191;
    --brand-200: 251 176 148;
    --brand-300: 248 137 100;
    --brand-400: 244 105 62;
    --brand-500: 240 80 37;
    --brand-600: 211 70 33;
    --brand-700: 173 58 27;
    --brand-800: 139 46 21;
    --brand-900: 110 37 17;
    --brand-950: 67 22 10;

    /* Primary is the canonical brand colour. Accent aliases it, so the whole
       component kit (which references --accent) follows automatically. Point
       --accent at a different ramp only if you want a true second colour. */
    --primary: var(--brand-500);
    --primary-hover: var(--brand-400);
    --primary-press: var(--brand-700);

    --accent: var(--primary);
    --accent-hover: var(--primary-hover);
    --accent-press: var(--primary-press);

    --success: 22 163 74;
    --danger: 239 68 68;
    --warning: 245 158 11;
    --info: 37 99 235;

    /* Light surfaces */
    --bg: #f9fafb;
    --surface: #ffffff;
    --surface-raised: #ffffff;
    --surface-sunken: #f3f4f6;
    --surface-high: #e5e7eb;

    --text: 16 24 40;
    --muted: #667085;
    --border: rgb(16 24 40 / 0.16);
    --border-soft: rgb(16 24 40 / 0.11);

    --popover-bg: rgb(255 255 255 / 0.94);
    --popover-border: rgb(0 0 0 / 0.1);
    --popover-shadow: 0 24px 60px rgb(16 24 40 / 0.18);
    --overlay: rgb(16 24 40 / 0.35);

    --card-shadow: 0 1px 0 0 rgb(255 255 255 / 0.6) inset, 0 12px 30px -18px rgb(16 24 40 / 0.45);
    --card-shadow-hover: 0 1px 0 0 rgb(255 255 255 / 0.6) inset, 0 18px 40px -20px rgb(16 24 40 / 0.5);

    /* Radii — tightened one step from the source design for a denser feel. */
    --r-control: 7px;
    --r-input: 9px;
    --r-card: 11px;
    --r-card-lg: 13px;
    --r-panel: 16px;
    --r-pill: 999px;

    --spring: cubic-bezier(0.34, 1.56, 0.64, 1);

    color-scheme: light;
}

.dark {
    --bg: #0c111d;
    --surface: #101828;
    --surface-raised: #1a2233;
    --surface-sunken: #080d16;
    --surface-high: #242e42;

    --text: 242 244 247;
    --muted: #94a3b8;
    --border: rgb(242 244 247 / 0.16);
    --border-soft: rgb(242 244 247 / 0.11);

    --popover-bg: rgb(10 11 26 / 0.9);
    --popover-border: rgb(255 255 255 / 0.1);
    --popover-shadow: 0 32px 80px rgb(0 0 0 / 0.5);
    --overlay: rgb(3 6 14 / 0.7);

    --card-shadow: none;
    --card-shadow-hover: none;

    color-scheme: dark;
}

/* --- Base ---------------------------------------------------------------- */
html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

body {
    margin: 0;
    background-color: var(--bg);
    color: rgb(var(--text));
    font-family: 'Plus Jakarta Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px rgb(var(--accent) / 0.35);
}

/* Browsers default <button> to cursor:default. Anything clickable gets a hand. */
button,
summary,
label[for],
select,
[role='button'],
[role='option'],
[role='tab'],
[role='menuitem'],
a[href] {
    cursor: pointer;
}

button:disabled,
select:disabled,
[aria-disabled='true'],
[data-disabled] {
    cursor: not-allowed;
}

::selection {
    background: rgb(var(--accent) / 0.25);
}

/* Alpine hasn't booted yet — keep popovers from flashing open. */
[x-cloak] {
    display: none !important;
}

/* iOS Safari auto-zooms when a focused field's font-size is below 16px. Bump
   real text fields to 16px on small screens — !important because the Tailwind
   utilities that set 13/14px are class-specificity and would otherwise win.
   (Don't "fix" this with maximum-scale=1; that blocks pinch-zoom entirely.) */
@media screen and (max-width: 767px) {
    input:not([type='checkbox']):not([type='radio']):not([type='hidden']),
    select,
    textarea {
        font-size: 16px !important;
    }
}

/* --- Primitives ---------------------------------------------------------- */
.ui-card-shadow {
    box-shadow: var(--card-shadow);
}

.ui-popover {
    background: var(--popover-bg);
    border: 1px solid var(--popover-border);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    backdrop-filter: blur(20px) saturate(180%);
    box-shadow: var(--popover-shadow);
}

/* Shared field chrome: input, textarea, select, combobox trigger, date trigger */
.ui-field {
    width: 100%;
    background: var(--surface-sunken);
    border: 1px solid var(--border);
    border-radius: var(--r-input);
    color: rgb(var(--text));
    font: inherit;
    transition: border-color 0.18s, box-shadow 0.18s, background 0.18s;
}

.ui-field::placeholder {
    color: var(--muted);
}

.ui-field:hover:not(:disabled):not([data-invalid]):not([data-disabled]) {
    border-color: rgb(var(--text) / 0.28);
}

.ui-field:focus,
.ui-field:focus-within {
    outline: none;
    border-color: rgb(var(--accent) / 0.55);
    box-shadow: 0 0 0 2px rgb(var(--accent) / 0.35);
}

/* When .ui-field is a wrapper (prefix/suffix, combobox, date picker), the
   wrapper draws the focus ring via :focus-within. The inner control must not
   draw its own from the global :focus-visible rule, or the two rings overlap.
   Scoped to form controls so buttons inside keep their focus indicator. */
.ui-field input:focus,
.ui-field input:focus-visible,
.ui-field textarea:focus,
.ui-field textarea:focus-visible,
.ui-field select:focus,
.ui-field select:focus-visible {
    outline: none;
    box-shadow: none;
}

.ui-field[data-invalid] {
    border-color: rgb(var(--danger) / 0.6);
}

.ui-field[data-invalid]:focus,
.ui-field[data-invalid]:focus-within {
    box-shadow: 0 0 0 2px rgb(var(--danger) / 0.3);
}

.ui-field:disabled,
.ui-field[data-disabled] {
    opacity: 0.55;
    cursor: not-allowed;
}

/* Readonly still submits its value, so it stays legible — just visibly
   not-editable, unlike the faded disabled state. */
.ui-field[data-readonly] {
    background: rgb(var(--text) / 0.04);
    border-style: dashed;
}

.ui-field[data-readonly] input {
    cursor: default;
}

/* Native select needs its own arrow since we strip the OS one. */
.ui-select {
    -webkit-appearance: none;
    appearance: none;
    background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
        linear-gradient(135deg, currentColor 50%, transparent 50%);
    background-position: calc(100% - 20px) calc(50% + 2px), calc(100% - 15px) calc(50% + 2px);
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
}

/* --- Tones ---------------------------------------------------------------
   Soft fills for badges and trend pills. The text colour is a *deeper* shade
   than the fill in light mode and a *lighter* one in dark mode — using the raw
   500-level colour on a 12%-alpha fill fails contrast badly for amber & green.
   ------------------------------------------------------------------------- */
:root {
    --tone-neutral-bg: rgb(16 24 40 / 0.07);
    --tone-neutral-fg: #344054;
    --tone-neutral-bd: rgb(16 24 40 / 0.16);

    /* Derived from the brand ramp, so accent badges re-theme with --primary.
       The semantic tones below stay fixed — success should read green whatever
       the brand colour is. */
    --tone-accent-bg: rgb(var(--primary) / 0.11);
    --tone-accent-fg: rgb(var(--brand-700));
    --tone-accent-bd: rgb(var(--primary) / 0.3);

    --tone-success-bg: rgb(22 163 74 / 0.11);
    --tone-success-fg: #15803d;
    --tone-success-bd: rgb(22 163 74 / 0.3);

    --tone-danger-bg: rgb(239 68 68 / 0.11);
    --tone-danger-fg: #b91c1c;
    --tone-danger-bd: rgb(239 68 68 / 0.3);

    --tone-warning-bg: rgb(245 158 11 / 0.14);
    --tone-warning-fg: #b45309;
    --tone-warning-bd: rgb(245 158 11 / 0.38);

    --tone-info-bg: rgb(37 99 235 / 0.11);
    --tone-info-fg: #1d4ed8;
    --tone-info-bd: rgb(37 99 235 / 0.3);
}

.dark {
    --tone-neutral-bg: rgb(242 244 247 / 0.09);
    --tone-neutral-fg: #cbd5e1;
    --tone-neutral-bd: rgb(242 244 247 / 0.18);

    --tone-accent-bg: rgb(var(--primary) / 0.18);
    --tone-accent-fg: rgb(var(--brand-300));
    --tone-accent-bd: rgb(var(--primary) / 0.38);

    --tone-success-bg: rgb(34 197 94 / 0.16);
    --tone-success-fg: #4ade80;
    --tone-success-bd: rgb(34 197 94 / 0.35);

    --tone-danger-bg: rgb(239 68 68 / 0.16);
    --tone-danger-fg: #fca5a5;
    --tone-danger-bd: rgb(239 68 68 / 0.35);

    --tone-warning-bg: rgb(245 158 11 / 0.16);
    --tone-warning-fg: #fcd34d;
    --tone-warning-bd: rgb(245 158 11 / 0.35);

    --tone-info-bg: rgb(59 130 246 / 0.16);
    --tone-info-fg: #93c5fd;
    --tone-info-bd: rgb(59 130 246 / 0.35);
}

.ui-tone-neutral,
.ui-tone-accent,
.ui-tone-success,
.ui-tone-danger,
.ui-tone-warning,
.ui-tone-info {
    background: var(--tone-bg);
    color: var(--tone-fg);
    border-color: var(--tone-bd);
}

.ui-tone-neutral { --tone-bg: var(--tone-neutral-bg); --tone-fg: var(--tone-neutral-fg); --tone-bd: var(--tone-neutral-bd); }
.ui-tone-accent  { --tone-bg: var(--tone-accent-bg);  --tone-fg: var(--tone-accent-fg);  --tone-bd: var(--tone-accent-bd); }
.ui-tone-success { --tone-bg: var(--tone-success-bg); --tone-fg: var(--tone-success-fg); --tone-bd: var(--tone-success-bd); }
.ui-tone-danger  { --tone-bg: var(--tone-danger-bg);  --tone-fg: var(--tone-danger-fg);  --tone-bd: var(--tone-danger-bd); }
.ui-tone-warning { --tone-bg: var(--tone-warning-bg); --tone-fg: var(--tone-warning-fg); --tone-bd: var(--tone-warning-bd); }
.ui-tone-info    { --tone-bg: var(--tone-info-bg);    --tone-fg: var(--tone-info-fg);    --tone-bd: var(--tone-info-bd); }

/* The status dot always uses the full-strength colour, not the text shade. */
.ui-tone-dot { background: var(--tone-dot, currentColor); }
.ui-tone-neutral .ui-tone-dot { --tone-dot: #94a3b8; }
.ui-tone-accent .ui-tone-dot  { --tone-dot: rgb(var(--accent)); }
.ui-tone-success .ui-tone-dot { --tone-dot: rgb(var(--success)); }
.ui-tone-danger .ui-tone-dot  { --tone-dot: rgb(var(--danger)); }
.ui-tone-warning .ui-tone-dot { --tone-dot: rgb(var(--warning)); }
.ui-tone-info .ui-tone-dot    { --tone-dot: rgb(var(--info)); }

/* --- Checkbox / radio ----------------------------------------------------
   Native inputs with the OS chrome stripped, repainted via background-image so
   checked state needs no extra markup and no JS.
   ------------------------------------------------------------------------- */
.ui-check,
.ui-radio {
    -webkit-appearance: none;
    appearance: none;
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    margin: 0;
    background-color: var(--surface-sunken);
    border: 1px solid var(--border);
    background-position: center;
    background-repeat: no-repeat;
    cursor: pointer;
    transition: background-color 0.15s, border-color 0.15s, box-shadow 0.15s;
}

.ui-check {
    border-radius: 6px;
}

.ui-radio {
    border-radius: 50%;
}

.ui-check:hover:not(:disabled),
.ui-radio:hover:not(:disabled) {
    border-color: rgb(var(--accent) / 0.5);
}

.ui-check:checked,
.ui-check:indeterminate,
.ui-radio:checked {
    background-color: rgb(var(--accent));
    border-color: rgb(var(--accent));
}

.ui-check:checked {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='white' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m3 8.5 3.5 3.5L13 5'/%3E%3C/svg%3E");
    background-size: 74%;
}

.ui-check:indeterminate {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='white' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M4 8h8'/%3E%3C/svg%3E");
    background-size: 74%;
}

.ui-radio:checked {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3.25' fill='white'/%3E%3C/svg%3E");
    background-size: 100%;
}

.ui-check:disabled,
.ui-radio:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.ui-scroll {
    scrollbar-width: thin;
    scrollbar-color: rgb(var(--text) / 0.2) transparent;
}

.ui-scroll::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}

.ui-scroll::-webkit-scrollbar-thumb {
    background: rgb(var(--text) / 0.2);
    border-radius: 999px;
}

.ui-scroll::-webkit-scrollbar-track {
    background: transparent;
}

/* Accent glow used on primary buttons and the hero panel. */
.ui-glow {
    box-shadow: 0 4px 20px rgb(var(--accent) / 0.3);
}

.ui-glow-lg {
    box-shadow: 0 8px 28px rgb(var(--accent) / 0.4);
}

/* Concentric rings radiating from a single point — reads as "many things, one
   centre", which is the platform's whole pitch. Masked so it fades out instead
   of terminating in a hard edge. Position with --rings-x / --rings-y. */
.ui-rings-bg {
    background-image: repeating-radial-gradient(
        circle at var(--rings-x, 78%) var(--rings-y, 22%),
        transparent 0 71px,
        var(--border-soft) 71px 72px
    );
    -webkit-mask-image: radial-gradient(
        circle at var(--rings-x, 78%) var(--rings-y, 22%),
        #000 0%,
        rgb(0 0 0 / 0.35) 55%,
        transparent 85%
    );
    mask-image: radial-gradient(
        circle at var(--rings-x, 78%) var(--rings-y, 22%),
        #000 0%,
        rgb(0 0 0 / 0.35) 55%,
        transparent 85%
    );
}

/* Faint grid backdrop for empty states / hero panels. */
.ui-grid-bg {
    background-image: linear-gradient(to right, var(--border-soft) 1px, transparent 1px),
        linear-gradient(to bottom, var(--border-soft) 1px, transparent 1px);
    background-size: 56px 56px;
}

/* --- Border beam ---------------------------------------------------------
   A light that sweeps around the card's edge. Drawn as a conic gradient on a
   pseudo-element, masked to just the 1px border ring so the card's own
   background stays untouched. Registering --beam-angle as an <angle> is what
   makes it animatable — a plain custom property can't be tweened.
   ------------------------------------------------------------------------- */
@property --beam-angle {
    syntax: '<angle>';
    initial-value: 0deg;
    inherits: false;
}

@keyframes ui-beam-spin {
    to {
        --beam-angle: 360deg;
    }
}

.ui-beam {
    position: relative;
    isolation: isolate;
}

.ui-beam::before {
    content: '';
    position: absolute;
    /* An absolutely-positioned pseudo-element anchors to the PADDING box, so
       inset:0 would draw the ring just inside the border as a second line.
       Pulling out by the border width sits it on the border itself. */
    inset: calc(-1 * var(--beam-inset, 1px));
    z-index: 1;
    border-radius: inherit;
    padding: var(--beam-width, 2px);
    background: conic-gradient(
        from var(--beam-angle),
        transparent 0deg 190deg,
        rgb(var(--beam-color, var(--accent)) / 0.25) 260deg,
        rgb(var(--beam-color, var(--accent)) / 0.7) 320deg,
        rgb(var(--beam-color, var(--accent))) 350deg,
        transparent 360deg
    );
    /* Punch out the middle, leaving only the ring painted. */
    -webkit-mask:
        linear-gradient(#000 0 0) content-box,
        linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask:
        linear-gradient(#000 0 0) content-box,
        linear-gradient(#000 0 0);
    mask-composite: exclude;
    opacity: 0;
    transition: opacity 0.25s;
    pointer-events: none;
}

/* Runs on hover, when explicitly marked active, or when it wraps a checked
   input — the same trigger the radio/checkbox cards already use. */
.ui-beam:hover::before,
.ui-beam[data-active]::before,
.ui-beam:has(:checked)::before,
.ui-beam:focus-within::before {
    opacity: 1;
    animation: ui-beam-spin var(--beam-duration, 3s) linear infinite;
}

@media (prefers-reduced-motion: reduce) {
    .ui-beam:hover::before,
    .ui-beam[data-active]::before,
    .ui-beam:has(:checked)::before,
    .ui-beam:focus-within::before {
        animation: none;
        background: rgb(var(--beam-color, var(--accent)) / 0.55);
    }
}

/* Indeterminate progress sweep. */
@keyframes ui-indeterminate {
    0% { transform: translateX(-100%); }
    100% { transform: translateX(400%); }
}

.ui-indeterminate {
    animation: ui-indeterminate 1.4s ease-in-out infinite;
}

@keyframes ui-shimmer {
    100% { transform: translateX(100%); }
}

.ui-skeleton {
    position: relative;
    overflow: hidden;
    background: rgb(var(--text) / 0.07);
}

.ui-skeleton::after {
    content: '';
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, rgb(var(--text) / 0.08), transparent);
    animation: ui-shimmer 1.6s infinite;
}

@media (prefers-reduced-motion: reduce) {
    .ui-skeleton::after,
    .ui-indeterminate {
        animation: none;
    }
}

/* ─────────────────────────────────────────────────────────────
   Rich text output (.ui-prose)
   Admin-authored HTML rendered on customer pages. Kept to the
   same tag set the sanitiser allows, so nothing can arrive here
   unstyled.
   ───────────────────────────────────────────────────────────── */
.ui-prose {
    font-size: 13px;
    line-height: 1.65;
    color: rgb(var(--text));
}
.ui-prose > :first-child { margin-top: 0; }
.ui-prose > :last-child  { margin-bottom: 0; }
.ui-prose p { margin: 0 0 0.75em; }
.ui-prose h2 { font-size: 16px; font-weight: 700; margin: 1.2em 0 0.45em; }
.ui-prose h3 { font-size: 14.5px; font-weight: 700; margin: 1.1em 0 0.4em; }
.ui-prose h4 { font-size: 13.5px; font-weight: 650; margin: 1em 0 0.35em; }
.ui-prose ul,
.ui-prose ol { margin: 0 0 0.75em; padding-left: 1.25em; }
.ui-prose ul { list-style: disc; }
.ui-prose ol { list-style: decimal; }
.ui-prose li { margin: 0.15em 0; }
.ui-prose strong, .ui-prose b { font-weight: 650; color: rgb(var(--text)); }
.ui-prose a {
    color: rgb(var(--primary));
    text-decoration: underline;
    text-underline-offset: 2px;
}
.ui-prose a:hover { color: rgb(var(--primary-hover)); }
.ui-prose blockquote {
    margin: 0 0 0.75em;
    padding: 0.35em 0 0.35em 0.9em;
    border-left: 2px solid var(--border);
    color: var(--muted);
}
.ui-prose code {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.9em;
    background: var(--surface-sunken);
    border-radius: var(--r-control);
    padding: 0.1em 0.35em;
}
.ui-prose pre {
    margin: 0 0 0.75em;
    padding: 0.7em 0.85em;
    background: var(--surface-sunken);
    border-radius: var(--r-card);
    overflow-x: auto;
}
.ui-prose pre code { background: none; padding: 0; }
.ui-prose hr { margin: 1em 0; border: 0; border-top: 1px solid var(--border-soft); }

/* The editor writes alignment and size as inline styles; a list that has been
   centred needs its markers to follow the text rather than stay hard left. */
.ui-prose [style*="text-align: center"],
.ui-prose [style*="text-align:center"] { list-style-position: inside; }
.ui-prose [style*="text-align: right"],
.ui-prose [style*="text-align:right"]  { list-style-position: inside; }

/* Inline colours must survive the dark theme, but the *default* text colour
   still has to flip — so only elements without an explicit colour inherit. */
.ui-prose :where(p, li, h2, h3, h4, blockquote):not([style*="color"]) { color: inherit; }

.ui-prose s, .ui-prose strike { text-decoration: line-through; }
.ui-prose u { text-decoration: underline; text-underline-offset: 2px; }

/* ─────────────────────────────────────────────────────────────
   Joined control (.ui-join)
   An input and its action welded into one control, so they read
   as a single thing rather than two that happen to sit together.
   ───────────────────────────────────────────────────────────── */
.ui-join {
    display: flex;
    align-items: stretch;
    width: 100%;
}
.ui-join > .ui-field {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
    flex: 1 1 auto;
    min-width: 0;
}
.ui-join > .ui-join-action {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    /* Collapse the doubled border down the seam. */
    margin-left: -1px;
    flex: 0 0 auto;
    white-space: nowrap;
}
/* Whichever side is focused owns the seam. */
.ui-join > .ui-field:focus,
.ui-join > .ui-join-action:focus-visible {
    position: relative;
    z-index: 1;
}

/* The action half of a joined control: primary, and visibly inert when the
   field beside it is empty. */
.ui-btn-join {
    background: rgb(var(--primary));
    border: 1px solid rgb(var(--primary));
    color: #fff;
    transition: background 0.18s, border-color 0.18s, opacity 0.18s;
}
.ui-btn-join:hover:not(:disabled) { background: rgb(var(--primary-hover)); border-color: rgb(var(--primary-hover)); }
.ui-btn-join:active:not(:disabled) { background: rgb(var(--primary-press)); border-color: rgb(var(--primary-press)); }
.ui-btn-join:disabled { cursor: not-allowed; opacity: 0.45; }

/* ─────────────────────────────────────────────────────────────
   Stepper (.ui-step-*)
   Minus / value / plus welded into one control, built on .ui-join.
   ───────────────────────────────────────────────────────────── */
.ui-step-btn {
    background: var(--surface-sunken);
    border: 1px solid var(--border);
    color: var(--muted);
    transition: background 0.15s, color 0.15s, border-color 0.15s, opacity 0.15s;
}
/* Tinted with an alpha on the token rather than color-mix: the ramp is stored
   as raw rgb components, which color-mix cannot take. */
.ui-step-btn:hover:not(:disabled) {
    background: rgb(var(--primary) / 0.12);
    color: rgb(var(--primary));
    border-color: rgb(var(--primary) / 0.35);
}
.ui-step-btn:active:not(:disabled) {
    background: rgb(var(--primary) / 0.2);
}
/* At a bound the button is inert — say so rather than let it look clickable. */
.ui-step-btn:disabled { opacity: 0.4; cursor: not-allowed; }

.ui-step-start {
    border-radius: var(--r-input) 0 0 var(--r-input);
}
.ui-step-end {
    border-radius: 0 var(--r-input) var(--r-input) 0;
    margin-left: -1px;
}
/* The value sits between the two buttons, so it owns no rounding at all. */
.ui-join > .ui-step-input {
    border-radius: 0;
    margin-left: -1px;
    min-width: 0;
    flex: 1 1 auto;
}
.ui-step-suffix {
    background: var(--surface-sunken);
    border: 1px solid var(--border);
    margin-left: -1px;
}
/* Focus lifts above its neighbours so the ring is never clipped by the seam. */
.ui-step-btn:focus-visible,
.ui-step-input:focus { position: relative; z-index: 1; }
