/* ====== BUTTONS ======
   One canonical button system. Pick a color (primary/success/danger or outline
   variant), pick a size (lg/md/sm), and add btn-block when you need full-width.
   Per-page CSS should NOT redefine button gradients — adjust paddings only if
   absolutely necessary (rare; mostly the standard sizes fit). */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    border: none;
    font-family: inherit;
    font-weight: 700;
    cursor: pointer;
    transition: all 0.2s;
    /* line-height:1 collapses the font half-leading (the asymmetric
       whitespace above and below glyphs in a line box) so flexbox
       align-items:center actually centers icons with the text glyph,
       not with the inflated line box. Root cause of the off-by-a-few-px
       SVG-misaligned-with-text class of bug. */
    line-height: 1;
}

/* Prevent icons from being squeezed inside narrow buttons. The .btn flex
   container handles centering once line-height:1 is in place. */
.btn svg {
    flex-shrink: 0;
}

.btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

/* ====== COLOR VARIANTS ======
   Every themed value below is a token from css/ui-theme.css — no gradient,
   radius, padding or shadow literal appears in this file. That is what makes the
   theme switchable from one C# constant (UiTheme.Active) without touching the
   component layer. If you are about to paste a literal here, it belongs in the
   theme file instead, or the two themes will drift.

   The colour tokens the theme reads (--btn-*-start/end/shadow) still live in
   theme.css and still auto-mute in dark mode; the theme composes them. */
.btn-primary {
    background: var(--btn-fill-primary);
    color: #fff;
    box-shadow: var(--btn-shadow-primary-rest);
}
/* §1 — hover and keyboard focus are ONE cue: lift + deepened shadow, no ring (Susanti,
   2026-07-17). They used to split (hover lifted without a ring; focus ringed without a
   lift), which broke the app's core rule on its most-used button — and §1 even claimed
   they already matched. Accepted trade-off, recorded in §2: the deepened shadow is now
   the ONLY keyboard-focus signal on filled buttons.

   `outline:none` is doing real work — drop it and the app-wide `button:focus-visible`
   fallback ring (utilities.css) reappears on focus alone, splitting the two states again.

   The [data-theme] prefix (always on <html>) raises these to 0,4,0, which is load-bearing
   twice over. It beats per-page dark overrides `[data-theme="dark"] .btn-primary[b-x]
   {box-shadow}` (0,3,0) that would clobber it in dark mode, AND any page's scoped
   hand-copy `.btn-primary:hover[b-x]` (0,3,0).

   :active MUST carry the prefix too: at 0,2,0 the lift above would outrank it and the
   button would stop visibly pressing. */
[data-theme] .btn-primary:hover:not(:disabled),
[data-theme] .btn-primary:focus-visible:not(:disabled) {
    outline: none;
    transform: var(--btn-transform-hover);
    box-shadow: var(--btn-shadow-primary-hover);
}
[data-theme] .btn-primary:active:not(:disabled) {
    transform: var(--btn-transform-press);
    box-shadow: var(--btn-shadow-primary-press);
}

.btn-success {
    background: var(--btn-fill-success);
    color: #fff;
    box-shadow: var(--btn-shadow-success-rest);
}
/* Same merged cue + same specificity reasoning as .btn-primary above. */
[data-theme] .btn-success:hover:not(:disabled),
[data-theme] .btn-success:focus-visible:not(:disabled) {
    outline: none;
    transform: var(--btn-transform-hover);
    box-shadow: var(--btn-shadow-success-hover);
}
[data-theme] .btn-success:active:not(:disabled) {
    transform: var(--btn-transform-press);
    box-shadow: var(--btn-shadow-success-press);
}

.btn-danger {
    background: var(--btn-fill-danger);
    color: #fff;
    box-shadow: var(--btn-shadow-danger-rest);
}
/* Same merged cue + same specificity reasoning as .btn-primary above. */
[data-theme] .btn-danger:hover:not(:disabled),
[data-theme] .btn-danger:focus-visible:not(:disabled) {
    outline: none;
    transform: var(--btn-transform-hover);
    box-shadow: var(--btn-shadow-danger-hover);
}
[data-theme] .btn-danger:active:not(:disabled) {
    transform: var(--btn-transform-press);
    box-shadow: var(--btn-shadow-danger-press);
}

/* "Saved/applied" success state — flip a primary button to success colors so
   the user gets a visual confirmation without having to swap class names. */
.btn-primary.is-success {
    background: var(--btn-fill-success);
    box-shadow: var(--btn-shadow-success-rest);
}

/* Neutral surface secondary — white card surface with neutral border, used as
   the muted pair next to a primary gradient CTA (Detail action-bar reject/
   cancel-like icon buttons, modal cancel, etc.). Distinct from .btn-outline-*
   which carries an intent color (primary/danger) — .btn-secondary is fully
   neutral so it doesn't compete for attention. */
.btn-secondary {
    border: 1.5px solid var(--border);
    background: var(--bg-white);
    color: var(--text-secondary);
}
/* Interaction cue (blue tint + blue text/icon) is in the hover/focus block below — §1: hover mirrors focus. */

/* Outline variants — for secondary CTAs (cancel, reject, etc). */
.btn-outline-primary {
    background: var(--bg-white);
    color: var(--blue-primary);
    border: 1.5px solid var(--border);
}
/* Interaction cue (blue tint) is in the hover/focus block below (mirrors focus). */

/* Destructive secondary — icon/text merah pada surface neutral. Border
   neutral (sama dengan outline-primary) supaya tidak triple-red noisy.
   Red intent direveal on hover via subtle red tint. Best practice Material
   3 / iOS HIG: destructive secondary tidak boleh dominasi visual attention. */
.btn-outline-danger {
    background: var(--bg-white);
    color: var(--red);
    border: 1.5px solid var(--border);
}
/* Interaction cue (blue tint) is in the hover/focus block below (mirrors focus);
   the resting RED text/icon is kept on the blue frame to carry the destructive intent. */

/* Size variants — pick the closest match. Pages with edge-case sizes can add
   one extra rule on top, but try not to.

   font-size stays a literal on purpose: it is type scale, not theme, and a theme
   that changed it would change every button's height and reflow the bars it sits
   in. Padding and radius are themed. */
.btn-lg { padding: var(--btn-pad-lg); font-size: 15px; border-radius: var(--btn-radius-lg); }
.btn-md { padding: var(--btn-pad-md); font-size: 13px; border-radius: var(--btn-radius-md); }
.btn-sm { padding: var(--btn-pad-sm); font-size: 12px; border-radius: var(--btn-radius-sm); }

/* Layout helpers */
.btn-block { width: 100%; display: flex; }
.btn-flex-1 { flex: 1; display: flex; }

/* Icon-only button — square, no label, used for secondary destructive or
   secondary optional actions in action-bar where primary action takes the
   space. Pair with title= + aria-label= for accessibility.
   Sizing matches `.btn-md` height so it lines up dengan sibling label buttons. */
.btn-icon {
    flex: 0 0 auto;
    width: 38px;
    height: 38px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--btn-radius-icon);
}

/* ====== BOTTOM BAR BUTTON BEHAVIOR ======
   Defensive layout for any page using a horizontal `.app-bottom-bar` row of
   buttons. Without min-width: 0, flex items default to their content's
   intrinsic width and won't shrink — so long labels (English, future locales)
   push the rightmost button past the screen edge.

   Convention: wrap the label text in <span> so text-overflow: ellipsis can
   clip cleanly while the icon stays at natural size. Buttons with no label
   span (icon-only) work too — the rule just no-ops on them.

   We keep the action bar a SINGLE row even at high display scales — the
   accepted pattern for tight rows is icon-only buttons with a modal confirm
   (see OpenComplaintModal / OpenCancelRefundModal in Detail.razor). */
/* ====== CANONICAL BOTTOM BAR ======
   One height for EVERY bottom-chrome bar so they never jump between pages:
   the tab nav, detail action bars, form submit footers, and the chat composer
   base all stand at --nav-height. Put class="app-bottom-bar" on the bar (a
   flex-shrink:0 sibling of the scroll area); controls inside are 44px tall.
   Absolutely-positioned bars (catalog/jasa detail) add the class too and just
   re-declare `position:absolute` on top. */
.app-bottom-bar {
    flex-shrink: 0;
    box-sizing: border-box;
    width: 100%;
    height: calc(var(--nav-height) + var(--safe-area-bottom-fixed));
    /* Bar stays full-bleed; its buttons cap to the card column (848 = the
       .tablet-card-flow content width) and centre, so they line up with the
       header + cards on wide screens. max(16px, …) keeps the normal 16px gutter
       on phones (where the centring term is 0/negative). */
    padding: 0 max(16px, calc((100% - 848px) / 2));
    padding-bottom: var(--safe-area-bottom-fixed);
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--bg-white);
    border-top: 1px solid var(--border);
    box-shadow: 0 -1px 2px rgba(13,33,55,.05), 0 -2px 4px rgba(13,33,55,.04), 0 -4px 8px rgba(13,33,55,.04);
    z-index: 9100;
}
.app-bottom-bar > .btn,
.app-bottom-bar > .btn-secondary {
    min-width: 0;
    height: 44px;
}
.app-bottom-bar > .btn-icon {
    width: 44px;
}
.app-bottom-bar > .btn > svg,
.app-bottom-bar > .btn-secondary > svg {
    flex: 0 0 auto;
}
.app-bottom-bar > .btn > span,
.app-bottom-bar > .btn-secondary > span {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ====== BOTTOM-BAR STATUS LABEL ======
   A non-interactive status line that sits inside an .app-bottom-bar in place of
   (or beside) the action buttons — e.g. Detail's "schedule expired" notice and
   the Chat composer's "chat closed" state. `flex: 1` lets it absorb the bar's
   width; modifier classes set the intent colour (.muted = grey). */
.action-info {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px;
    font-size: 13px;
    font-weight: 600;
    line-height: 1.3;
    text-align: center;
    font-family: inherit;
    white-space: nowrap;
    overflow: hidden;
    background: none;
    border: none;
}
.action-info svg {
    flex-shrink: 0;
    width: 16px;
    height: 16px;
}
.action-info.success { color: var(--green-badge); }
.action-info.waiting { color: var(--orange-badge); }
.action-info.muted { color: var(--text-muted); }

/* ====== KEYBOARD FOCUS + TOUCH-PRESS + HOVER (bordered buttons) ======
   tokens.css kills the browser focus ring, so every button defines its own cue.
   All bordered buttons share ONE blue-tint interaction cue — blue-pale background
   + blue-primary border — identical on mouse :hover, keyboard :focus-visible, and
   touch :active (design-discipline §1: hover mirrors focus). Text/icon colour:
     • neutral     (.btn-secondary)       grey text → flips BLUE (whole button lights blue)
     • affirmative (.btn-outline-primary)  text already blue
     • destructive (.btn-outline-danger)   keeps its RED text/icon on the blue frame,
                                            so danger stays legible without a strong red fill
   :hover is guarded so a touch tap doesn't leave the cue stuck. */
.btn-secondary:focus-visible:not(:disabled),
.btn-secondary:active:not(:disabled),
.btn-outline-primary:focus-visible:not(:disabled),
.btn-outline-primary:active:not(:disabled),
.btn-outline-danger:focus-visible:not(:disabled),
.btn-outline-danger:active:not(:disabled) {
    outline: none;
    background: var(--blue-pale);
    border-color: var(--blue-primary);
}
/* Neutral also lights its text/icon blue (resting colour is neutral grey; the
   affirmative button is already blue, the destructive one keeps its red). */
.btn-secondary:focus-visible:not(:disabled),
.btn-secondary:active:not(:disabled) {
    color: var(--blue-primary);
}
@media (hover: hover) {
    .btn-secondary:hover:not(:disabled),
    .btn-outline-primary:hover:not(:disabled),
    .btn-outline-danger:hover:not(:disabled) {
        background: var(--blue-pale);
        border-color: var(--blue-primary);
    }
    .btn-secondary:hover:not(:disabled) {
        color: var(--blue-primary);
    }
}

/* Social / OAuth button keeps the universal blue border + glow ring (distinct control). */
.btn-social:focus-visible:not(:disabled) {
    outline: none;
    border-color: var(--blue-primary);
    box-shadow: 0 0 0 3px rgba(21,101,192,0.18);
}

/* The filled buttons' focus cue used to live here, separate from their hover. That
   separation WAS the §1 break: same specificity, later in source, so it overrode the
   hover's lift and left focus flat. Both states are now declared together with each
   colour variant above — keep them there, together, or they'll drift apart again. */

/* ====== SOCIAL / OAUTH BUTTONS ====== */
/* Defined globally (not in Login.razor.css scoped CSS) so they apply to <button>
   elements rendered from child components like LoadingButton — Blazor scoped CSS
   only matches elements rendered directly in the same .razor file. */
.btn-social {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    width: 100%;
    padding: 12px 16px;
    border-radius: var(--btn-radius-social);
    font-size: 14px;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    transition: background 0.18s, border-color 0.18s, box-shadow 0.18s, transform 0.06s;
    border: 1px solid var(--border);
    background: var(--bg-white);
    color: var(--text-primary);
}

.btn-social:hover:not(:disabled) {
    background: #F8FAFD;
    border-color: #C8CDD2;
    box-shadow: 0 1px 3px rgba(60, 64, 67, 0.12), 0 1px 2px rgba(60, 64, 67, 0.06);
}

.btn-social:active:not(:disabled) {
    transform: translateY(0.5px);
    background: #EEF1F4;
    box-shadow: none;
}

.btn-social:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

.btn-social svg {
    flex-shrink: 0;
    width: 18px;
    height: 18px;
}

/* Google brand-aligned: white background, Google's spec border color (#DADCE0),
   Google Sans-style typography (slight letter-spacing, weight 500), subtle elevation. */
.btn-google {
    border-color: #DADCE0;
    background: #FFFFFF;
    color: #3C4043;
    letter-spacing: 0.25px;
    box-shadow: 0 1px 1px rgba(60, 64, 67, 0.05);
}

/* Dark theme = Google's sanctioned dark "Sign in with Google" style: dark surface
   (#1F1F1F), light text, subtle stroke. Brand-specific hex (like the fixed delete
   badge) — Google's spec colors, not app tokens. The 4-color "G" SVG is inline with
   fixed brand colors, so it stays colored in both themes per Google's rules. Hover/
   active reproduce Google's white state-layer (≈8% / 12%) over the dark surface;
   :not(:disabled) raises specificity over the light .btn-social hover/active. */
[data-theme="dark"] .btn-google {
    border-color: #5F6368;
    background: #1F1F1F;
    color: #E3E3E3;
    box-shadow: none;
}

[data-theme="dark"] .btn-google:hover:not(:disabled) {
    border-color: #6F7378;
    background: #28292A;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}

[data-theme="dark"] .btn-google:active:not(:disabled) {
    background: #303134;
    box-shadow: none;
}

/* Same dark Google styling when the user is on SYSTEM theme and the OS is dark.
   theme.css flips the page's tokens for [data-theme="system"] under
   prefers-color-scheme: dark, but .btn-google uses Google's fixed brand hex (not
   tokens), so it needs this explicit branch — without it the button stayed white
   on a dark OS while the rest of the (token-driven) page went dark. Keep these in
   sync with the [data-theme="dark"] .btn-google rules above. */
@media (prefers-color-scheme: dark) {
    [data-theme="system"] .btn-google {
        border-color: #5F6368;
        background: #1F1F1F;
        color: #E3E3E3;
        box-shadow: none;
    }

    [data-theme="system"] .btn-google:hover:not(:disabled) {
        border-color: #6F7378;
        background: #28292A;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
    }

    [data-theme="system"] .btn-google:active:not(:disabled) {
        background: #303134;
        box-shadow: none;
    }
}

/* ====== MAPS / LOCATION ACTION BUTTON ======
   Shared "Open in Maps" / location button (Detail + JasaBooking). Blue-tinted
   secondary CTA: idle = blue-pale fill + blue border + blue text. On hover/
   focus/press it DEEPENS to the filled active-blue (`--tab-active-bg`, the app's
   canonical filled-state token — contrast-safe with white text in BOTH themes)
   + white text. No ring/glow/outline (the offset outline used to double up with
   the idle blue border into a harsh 2-ring look). Pages add their own margin. */
.btn-maps {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: 100%;
    padding: 10px;
    /* Themed: it is a full-width bordered CTA, so leaving it at a literal would
       make it the one rounded rectangle among pills. */
    border-radius: var(--btn-radius-social);
    border: 1.5px solid var(--blue-primary);
    background: var(--blue-pale);
    color: var(--blue-primary);
    font-family: inherit;
    font-size: 13.5px;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.btn-maps:focus-visible,
.btn-maps:active {
    outline: none;
    background: var(--tab-active-bg);
    border-color: var(--tab-active-bg);
    color: #fff;
    box-shadow: none;
}
@media (hover: hover) {
    .btn-maps:hover {
        background: var(--tab-active-bg);
        border-color: var(--tab-active-bg);
        color: #fff;
    }
}
