/* ============================================================================
   GMH form + component layer.

   Batch 1 of the admin redesign programme. Everything the components under
   resources/views/components/gmh/ need, and nothing else.

   THREE RULES THIS FILE OBEYS, AND SO MUST YOU
   ---------------------------------------------------------------------------
   1. Tokens only. Every colour, radius and font here is var(--gmh-*), defined
      once in gmh-theme.css. There is not a single literal hex below, and there
      must never be. That is what makes dark mode free: gmh-dark.css redefines
      the same tokens under html.gmh-dark, so these components follow with no
      dark-specific rules of their own.

   2. This file is NOT gmh-theme.css. Tokens live there; components live here.
      Adding a token here splits the source of truth and breaks rule 1.

   3. No page may restyle a component. If it does not fit, change the component
      and check the other pages. A page-local override is how the admin drifted
      into 165 distinct button class combinations in the first place.

   Loaded via the GmhNav plugin in config/adminlte.php, after gmh-theme.css.
   ========================================================================== */


/* ==========================================================================
   0. [hidden] WINS
   The attribute only carries `display:none` from the user-agent sheet, so ANY
   class that sets display beats it. .gmh-stack{display:flex} did exactly that
   and left a "hidden" panel fully visible on the login page. This is the guard.
   ========================================================================== */
[hidden] { display: none !important; }

/* ==========================================================================
   0b. BORDER-BOX ON EVERY COMPONENT
   These components must not depend on a host stylesheet for their box model.
   Admin pages get border-box from Bootstrap; the auth pages do not load
   Bootstrap and Tailwind's preflight is off, so nothing set it there, and a
   380px field held a 406px input, overflowing by exactly its padding + border.
   Declared here so a component is correct wherever it is mounted.
   ========================================================================== */
.gmh-tb-btn, .gmh-icon-btn, .gmh-input, .gmh-field, .gmh-card, .gmh-modal, .gmh-drawer,
.gmh-dd__menu, .gmh-pop, .gmh-ms__panel, .gmh-cal, .gmh-table-wrap,
.gmh-stat, .gmh-empty, .gmh-chip, .gmh-badge, .gmh-auth,
.gmh-auth__brand, .gmh-auth__panel, .gmh-auth__form, .gmh-stack, .gmh-row {
    box-sizing: border-box;
}

/* ==========================================================================
   1. BUTTON: x-gmh.button

   THE BUTTON STYLES ARE NOT HERE. They are in gmh-nav.css, as
   .gmh-tb-btn / .gmh-tb-btn-primary / .gmh-tb-btn-ghost / .gmh-icon-btn /
   .gmh-search-btn, and they are already used 315 times across the admin.

   An earlier draft of this file defined a parallel .gmh-btn--* system. That
   would have made a 166th button style rather than replacing the other 165, which is the opposite of the point. x-gmh.button renders the existing
   classes instead.

   Only the two things gmh-nav.css does not already provide live here.
   ========================================================================== */

/* Full-width, used by the auth form. Admin pages do not need it. */
.gmh-btn-block { width: 100%; justify-content: center; }

/* The danger variant is a ghost button with red text. UIUX_GUIDE.md section 1:
   "Ghost metrics, red text; soft red border when the action destroys data." */
.gmh-tb-btn.is-danger { color: var(--gmh-red); border-color: var(--gmh-red-soft); }
.gmh-tb-btn.is-danger:hover { background: var(--gmh-red-soft); color: var(--gmh-red); }

/* A disabled control still says what it would do, never swap its label. */
.gmh-tb-btn.is-disabled,
.gmh-icon-btn.is-disabled {
    opacity: .5;
    cursor: not-allowed;
    pointer-events: none;
}

/* Focus is never removed, keyboard users need it.
   The !important is load bearing, not decoration. gmh-nav.css sets
   `.gmh-tb-btn { box-shadow: none !important }` to beat AdminLTE and the UA
   button chrome, and an important declaration wins over a normal one whatever
   the specificity. So this ring was declared, matched, and then discarded: a
   focused GMH button rendered box-shadow: none and keyboard users saw nothing.
   Verified in a browser, not inferred: the same rule DID paint on .gmh-icon-btn,
   which carries no such reset. */
.gmh-tb-btn:focus-visible,
.gmh-icon-btn:focus-visible,
.gmh-search-btn:focus-visible,
.gmh-input:focus-visible,
.gmh-chip:focus-within,
.gmh-dd-item:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--gmh-purple) 35%, transparent) !important;
}

/* ==========================================================================
   2. INPUT / SELECT / TEXTAREA: x-gmh.input, .select, .textarea
   ========================================================================== */
.gmh-input {
    width: 100%;
    font: 400 14px/1.4 var(--gmh-font);
    color: var(--gmh-ink);
    background: var(--gmh-card);
    border: 1px solid var(--gmh-line);
    border-radius: var(--gmh-radius-sm);
    padding: 8px 12px;
    transition: border-color .12s ease, box-shadow .12s ease;
}
.gmh-input::placeholder { color: var(--gmh-grey-faint); }
.gmh-input:focus {
    outline: none;
    border-color: var(--gmh-purple);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--gmh-purple) 25%, transparent);
}
.gmh-input.is-error { border-color: var(--gmh-red); }
.gmh-input.is-error:focus {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--gmh-red) 22%, transparent);
}
.gmh-input:disabled {
    opacity: .5;
    cursor: not-allowed;
    background: var(--gmh-bg);
}
/* Readonly is not disabled: the value still matters and stays selectable. */
.gmh-input[readonly] {
    background: var(--gmh-bg);
    color: var(--gmh-grey);
}
textarea.gmh-input { min-height: 84px; resize: vertical; line-height: 1.55; }

/* Native select arrow replaced with a token-coloured caret. */
select.gmh-input {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 32px;
    background-image:
        linear-gradient(45deg, transparent 50%, var(--gmh-grey) 50%), linear-gradient(135deg, var(--gmh-grey) 50%, transparent 50%);
    background-position: calc(100% - 17px) calc(50% + 1px), calc(100% - 12px) calc(50% + 1px);
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
}

/* ==========================================================================
   3. FIELD: x-gmh.field
   Label + control + hint + error. 178 files hand-roll this today.
   ========================================================================== */
.gmh-field { display: flex; flex-direction: column; gap: 5px; }
.gmh-label { font: 500 12px/1.3 var(--gmh-font); color: var(--gmh-grey); }
.gmh-label .gmh-req { color: var(--gmh-red); }
.gmh-hint { font-size: 11.5px; line-height: 1.45; color: var(--gmh-grey-faint); }
.gmh-error {
    display: flex;
    align-items: flex-start;
    gap: 5px;
    font-size: 11.5px;
    line-height: 1.45;
    color: var(--gmh-red);
}

/* ==========================================================================
   4. CHECK / RADIO / TOGGLE / BADGE / CHIP
   ========================================================================== */
.gmh-check {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 13.5px;
    color: var(--gmh-ink);
    cursor: pointer;
}
.gmh-check input { width: 16px; height: 16px; margin: 0; accent-color: var(--gmh-purple); }
.gmh-check.is-disabled { opacity: .5; cursor: not-allowed; }

/* 36x20 pill, 16px thumb. The standard enable/disable control. */
.gmh-toggle {
    position: relative;
    display: inline-block;
    flex: none;
    width: 36px;
    height: 20px;
    border-radius: var(--gmh-radius-pill);
    background: var(--gmh-line);
    cursor: pointer;
    transition: background-color .15s ease;
}
.gmh-toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.gmh-toggle::after {
    content: "";
    position: absolute;
    top: 2px; left: 2px;
    width: 16px; height: 16px;
    border-radius: 50%;
    background: var(--gmh-card);
    transition: left .15s ease;
}
.gmh-toggle.is-on { background: var(--gmh-purple); }
.gmh-toggle.is-on::after { left: 18px; }
.gmh-toggle.is-disabled { opacity: .5; cursor: not-allowed; }
@media (prefers-reduced-motion: reduce) {
    .gmh-toggle, .gmh-toggle::after, .gmh-btn, .gmh-input { transition: none; }
}

/* Badges are the ONE place uppercase is correct. Table headers are not. */
.gmh-badge {
    display: inline-block;
    font: 700 10.5px/1.6 var(--gmh-font);
    letter-spacing: .04em;
    text-transform: uppercase;
    padding: 2px 8px;
    border-radius: 6px;
    white-space: nowrap;
}
.gmh-badge--green  { background: var(--gmh-green-soft);  color: var(--gmh-green); }
.gmh-badge--red    { background: var(--gmh-red-soft);    color: var(--gmh-red); }
.gmh-badge--amber  { background: var(--gmh-amber-soft);  color: var(--gmh-amber); }
.gmh-badge--purple { background: var(--gmh-purple-soft); color: var(--gmh-purple-deep); }
.gmh-badge--grey   { background: var(--gmh-line-soft);   color: var(--gmh-grey); }

.gmh-chip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font: 400 13px/1 var(--gmh-font);
    padding: 7px 14px;
    border: 1px solid var(--gmh-line);
    border-radius: var(--gmh-radius-pill);
    background: var(--gmh-card);
    color: var(--gmh-ink);
    cursor: pointer;
}
.gmh-chip input { margin: 0; accent-color: var(--gmh-purple); }
.gmh-chip.is-on {
    background: var(--gmh-purple-soft);
    border-color: var(--gmh-purple);
    color: var(--gmh-purple-deep);
    font-weight: 600;
}

/* ==========================================================================
   5. CARD / FORM CARD / ACTIONS
   ========================================================================== */
.gmh-card {
    background: var(--gmh-card);
    border: 1px solid var(--gmh-line);
    border-radius: var(--gmh-radius);
    overflow: hidden;
}
.gmh-card__head { padding: 12px 16px; border-bottom: 1px solid var(--gmh-line); }
.gmh-card__title { font: 700 18px/1.3 var(--gmh-font); color: var(--gmh-ink); }
.gmh-card__sub { font: 400 12px/1.4 var(--gmh-font); color: var(--gmh-grey-faint); margin-top: 2px; }
.gmh-card__body { padding: 16px; display: flex; flex-direction: column; gap: 12px; }
.gmh-card__foot {
    padding: 12px 16px;
    border-top: 1px solid var(--gmh-line);
    background: var(--gmh-head);
    display: flex;
    gap: 8px;
    justify-content: flex-end;
    flex-wrap: wrap;
}
/* Fixed order: secondary first, primary last, left to right. */
.gmh-actions { display: flex; gap: 8px; justify-content: flex-end; flex-wrap: wrap; }

/* ==========================================================================
   6. TABS: x-gmh.tabs
   Replaces 57 byte-identical copies of nav-tabs.blade.php.
   ========================================================================== */
.gmh-tabs {
    display: flex;
    gap: 4px;
    border-bottom: 1px solid var(--gmh-line);
    overflow-x: auto;
    scrollbar-width: none;
}
.gmh-tabs::-webkit-scrollbar { display: none; }
.gmh-tab {
    font: 600 14px/1 var(--gmh-font);
    padding: 10px 16px;
    color: var(--gmh-grey);
    white-space: nowrap;
    text-decoration: none;
    border-bottom: 2px solid transparent;
    border-radius: var(--gmh-radius-sm) var(--gmh-radius-sm) 0 0;
}
.gmh-tab:hover { color: var(--gmh-purple-deep); text-decoration: none; }
.gmh-tab.is-active {
    color: var(--gmh-purple-deep);
    background: var(--gmh-purple-soft);
    border-bottom-color: var(--gmh-purple);
}
.gmh-tab__count { opacity: .65; font-weight: 500; }

/* ==========================================================================
   7. SEARCH: x-gmh.search-bar
   Placeholder reads "Search by ...". Runs on click or Enter, never as you type.
   ========================================================================== */
.gmh-search { position: relative; width: 256px; max-width: 100%; }
.gmh-search .gmh-input { padding-right: 38px; }

/* .gmh-search-btn in gmh-nav.css only strips the border and background, it
   carries no positioning, because the pages that used it supplied their own.
   Scoped to this wrapper so no existing use of the class is affected. */
.gmh-search .gmh-search-btn {
    position: absolute;
    right: 4px;
    top: 4px;
    width: 30px;
    height: 30px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--gmh-grey);
    border-radius: 6px;
    cursor: pointer;
}
.gmh-search .gmh-search-btn:hover { color: var(--gmh-purple); }

/* ==========================================================================
   8. OVERLAYS: modal, drawer, dropdown, popover
   ========================================================================== */
.gmh-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .4);
    z-index: 1080;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}
.gmh-overlay[hidden] { display: none; }

.gmh-modal {
    width: 100%;
    max-width: 520px;
    max-height: calc(100vh - 32px);
    display: flex;
    flex-direction: column;
    background: var(--gmh-card);
    border-radius: var(--gmh-radius);
    box-shadow: 0 12px 28px -8px rgba(17, 24, 39, .28);
    overflow: hidden;
}
/* .gmh-modal is the panel INSIDE .gmh-overlay, which is what hides it. Bootstrap's .modal
   hides itself with display:none instead, so combining the two forces a closed modal to
   display:flex: invisible at opacity 0, and still swallowing every click across its box.
   That took out an entire sidebar once. Put .gmh-modal on .modal-content, never on .modal,
   and this guard makes the mistake harmless if anyone repeats it. */
.modal.gmh-modal:not(.show) { display: none !important; }

.gmh-modal--sm { max-width: 400px; }
.gmh-modal--lg { max-width: 720px; }
.gmh-modal__head {
    padding: 14px 16px;
    border-bottom: 1px solid var(--gmh-line);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    font: 600 18px/1.3 var(--gmh-font);
}
.gmh-modal__body { padding: 16px; overflow-y: auto; }
.gmh-x {
    background: none;
    border: 0;
    font-size: 20px;
    line-height: 1;
    color: var(--gmh-grey-faint);
    cursor: pointer;
    padding: 2px 6px;
    border-radius: 6px;
}
.gmh-x:hover { background: var(--gmh-line-soft); color: var(--gmh-ink); }

/* Drawer, this is what retires Flowbite. 17 of its 19 attributes drove one. */
.gmh-drawer {
    position: fixed;
    top: 0;
    bottom: 0;
    width: 320px;
    max-width: 100vw;
    background: var(--gmh-card);
    border-left: 1px solid var(--gmh-line);
    box-shadow: -8px 0 28px -12px rgba(17, 24, 39, .28);
    z-index: 1090;
    display: flex;
    flex-direction: column;
    transition: transform .2s ease;
}
.gmh-drawer--right { right: 0; transform: translateX(100%); }
.gmh-drawer--left  { left: 0; right: auto; border-left: 0; border-right: 1px solid var(--gmh-line); transform: translateX(-100%); }
.gmh-drawer.is-open { transform: translateX(0); }
.gmh-drawer__head {
    padding: 14px 16px;
    border-bottom: 1px solid var(--gmh-line);
    display: flex;
    align-items: center;
    justify-content: space-between;
    font: 600 16px/1.3 var(--gmh-font);
}
.gmh-drawer__body { padding: 16px; overflow-y: auto; flex: 1; display: flex; flex-direction: column; gap: 12px; }
@media (prefers-reduced-motion: reduce) { .gmh-drawer { transition: none; } }

/* Dropdown, replaces Bootstrap data-toggle="dropdown". */
.gmh-dd { position: relative; display: inline-block; }
.gmh-dd__menu {
    position: absolute;
    top: calc(100% + 4px);
    min-width: 190px;
    background: var(--gmh-card);
    border: 1px solid var(--gmh-line);
    border-radius: var(--gmh-radius);
    box-shadow: 0 12px 28px -8px rgba(17, 24, 39, .18);
    padding: 5px;
    z-index: 1070;
}
.gmh-dd__menu[hidden] { display: none; }
.gmh-dd--left  .gmh-dd__menu { left: 0; }
.gmh-dd--right .gmh-dd__menu { right: 0; }
.gmh-dd-item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 8px 10px;
    border: 0;
    background: none;
    text-align: left;
    font: 400 13.5px/1.4 var(--gmh-font);
    color: var(--gmh-ink);
    border-radius: 6px;
    cursor: pointer;
    text-decoration: none;
}
.gmh-dd-item:hover { background: var(--gmh-purple-hover); color: var(--gmh-purple-deep); text-decoration: none; }
.gmh-dd-item.is-danger { color: var(--gmh-red); }
.gmh-dd-item.is-danger:hover { background: var(--gmh-red-soft); }
.gmh-dd__sep { height: 1px; background: var(--gmh-line-soft); margin: 4px 0; }

/* Filter popover, 300-320px, right aligned. */
.gmh-pop {
    position: absolute;
    right: 0;
    top: calc(100% + 6px);
    width: 310px;
    max-width: calc(100vw - 24px);
    background: var(--gmh-card);
    border: 1px solid var(--gmh-line);
    border-radius: var(--gmh-radius);
    box-shadow: 0 12px 28px -8px rgba(17, 24, 39, .18);
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    z-index: 1070;
}
.gmh-pop[hidden] { display: none; }
/* 8px purple dot when any filter is active. */
.gmh-filter-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--gmh-purple);
    display: inline-block;
}

/* ==========================================================================
   9. MULTISELECT: x-gmh.multiselect
   Promoted out of components/jobpool/. Live "N selected" summary.
   ========================================================================== */
/* --------------------------------------------------------------------------
   MULTISELECT, rebuilt 2026-08-28 to the reference designs.
   Round check indicators, a count chip on the trigger, indented options under
   a group header that carries its own checkbox.
   -------------------------------------------------------------------------- */
.gmh-ms { position: relative; }

.gmh-ms__trigger {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--gmh-card);
    border: 1px solid var(--gmh-line);
    border-radius: 8px;
    padding: 8px 11px;
    font: 500 13px var(--gmh-font);
    color: var(--gmh-ink);
    cursor: pointer;
    text-align: left;
}
.gmh-ms__trigger:hover { border-color: var(--gmh-purple); }
.gmh-ms__trigger:focus-visible { outline: 2px solid var(--gmh-purple); outline-offset: 1px; }

/* The label greys out until something is chosen, so an empty picker reads as a
   placeholder rather than as a value. */
.gmh-ms__placeholder { flex: 1; min-width: 0; color: var(--gmh-grey-faint); }
.gmh-ms__placeholder.is-filled { color: var(--gmh-ink); font-weight: 600; }

.gmh-ms__chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background: var(--gmh-purple);
    color: var(--gmh-on-purple);
    border-radius: var(--gmh-radius-pill);
    padding: 1px 5px 1px 8px;
    font: 700 11px var(--gmh-font);
    flex: none;
}
.gmh-ms__chip[hidden] { display: none; }
.gmh-ms__chipx { cursor: pointer; font-size: 13px; line-height: 1; opacity: .85; }
.gmh-ms__chipx:hover { opacity: 1; }
.gmh-ms__caret { color: var(--gmh-grey-faint); font-size: 10px; flex: none; }

.gmh-ms__panel {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    width: 100%;
    min-width: 240px;
    max-width: calc(100vw - 24px);
    background: var(--gmh-card);
    border: 1px solid var(--gmh-line);
    border-radius: var(--gmh-radius);
    box-shadow: 0 12px 28px -8px rgba(17, 24, 39, .18);
    overflow: hidden;
    z-index: 1070;
}
.gmh-ms__panel[hidden] { display: none; }

.gmh-ms__search { padding: 8px 8px 4px; }
.gmh-ms__search input {
    width: 100%;
    border: 1px solid var(--gmh-line);
    border-radius: 8px;
    padding: 6px 9px;
    font: 400 13px var(--gmh-font);
    color: var(--gmh-ink);
    background: var(--gmh-card);
}
.gmh-ms__search input:focus { outline: 2px solid var(--gmh-purple); outline-offset: -1px; }

.gmh-ms__list { max-height: 288px; overflow-y: auto; padding: 4px; }

.gmh-ms__row {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 7px 9px;
    border-radius: 6px;
    font-size: 13.5px;
    color: var(--gmh-ink);
    cursor: pointer;
}
.gmh-ms__row:hover { background: var(--gmh-purple-hover); }
.gmh-ms__row[hidden] { display: none; }
.gmh-ms__row.is-checked { background: var(--gmh-purple-soft); }

/* Select all sits above everything and reads as a control, not an option. */
.gmh-ms__row--all { font-weight: 600; border-bottom: 1px solid var(--gmh-line); border-radius: 0; margin-bottom: 3px; }

/* A group header is a row with a checkbox, so it can own its children. The count on the
   right says how many are underneath without opening anything.

   It sticks while its own options scroll past. Two details make that work rather than
   smear: the list has 4px of padding, so `top: 0` would pin the header 4px below the
   scrollport and let rows slide through the gap above it; and the row is inset by the same
   padding, so rows scrolling past would show either side of it. Pulling both back covers
   the full width, flush to the top. */
.gmh-ms__row--group {
    font-weight: 700;
    font-size: 12.5px;
    position: sticky;
    top: -4px;
    z-index: 2;
    margin: 0 -4px;
    padding-left: 13px;
    padding-right: 13px;
    border-radius: 0;
    background: var(--gmh-card);
    box-shadow: inset 0 -1px 0 var(--gmh-line);
}
.gmh-ms__row--group:hover { background: var(--gmh-purple-hover); }
.gmh-ms__row--group.is-checked { background: var(--gmh-purple-soft); }
.gmh-ms__gcount { margin-left: auto; font: 500 11px var(--gmh-font); color: var(--gmh-grey-faint); }

/* Select all is inset the same way, for the same reason. */
.gmh-ms__row--all { margin: 0 -4px 3px; padding-left: 13px; padding-right: 13px; }

/* Indentation is what makes a heading read as a heading rather than as another option. */
.gmh-ms__row--child { padding-left: 30px; }

/* Round indicators, per the reference.

   `accent-color` alone will not do it: border-radius has no effect on a native checkbox,
   which is why these stayed square. So the control is unstyled with `appearance: none` and
   drawn here, while staying a real `<input type=checkbox>` so the indeterminate state,
   keyboard handling and screen reader semantics all still come for free. The marks are
   pure CSS, so there is no image to fail to load. */
.gmh-ms__row input[type=checkbox] {
    appearance: none;
    -webkit-appearance: none;
    margin: 0;
    width: 17px;
    height: 17px;
    flex: none;
    display: inline-grid;
    place-content: center;
    border: 1.5px solid var(--gmh-line);
    border-radius: 50%;
    background: var(--gmh-card);
    cursor: pointer;
    transition: background-color .12s ease, border-color .12s ease;
}
.gmh-ms__row:hover input[type=checkbox] { border-color: var(--gmh-purple); }

.gmh-ms__row input[type=checkbox]:checked,
.gmh-ms__row input[type=checkbox]:indeterminate {
    background: var(--gmh-purple);
    border-color: var(--gmh-purple);
}

/* The tick: two borders of a box, rotated. Nudged up a pixel because a rotated square
   sits low inside a circle otherwise. */
.gmh-ms__row input[type=checkbox]:checked::after {
    content: "";
    width: 9px;
    height: 5px;
    border-left: 2px solid var(--gmh-on-purple);
    border-bottom: 2px solid var(--gmh-on-purple);
    transform: rotate(-45deg) translate(1px, -2px);
}

/* The dash, for a group holding some but not all of its options. */
.gmh-ms__row input[type=checkbox]:indeterminate::after {
    content: "";
    width: 9px;
    height: 2px;
    border-radius: 1px;
    background: var(--gmh-on-purple);
}

.gmh-ms__row input[type=checkbox]:focus-visible {
    outline: 2px solid var(--gmh-purple);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
    .gmh-ms__row input[type=checkbox] { transition: none; }
}

.gmh-ms__none { padding: 12px 9px; font-size: 12.5px; color: var(--gmh-grey-faint); text-align: center; }
.gmh-ms__none[hidden] { display: none; }

/* ==========================================================================
   10. STEPPER / STAT CARD / EMPTY STATE
   ========================================================================== */
.gmh-stepper { display: flex; align-items: center; flex-wrap: wrap; gap: 0; }
.gmh-step__dot {
    width: 26px; height: 26px;
    flex: none;
    display: grid;
    place-items: center;
    border-radius: 50%;
    font: 700 12px/1 var(--gmh-font);
    background: var(--gmh-line-soft);
    color: var(--gmh-grey);
}
/* Green when done, purple when current: the same convention the Route Prices stepper uses,
   so a completed step reads the same wherever a pricing page shows one. */
.gmh-step__dot.is-done { background: var(--gmh-green); color: #fff; }
.gmh-step__dot.is-current {
    background: var(--gmh-card);
    color: var(--gmh-purple-deep);
    box-shadow: 0 0 0 2px var(--gmh-purple);
}
.gmh-step__label { font: 600 13px/1 var(--gmh-font); color: var(--gmh-grey); margin: 0 10px 0 8px; }
.gmh-step__label.is-current { color: var(--gmh-ink); }
.gmh-step__bar { width: 34px; height: 2px; background: var(--gmh-line); }
.gmh-step__bar.is-done { background: var(--gmh-green); }

.gmh-stat {
    background: var(--gmh-head);
    border-radius: var(--gmh-radius);
    padding: 14px 16px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.gmh-stat__label { font: 400 14px/1.3 var(--gmh-font); color: var(--gmh-grey); }
.gmh-stat__sub { font: 400 11px/1.3 var(--gmh-font); color: var(--gmh-grey-faint); margin-top: 2px; display: block; }
.gmh-stat__value {
    font: 800 30px/1.05 var(--gmh-font);
    letter-spacing: -.03em;
    color: var(--gmh-ink);
    font-variant-numeric: tabular-nums;
}

/* Sits inside the table body, never replaces the card. */
.gmh-empty {
    padding: 40px 20px;
    text-align: center;
    font-size: 13px;
    line-height: 1.6;
    color: var(--gmh-grey-faint);
}

/* ==========================================================================
   11. TABLE: x-gmh.table
   GMH owns the look; DataTables owns the behaviour where a page uses it.
   ========================================================================== */
.gmh-table-wrap {
    background: var(--gmh-card);
    border: 1px solid var(--gmh-line);
    border-radius: var(--gmh-radius);
    overflow: hidden;
}
.gmh-table-toolbar {
    padding: 12px 14px;
    border-bottom: 1px solid var(--gmh-line);
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: center;
    justify-content: space-between;
}
/* Tabs strip inside the table card, above the toolbar. */
.gmh-table-tabs { padding: 0 14px; }
.gmh-table-tabs .gmh-tabs { border-bottom: 0; }

.gmh-table-scroll { overflow-x: auto; }
.gmh-table { width: 100%; border-collapse: collapse; }

/* 13px/500 grey on the head background. NORMAL CASE, never uppercase. */
.gmh-table thead th {
    background: var(--gmh-head);
    color: var(--gmh-grey);
    font: 500 13px/1.4 var(--gmh-font);
    text-align: left;
    padding: 11px 12px;
    border-bottom: 1px solid var(--gmh-line);
    white-space: nowrap;
    position: relative;
    user-select: none;
}
.gmh-table thead th.is-sortable { cursor: pointer; padding-right: 22px; }
.gmh-table thead th.is-sorted { color: var(--gmh-purple-deep); }
.gmh-table__arrow {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 9px;
    color: var(--gmh-grey-faint);
}
.gmh-table thead th.is-sorted .gmh-table__arrow { color: var(--gmh-purple); }

/* Sticky header, fixedheader is vendored but this covers the GMH tables too. */
.gmh-table--sticky thead th { position: sticky; top: 0; z-index: 2; }

/* Column resize. Our own implementation, not a plugin, see gmh-form.js. */
.gmh-table__resize {
    position: absolute;
    right: 0; top: 0; bottom: 0;
    width: 6px;
    cursor: col-resize;
    touch-action: none;
}
.gmh-table__resize::after {
    content: "";
    position: absolute;
    right: 2px; top: 8px; bottom: 8px;
    width: 1px;
    background: var(--gmh-line);
}
.gmh-table__resize:hover::after,
.gmh-table__resize.is-dragging::after { background: var(--gmh-purple); }

.gmh-table tbody td {
    padding: 11px 12px;
    border-bottom: 1px solid var(--gmh-line-soft);
    font-size: 13.5px;
    color: var(--gmh-ink);
    vertical-align: middle;
}
.gmh-table tbody tr:last-child td { border-bottom: 0; }
.gmh-table tbody tr:hover { background: var(--gmh-purple-hover); }
/* Click to highlight. Opt in with data-gmh-selectable on the table; gmh-table.js
   does the toggling. Listed after :hover so a selected row stays selected while
   the pointer is over it, rather than flipping to the lighter hover fill. */
.gmh-table tbody tr.is-selected,
.gmh-table tbody tr.is-selected:hover { background: var(--gmh-purple-soft); }
.gmh-table tbody tr.is-selected > td:first-child { box-shadow: inset 3px 0 0 var(--gmh-purple); }
.gmh-table[data-gmh-selectable] tbody tr { cursor: pointer; }
.gmh-table__sub { font-size: 12px; color: var(--gmh-grey-faint); }

/* Drag handle for row reorder. */
.gmh-table__grip {
    color: var(--gmh-grey-faint);
    cursor: grab;
    font-size: 13px;
    letter-spacing: -2px;
    user-select: none;
}
.gmh-table tbody tr.is-dragging { background: var(--gmh-purple-soft); opacity: .85; }
.gmh-table tbody tr.is-drop-target td { border-top: 2px solid var(--gmh-purple); }

.gmh-table-foot {
    padding: 10px 14px;
    border-top: 1px solid var(--gmh-line);
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    align-items: center;
    justify-content: space-between;
    font-size: 12.5px;
    color: var(--gmh-grey);
}
.gmh-pager { display: flex; gap: 4px; flex-wrap: wrap; }
.gmh-pager__btn {
    min-width: 28px;
    height: 28px;
    padding: 0 8px;
    border: 1px solid var(--gmh-line);
    border-radius: var(--gmh-radius-sm);
    background: var(--gmh-card);
    color: var(--gmh-ink);
    font: 500 12.5px/1 var(--gmh-font);
    cursor: pointer;
}
.gmh-pager__btn:hover:not(:disabled) { background: var(--gmh-purple-soft); }
.gmh-pager__btn.is-current {
    background: var(--gmh-purple);
    border-color: var(--gmh-purple);
    color: var(--gmh-on-purple);
}
.gmh-pager__btn:disabled { opacity: .45; cursor: not-allowed; }

/* ==========================================================================
   12. DATEPICKER: x-gmh.datepicker
   Replaces flowbite-datepicker, which dies with ADR 0008.
   ========================================================================== */
.gmh-cal {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    width: 260px;
    background: var(--gmh-card);
    border: 1px solid var(--gmh-line);
    border-radius: var(--gmh-radius);
    box-shadow: 0 12px 28px -8px rgba(17, 24, 39, .18);
    padding: 12px;
    z-index: 1070;
}
.gmh-cal[hidden] { display: none; }
.gmh-cal__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font: 600 13px/1 var(--gmh-font);
    margin-bottom: 10px;
}
.gmh-cal__nav {
    background: none;
    border: 0;
    cursor: pointer;
    color: var(--gmh-grey);
    padding: 4px 8px;
    border-radius: 6px;
    font-size: 14px;
}
.gmh-cal__nav:hover { background: var(--gmh-purple-soft); color: var(--gmh-purple-deep); }
.gmh-cal__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; text-align: center; }
.gmh-cal__dow { font: 600 10px/26px var(--gmh-font); color: var(--gmh-grey-faint); }
.gmh-cal__day {
    font: 400 11.5px/26px var(--gmh-font);
    border: 0;
    background: none;
    color: var(--gmh-ink);
    border-radius: 6px;
    cursor: pointer;
}
.gmh-cal__day:hover { background: var(--gmh-purple-hover); }
.gmh-cal__day.is-muted { color: var(--gmh-grey-faint); opacity: .5; }
.gmh-cal__day.is-in-range { background: var(--gmh-purple-soft); color: var(--gmh-purple-deep); }
.gmh-cal__day.is-selected { background: var(--gmh-purple); color: var(--gmh-on-purple); font-weight: 600; }
.gmh-cal__day:disabled { opacity: .3; cursor: not-allowed; }

/* ==========================================================================
   13. MAP: x-gmh.map
   Must stay the Google Maps JS API. The Static Maps API is NOT enabled on the
   GCP project (staticmap returns 403), see docs/OPEN_ITEMS.md. Anything
   reaching for a static map fails silently.
   ========================================================================== */
.gmh-map {
    width: 100%;
    height: 320px;
    border: 1px solid var(--gmh-line);
    border-radius: var(--gmh-radius);
    overflow: hidden;
    background: var(--gmh-head);
}
.gmh-map--sm { height: 200px; }
.gmh-map--lg { height: 480px; }
/* Fill the pane the page puts the map in, rather than a fixed height. The
   explicit height:auto is load-bearing: an absolutely positioned box with
   top, bottom AND a height ignores bottom, so .gmh-map's own 320px would
   otherwise win over the page's inset and leave the map short. */
.gmh-map--fill { position: absolute; inset: 0; height: auto; }
/* Shown until the API callback runs, and left in place if it never does. */
.gmh-map__fallback {
    height: 100%;
    display: grid;
    place-items: center;
    text-align: center;
    padding: 16px;
    font-size: 13px;
    color: var(--gmh-grey-faint);
}

/* ==========================================================================
   14. AUTH SHELL: layouts/gmh-auth.blade.php
   The 7 auth pages. Split-screen: brand panel left, form right.
   ========================================================================== */
.gmh-auth {
    min-height: 100vh;
    display: grid;
    grid-template-columns: minmax(0, 4fr) minmax(0, 6fr);
    background: var(--gmh-bg);
}
.gmh-auth__brand {
    background: linear-gradient(160deg, var(--gmh-purple), var(--gmh-purple-deep));
    color: var(--gmh-on-purple);
    padding: 40px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 28px;
}
.gmh-auth__logo {
    max-width: 170px;
    height: auto;
    /* The only logo asset is dark purple, which disappears on the purple panel.
       There is no white version in public/logo/, so render it white. */
    filter: brightness(0) invert(1);
}
.gmh-auth__tagline { font: 700 26px/1.25 var(--gmh-font); letter-spacing: -.02em; }
.gmh-auth__sub { font-size: 14px; opacity: .85; max-width: 32ch; margin-top: 10px; }
.gmh-auth__panel {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px 24px;
}
.gmh-auth__form { width: 100%; max-width: 380px; display: flex; flex-direction: column; gap: 14px; }
.gmh-auth__title { font: 700 24px/1.2 var(--gmh-font); color: var(--gmh-ink); }
.gmh-auth__lede { font-size: 13.5px; color: var(--gmh-grey); margin-top: 3px; }
.gmh-auth__foot { text-align: center; font-size: 12.5px; }
.gmh-auth__link { text-decoration: none; }
.gmh-auth__link:hover { text-decoration: underline; }
.gmh-auth__link { color: var(--gmh-purple); }

/* The brand panel is decoration; on a phone the form is all that matters. */
@media (max-width: 720px) {
    .gmh-auth { grid-template-columns: 1fr; }
    .gmh-auth__brand { display: none; }
}

/* ==========================================================================
   15. UTILITIES the components need
   Deliberately few. Prefer a Tailwind utility over adding to this list.
   ========================================================================== */
.gmh-stack { display: flex; flex-direction: column; gap: 12px; }

/* Read-only label and value pair: x-gmh.detail. The value is an <input> because
   the page scripts assign to .value; see the component for why that is not
   a <span>. It is styled to read as text, not as an editable field, so nobody
   tries to type in it. */
.gmh-detail { display: grid; grid-template-columns: minmax(120px, 34%) 1fr; gap: 10px; align-items: baseline; }
.gmh-detail__label { font: 500 12px/1.4 var(--gmh-font); color: var(--gmh-grey); }
.gmh-detail__value {
    font: 400 14px/1.45 var(--gmh-font);
    color: var(--gmh-ink);
    background: transparent;
    border: 0;
    padding: 0;
    width: 100%;
    cursor: default;
}
.gmh-detail__value:focus { outline: none; }
/* A long value, an address most often, has to wrap. An <input> cannot, so the
   multiline variant is a textarea: it still answers to .value, which is what the
   page scripts assign to, and it wraps. Resize and scrollbar are suppressed so it
   reads as text rather than as a control. */
.gmh-detail__value--multiline {
    resize: none;
    overflow: hidden;
    min-height: 2.9em;
    font: 400 14px/1.45 var(--gmh-font);
}
.gmh-detail__value--text { display: block; word-break: break-word; }
@media (max-width: 640px) { .gmh-detail { grid-template-columns: 1fr; gap: 2px; } }

/* A field following another field needs the step-3 gap. .gmh-stack and
   .gmh-card__body already supply it with flex gap, so they are excluded or the
   two would add up.

   This is a margin and not a third flex container on purpose. Several of these
   fields sit in a div the page's script shows and hides by writing
   element.style.display, and an inline display beats a class, so making the
   parent display:flex would give it a gap right up until the script touched it
   and then silently lose it. */
:not(.gmh-stack):not(.gmh-card__body) > .gmh-field + .gmh-field { margin-top: 12px; }
.gmh-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* Two cards side by side, stacking on narrow screens. The settings pages that
   need this held it in Bootstrap's .col-xl-6, which is not available to a page
   composing GMH components. Step-3 spacing, same as .gmh-stack. */
.gmh-cols-2 {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
    align-items: start;
}
@media (max-width: 900px) {
    .gmh-cols-2 { grid-template-columns: minmax(0, 1fr); }
}
.gmh-sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ==========================================================================
   16. DATATABLES: WEARING GMH
   GMH owns the look; DataTables owns the behaviour. These rules style what
   DataTables emits so a wrapped table stops looking like Bootstrap.
   Scoped to .gmh-table-wrap so no un-migrated page is affected.
   ========================================================================== */

/* Row action buttons sit in a col-md-4 grid from the DataTable class. Give them
   breathing room without an inline style on every one. */
.gmh-table-wrap .gmh-dt-action { padding: 3px 4px; }

/* DataTables' own "Show N entries" control. The GMH pattern puts rows-per-page
   in the footer beside "X-Y of Z", so this one is hidden and the footer control
   is the only one. Hidden, not removed: DataTables still reads it. */
.gmh-table-wrap .dataTables_length { display: none; }

/* Its search box is disabled via bFilter:false, but belt and braces, the page
   supplies x-gmh.search-bar instead. */
.gmh-table-wrap .dataTables_filter { display: none; }

/* Footer: info text and pager, in GMH type. */
.gmh-table-wrap .dataTables_info {
    font-size: 12.5px;
    color: var(--gmh-grey);
    padding: 10px 14px;
}
.gmh-table-wrap .dataTables_paginate { padding: 10px 14px; }
.gmh-table-wrap .dataTables_paginate a.paginate_button {
    display: inline-block;
    min-width: 28px;
    height: 28px;
    padding: 0 8px;
    margin-left: 4px;
    border: 1px solid var(--gmh-line) !important;
    border-radius: var(--gmh-radius-sm);
    background: var(--gmh-card) !important;
    color: var(--gmh-ink) !important;
    font: 500 12.5px/26px var(--gmh-font);
    text-align: center;
    cursor: pointer;
}
.gmh-table-wrap .dataTables_paginate a.paginate_button:hover {
    background: var(--gmh-purple-soft) !important;
    color: var(--gmh-purple-deep) !important;
}
.gmh-table-wrap .dataTables_paginate a.paginate_button.current {
    background: var(--gmh-purple) !important;
    border-color: var(--gmh-purple) !important;
    color: var(--gmh-on-purple) !important;
}
.gmh-table-wrap .dataTables_paginate a.paginate_button.disabled {
    opacity: .45;
    cursor: not-allowed;
}

/* The same pagination spec for Yajra's Bootstrap markup. The rules above target
   vanilla DataTables buttons, but every table built on DataTableTrait renders
   Bootstrap pagination (li.page-item > a.page-link), so those pages fell
   through to the old generic styling and looked like a different product. */
/* And the li that carries the same class in Bootstrap markup stays a plain
   wrapper: the box, border and spacing belong to the .page-link inside it.
   Before this, both got the full treatment and every button rendered as a
   bordered box inside a bordered box. */
.gmh-table-wrap .dataTables_paginate li.paginate_button {
    border: 0 !important;
    background: none !important;
    padding: 0;
    margin: 0;
    min-width: 0;
    height: auto;
}
.gmh-table-wrap .pagination { margin: 0; }
.gmh-table-wrap .pagination .page-link {
    min-width: 28px;
    height: 28px;
    padding: 0 8px;
    margin-left: 4px;
    border: 1px solid var(--gmh-line);
    border-radius: var(--gmh-radius-sm);
    background: var(--gmh-card);
    color: var(--gmh-ink);
    font: 500 12.5px/26px var(--gmh-font);
    text-align: center;
    box-shadow: none;
}
.gmh-table-wrap .pagination .page-link:hover {
    background: var(--gmh-purple-soft);
    color: var(--gmh-purple-deep);
}
.gmh-table-wrap .pagination .page-item.active .page-link {
    background: var(--gmh-purple);
    border-color: var(--gmh-purple);
    color: var(--gmh-on-purple);
}
.gmh-table-wrap .pagination .page-item.disabled .page-link {
    opacity: .45;
    cursor: not-allowed;
    background: var(--gmh-card);
    color: var(--gmh-grey-faint);
}

/* Header row: 13px/500 grey on the head background, NORMAL CASE. */
.gmh-table-wrap table.dataTable thead th {
    background: var(--gmh-head);
    color: var(--gmh-grey);
    font: 500 13px/1.4 var(--gmh-font);
    text-transform: none;
    border-bottom: 1px solid var(--gmh-line);
}
.gmh-table-wrap table.dataTable tbody td { border-top: 0; border-bottom: 1px solid var(--gmh-line-soft); }
.gmh-table-wrap table.dataTable tbody tr:hover { background: var(--gmh-purple-hover); }
.gmh-table-wrap table.dataTable tbody tr.is-selected,
.gmh-table-wrap table.dataTable tbody tr.is-selected:hover { background: var(--gmh-purple-soft); }
.gmh-table-wrap table.dataTable tbody tr.is-selected > td:first-child { box-shadow: inset 3px 0 0 var(--gmh-purple); }

/* ---------------------------------------------------------------------------
   Legacy toggle markup emitted by app/DataTables/*

   Twelve DataTables render

       <label class="switch"><input type="checkbox"><span class="slider round">

   and sixteen views each carried their own copy of the 61-line stylesheet for
   it: seven pasted inline, nine including announcement/partials/switch. Same
   control, drawn at 50x24 in a hardcoded green, depending on which copy the
   page happened to get.

   Defined once here, to the x-gmh.toggle spec, 36x20, purple when on. The
   DataTables belong to the Ops lane, so the markup cannot change; only the
   styling can, which is why this targets .switch rather than .gmh-toggle.

   Every page that still carries a local copy renders that copy from the body, which beats this file in the cascade. So this rule does nothing until a
   page's local copy is removed, and pages migrate one at a time.
--------------------------------------------------------------------------- */
.switch {
    position: relative;
    display: inline-block;
    flex: none;
    width: 36px;
    height: 20px;
    vertical-align: middle;
    cursor: pointer;
}
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }

.switch .slider {
    position: absolute;
    inset: 0;
    border-radius: var(--gmh-radius-pill);
    background: var(--gmh-line);
    transition: background-color .15s ease;
}
.switch .slider::before {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--gmh-card);
    transition: left .15s ease;
}

.switch input:checked + .slider { background: var(--gmh-purple); }
.switch input:checked + .slider::before { left: 18px; }
.switch input:focus-visible + .slider { outline: 2px solid var(--gmh-purple); outline-offset: 2px; }
.switch input:disabled + .slider { opacity: .5; cursor: not-allowed; }

@media (prefers-reduced-motion: reduce) {
    .switch .slider, .switch .slider::before { transition: none; }
}

/* ==========================================================================
   ROUTE PRICE MAP
   Click an origin, click a destination, price it, post the batch. The map is
   the Google Maps JS API with a Data layer, the same as the region map page.
   Stacked rather than side by side: the price table needs the full width,
   because it carries one column per car type and there are 27 of them.
   ========================================================================== */
.rpm-mapcard, .rpm-card {
    background: var(--gmh-card);
    border: 1px solid var(--gmh-line);
    border-radius: var(--gmh-radius);
    overflow: hidden;
}
/* A card holding a dropdown must not clip it. `overflow: hidden` is what keeps the map
   and the tab strip inside the rounded corners, but the multiselect panel is
   position:absolute and gets cropped by exactly the same rule, so the source picker
   opened into a sliver. This card has no child that needs clipping. */
.rpm-card--pop { overflow: visible; }
/* The shared panel is 240px, which suits a short filter list. This picker holds 121
   sources with names like "Klook Sky Mirror World Tour", so it takes a wider panel.
   Scoped here rather than changed on the component, which other callers use for
   short lists. */
.rpm-card--pop .gmh-ms { max-width: 420px; }
.rpm-mb { margin-bottom: 12px; }
.rpm-head {
    padding: 10px 13px;
    border-bottom: 1px solid var(--gmh-line);
    background: var(--gmh-bg);
    display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
}
/* The guide's table-card title: 18px/700 ink. At 13px the section header sat weaker
   than a bare bold <th>, and the charter grid read as if its header row were the title. */
.rpm-head h3 { margin: 0; font-size: 18px; font-weight: 700; color: var(--gmh-ink); }
.rpm-state, .rpm-meta { font-size: 11.5px; color: var(--gmh-grey-faint); margin-left: auto; }
.rpm-body { padding: 12px 13px; }
.rpm-srcrow { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.rpm-note { margin: 0; font-size: 11.5px; color: var(--gmh-grey); }
.rpm-map { width: 100%; height: 460px; }
.rpm-legend {
    display: flex; gap: 14px; flex-wrap: wrap;
    font-size: 11.5px; color: var(--gmh-grey);
    padding: 9px 13px; border-top: 1px solid var(--gmh-line);
}
.rpm-sw { display: inline-block; width: 11px; height: 11px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; }
.rpm-sw-origin { background: var(--gmh-purple); }
.rpm-sw-dest { background: var(--gmh-purple-soft); border: 1px solid var(--gmh-purple); }
.rpm-sw-sub { background: #EFF6FF; border: 1px dashed #1D4ED8; }
.rpm-hint {
    font-size: 12.5px; color: var(--gmh-grey);
    padding: 9px 13px; border-top: 1px solid var(--gmh-line); background: var(--gmh-bg);
}
.rpm-hint b { color: var(--gmh-purple-deep); }
.rpm-tabs {
    display: flex; gap: 2px; padding: 0 10px;
    border-bottom: 1px solid var(--gmh-line); overflow-x: auto;
}
.rpm-tab {
    font: 600 13px var(--gmh-font); padding: 9px 11px; color: var(--gmh-grey);
    border-bottom: 2px solid transparent; white-space: nowrap; cursor: pointer;
    display: flex; align-items: center; gap: 6px;
}
.rpm-tab:hover { color: var(--gmh-ink); }
.rpm-tab.is-on { color: var(--gmh-purple-deep); border-bottom-color: var(--gmh-purple); }
.rpm-n { font-size: 10.5px; color: var(--gmh-grey-faint); }
.rpm-x { color: var(--gmh-grey-faint); font-size: 13px; line-height: 1; }
.rpm-x:hover { color: var(--gmh-red); }
.rpm-notab { padding: 9px 11px; font-size: 12.5px; color: var(--gmh-grey-faint); }

/* The table. One row per destination, one column per car type, exactly like the old
   fixed route page. Scrolls sideways inside its own container so the page body never
   scrolls with it. */
.rpm-tablewrap { overflow-x: auto; }
.rpm-table { width: 100%; border-collapse: collapse; }

/* The guide's table header: 13px/500 grey on the header ground, normal case. Applies to
   every thead th in an rpm table so an unclassed <th> (the charter grid's were) can never
   fall back to browser-default bold ink and masquerade as a title row. */
.rpm-table thead th {
    background: var(--gmh-bg);
    font: 500 13px var(--gmh-font);
    color: var(--gmh-grey);
    text-align: left;
    padding: 9px 12px;
    border-bottom: 1px solid var(--gmh-line);
    white-space: nowrap;
}
.rpm-th {
    background: var(--gmh-bg);
    font: 500 13px var(--gmh-font);
    color: var(--gmh-grey);
    text-align: left;
    padding: 9px 12px;
    border-bottom: 1px solid var(--gmh-line);
    white-space: nowrap;
    position: sticky; top: 0;
}
.rpm-th--num, .rpm-th--act { text-align: center; }
.rpm-th--place { position: sticky; left: 0; z-index: 2; min-width: 190px; }
.rpm-td {
    padding: 7px 12px;
    border-bottom: 1px solid var(--gmh-line-soft);
    font-size: 13.5px;
    white-space: nowrap;
}
.rpm-td--place {
    font-weight: 600;
    position: sticky; left: 0;
    background: var(--gmh-card);
    z-index: 1;
}
.rpm-td--num, .rpm-td--act { text-align: center; }
.rpm-price {
    width: 78px;
    border: 1px solid var(--gmh-line);
    border-radius: 8px;
    padding: 5px 7px;
    font-size: 12.5px; font-weight: 700; text-align: right;
    background: var(--gmh-card); color: var(--gmh-ink);
}
.rpm-price:focus { outline: 2px solid var(--gmh-purple); outline-offset: -1px; }
.rpm-subtag {
    font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
    background: #EFF6FF; color: #1D4ED8; border-radius: 6px; padding: 2px 6px; margin-left: 6px;
}
.rpm-del { background: none; border: 0; cursor: pointer; color: var(--gmh-red); font: 600 11.5px var(--gmh-font); }
.rpm-del:hover { text-decoration: underline; }
.rpm-empty { padding: 26px 13px; text-align: center; color: var(--gmh-grey-faint); font-size: 12.5px; }
.rpm-bar {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    padding: 11px 13px; border-top: 1px solid var(--gmh-line); background: var(--gmh-bg);
}
.rpm-sum { font-size: 12px; color: var(--gmh-grey); margin-right: auto; }
.rpm-sum b { color: var(--gmh-ink); }
.rpm-clash {
    background: var(--gmh-amber-soft); border: 1px solid var(--gmh-amber);
    border-radius: 8px; padding: 8px 10px; margin-top: 9px;
    font-size: 11.5px; color: var(--gmh-ink); max-height: 150px; overflow: auto; line-height: 1.6;
}
.rpm-field { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--gmh-grey); }
.rpm-field select {
    border: 1px solid var(--gmh-line); border-radius: 8px; padding: 7px 10px;
    font-size: 13px; font-weight: 600; color: var(--gmh-ink); background: var(--gmh-card);
    min-width: 170px;
}
.rpm-field select:focus { outline: 2px solid var(--gmh-purple); outline-offset: -1px; }
/* An empty price box must read as empty. It previously carried a "0.00" placeholder,
   which looks exactly like a price of zero, and the whole engine turns on blank meaning
   "price it by formula" while zero means the journey is free. */
.rpm-price:placeholder-shown,
.rpm-price:not([value]):not(:focus) { border-style: dashed; }
.rpm-price[value=""]:not(:focus) { border-style: dashed; background: var(--gmh-bg); }
/* Driver earning is typed; the customer price is derived and sits under it, so the two are
   read together and nobody has to remember which side of the margin they are looking at. */
.rpm-sub2 { display: block; font-size: 9.5px; font-weight: 400; color: var(--gmh-grey-faint); text-transform: none; letter-spacing: 0; }
.rpm-sell { display: block; font-size: 10px; color: var(--gmh-grey-faint); margin-top: 2px; white-space: nowrap; }
.rpm-margin { font-weight: 700; font-size: 12.5px; color: var(--gmh-purple-deep); }
/* A margin that arrived from the global default must not look like a negotiated one. */
.rpm-margin.is-default { color: var(--gmh-grey); font-weight: 500; }
.rpm-nomargin { font-size: 11.5px; font-weight: 700; color: var(--gmh-red); }
.rpm-muted { color: var(--gmh-grey-faint); }
/* How much past work a suggestion stands on. A median of three jobs and a median of two
   thousand are not the same claim, so they are not drawn the same. */
.rpm-evidence { display: block; font-size: 9.5px; color: var(--gmh-grey-faint); white-space: nowrap; }
.rpm-evidence.is-thin { color: var(--gmh-amber); font-weight: 600; }
/* The Draw button sits in the map header and only appears when the current origin can
   actually be split, so it is never a control that refuses. */
.rpm-draw { margin-left: auto; }
.rpm-draw[hidden] { display: none; }

/* Google Places autocomplete (tracker #71): the default panel clips each
   result to one ellipsized line at the input's width, hiding exactly the part
   of the address that tells two results apart. Let items wrap and give the
   panel sensible room. Structure untouched - page JS reads .pac-item spans. */
.pac-container {
    min-width: 320px;
    max-width: min(560px, 92vw);
}
.pac-item {
    white-space: normal;
    height: auto;
    line-height: 1.35;
    padding: 6px 10px;
}
.pac-item .pac-item-query {
    white-space: normal;
}

/* --------------------------------------------------------------------------
   ROUTE PRICE STEPPER
   Three steps, each asking one question. The header says which you are on and
   what you have already answered, so the answers stay visible after the step
   that collected them is gone.
   -------------------------------------------------------------------------- */
.rpm-steps {
    display: flex; gap: 8px; flex-wrap: wrap;
    list-style: none; margin: 0 0 12px; padding: 0;
}
.rpm-step {
    display: flex; align-items: center; gap: 9px;
    flex: 1 1 200px; min-width: 0;
    background: var(--gmh-card);
    border: 1px solid var(--gmh-line);
    border-radius: var(--gmh-radius);
    padding: 9px 13px;
}
.rpm-stepn {
    display: grid; place-content: center; flex: none;
    width: 22px; height: 22px; border-radius: 50%;
    background: var(--gmh-line-soft); color: var(--gmh-grey);
    font: 700 11px var(--gmh-font);
}
.rpm-stept { font: 600 13px var(--gmh-font); color: var(--gmh-grey); min-width: 0; }
/* The answer sits under its own step, so what was chosen survives the step ending. */
.rpm-stept em {
    display: block; font: 400 11.5px var(--gmh-font); font-style: normal;
    color: var(--gmh-grey-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rpm-step.is-on { border-color: var(--gmh-purple); background: var(--gmh-purple-soft); }
.rpm-step.is-on .rpm-stepn { background: var(--gmh-purple); color: var(--gmh-on-purple); }
.rpm-step.is-on .rpm-stept { color: var(--gmh-purple-deep); }
.rpm-step.is-done .rpm-stepn { background: var(--gmh-green); color: #fff; }
.rpm-step.is-done .rpm-stept { color: var(--gmh-ink); }
.rpm-step.is-done .rpm-stept em { color: var(--gmh-green); }

.rpm-previews { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 760px) { .rpm-previews { grid-template-columns: 1fr; } }
.rpm-minimap { width: 100%; height: 220px; }

/* --------------------------------------------------------------------------
   Route price map: choosing destinations across regions.

   The region control sits in the map head rather than under "Applies to",
   because it says what you are looking at, not what the prices apply to. On
   step 2 a journey from KLIA can end in Kelantan or Sarawak, so switching
   region is how you get there and the picks made elsewhere are kept.
   -------------------------------------------------------------------------- */

.rpm-field--inline { margin-left: 0; font-size: 11.5px; }
/* A toolbar label sits beside its control, never above it: "Source of Order" was
   wrapping onto two lines in both pricing listings and pushing the toolbar taller
   than the search box beside it. Only the inline variant, because the drawer's
   full-width fields carry long hint labels that must still wrap. */
.rpm-field--inline > span { white-space: nowrap; }
.rpm-field--inline select { padding: 3px 8px; font-size: 11.5px; }

/* What has been chosen so far, grouped by the region it is in, so a
   destination in a region you are no longer looking at stays visible. */
.rpm-picked {
    border-top: 1px solid var(--gmh-line);
    padding: 10px 13px 12px;
    background: var(--gmh-bg);
}
.rpm-picked__head {
    display: flex; align-items: center; gap: 8px;
    font-size: 12px; color: var(--gmh-ink); margin-bottom: 8px;
}
.rpm-picked__body { display: flex; flex-direction: column; gap: 7px; }

.rpm-picked__group { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.rpm-picked__region {
    font-size: 10.5px; font-weight: 700; letter-spacing: .02em;
    color: var(--gmh-grey-faint); min-width: 104px;
}
/* The region currently on the map reads stronger, so the list and the map
   agree about where you are. */
.rpm-picked__group.is-here .rpm-picked__region { color: var(--gmh-purple-deep); }

.rpm-picked__item {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 3px 8px; font: inherit; font-size: 11.5px; line-height: 1.4;
    color: var(--gmh-ink); background: var(--gmh-card);
    border: 1px solid var(--gmh-line); border-radius: var(--gmh-radius-pill);
    cursor: pointer;
}
.rpm-picked__item:hover {
    border-color: var(--gmh-purple); background: var(--gmh-purple-soft);
}
.rpm-picked__item i { font-style: normal; color: var(--gmh-grey-faint); }
.rpm-picked__item:hover i { color: var(--gmh-purple-deep); }
.rpm-picked__item:focus-visible {
    outline: 2px solid var(--gmh-purple); outline-offset: 1px;
}

/* --------------------------------------------------------------------------
   Route price map: layout corrections from the first design review.

   Three misalignments and one duplicate, all found by looking at the built
   page against the reference rather than the code.
   -------------------------------------------------------------------------- */

/* The map head lays out as: title, then the picked-place name beside it, and
   the controls on the right. The shared .rpm-state rule pushes itself to the
   right edge with margin-left auto, where it fought the region control and
   wrapped onto its own line, so "Kuala Langat" floated above the Region
   select instead of sitting beside the title. */
.rpm-mapcard .rpm-state { margin-left: 0; }
.rpm-mapcard .rpm-dock { margin-left: auto; }
.rpm-mapcard .rpm-dock:empty { display: none; margin-left: 0; }

/* Every control on the "Applies to" row is 36px tall and vertically centred,
   so the multiselect trigger, the labels and the selects sit on one line
   instead of three slightly different ones. */
.rpm-srcrow { align-items: center; }
.rpm-srcrow .gmh-ms__trigger { min-height: 36px; padding-top: 0; padding-bottom: 0; }
.rpm-srcrow .rpm-field select,
.rpm-srcrow select { height: 36px; padding-top: 0; padding-bottom: 0; }
/* .rpm-field carries a bottom margin for stacked layouts. In this row flexbox
   centres the margin box, so that margin pushed the selects 4px above the
   multiselect trigger. Measured on the built page: trigger top 215, selects
   top 211, all three 36px tall. */
.rpm-srcrow .rpm-field,
.rpm-srcrow .rpm-dock .rpm-field { color: var(--gmh-grey); margin-bottom: 0; }
.rpm-srcrow .rpm-note { flex-basis: 100%; margin-top: 2px; }

/* The docked region control matches the row it lands in: full size among the
   step 1 pickers, compact when it sits on the map head in step 2. */
.rpm-dock { display: inline-flex; align-items: center; }
.rpm-srcrow .rpm-dock .rpm-field--inline { font-size: 12px; }
.rpm-srcrow .rpm-dock .rpm-field--inline select { height: 36px; font-size: 13px; }

/* Step 2's journey card: what was settled on step 1, read only, beside the
   region control. Same row and heights as "Applies to" so the two steps read
   as one screen changing question. */
.rpm-ctx { font-size: 13px; color: var(--gmh-ink); }
.rpm-ctx b { font-weight: 700; }
.rpm-ctx--muted { color: var(--gmh-grey); font-size: 12px; }

/* The hover label floats over the map, so pointing at a polygon can never
   move the map. It sits clear of the fullscreen control and ignores the
   pointer so it cannot flicker under its own cursor. */
.rpm-mapwrap { position: relative; }
.rpm-hoverchip {
    position: absolute; top: 10px; left: 10px;
    padding: 4px 11px; font-size: 12px; font-weight: 600;
    color: var(--gmh-ink); background: var(--gmh-card);
    border: 1px solid var(--gmh-line); border-radius: var(--gmh-radius-pill);
    box-shadow: 0 1px 3px rgba(17, 24, 39, .12);
    pointer-events: none;
}

/* The map card head holds text that comes and goes (the picked origin) and a
   button that appears once an origin is chosen. Pinning the height means
   neither can resize the head, so the map never shifts under the cursor. */
.rpm-mapcard .rpm-head { min-height: 56px; }

/* The past order price under each box: quiet until pointed at, clickable to
   apply, and amber when it stands on thin evidence. */
.rpm-sug {
    display: block; margin-top: 2px; padding: 0;
    border: 0; background: none; cursor: pointer;
    font: inherit; font-size: 10.5px; color: var(--gmh-grey-faint);
}
.rpm-sug:hover { color: var(--gmh-purple-deep); text-decoration: underline; }
.rpm-sug.is-thin { color: var(--gmh-amber); }
a.rpm-margin { text-decoration: underline dotted; text-underline-offset: 2px; }
a.rpm-margin:hover { color: var(--gmh-purple-deep); }

/* Charter rate grid: the car type cell shows the vehicle, because 27 rows of
   near-identical names read faster with the picture the customer sees. */
.chr-car { display: inline-flex; align-items: center; gap: 10px; }
.chr-car__img {
    width: 56px; height: 34px; object-fit: contain; flex-shrink: 0;
    background: var(--gmh-bg); border: 1px solid var(--gmh-line-soft);
    border-radius: var(--gmh-radius-sm);
}

/* Charter rate grid corrections, all measured on the built page.

   The car type column was 938px wide because nothing else claimed the slack,
   leaving a void between the name and its numbers; the rate cell centred a
   78px input inside 381px; the headers were left aligned over mixed cells;
   and the margin chips floated in a 44px card of their own. */
.chr-map { height: 340px; }

.chr-table .chr-num,
.chr-table th.chr-num { text-align: right; }
.chr-table .chr-num .rpm-sell,
.chr-table .chr-num .rpm-sug { display: block; text-align: right; }
.chr-table .chr-num .rpm-sug { margin-left: auto; }
.chr-table input.chr-price { text-align: right; }

/* The margins doing the converting, docked as a row of the Applies-to card so
   the number that divides the price sits beside the controls that pick it. */
.chr-margins {
    flex-basis: 100%;
    display: flex; gap: 14px; flex-wrap: wrap;
    padding-top: 8px; margin-top: 4px;
    border-top: 1px solid var(--gmh-line-soft);
    font-size: 12px;
}

/* Full width, on the user's direction (2026-09-10): the grid fills the card like
   every other table; the colgroup pins the two numeric columns so the car name
   column takes the slack. */
.chr-table { width: 100%; }

/* The two grouped checkbox pickers on the charter page earn more room: source and
   region names are long, and a cramped trigger truncates what was chosen. */
.chr-ms { min-width: 300px; }

/* ------------------------------------------------------------------ price calculator
   Three columns: the journey's what, its where, and the price with its settings. The map
   column takes the slack because pins want room; the two side columns hold their width so
   the controls and the breakdown read as fixed instruments. Collapses to one column on
   anything narrower than a desk. */
.pca-grid { display: grid; grid-template-columns: 300px minmax(420px, 1fr) 340px; gap: 12px; align-items: start; }
@media (max-width: 1100px) { .pca-grid { grid-template-columns: 1fr; } }

.pca-fields { display: flex; flex-direction: column; gap: 10px; }
.pca-dim { color: #9CA3AF; font-style: normal; font-weight: 400; font-size: 11px; margin-left: 4px; }
.pca-carimg { width: 96px; height: 54px; object-fit: contain; align-self: flex-end; margin-top: -6px; }

.pca-check { display: flex; align-items: center; gap: 8px; font-size: 13px; color: #374151; cursor: pointer; }
.pca-check input { accent-color: #9B3BAD; width: 15px; height: 15px; }

/* The bid panel, shown only when the distance breaker fires. */
.pca-bid { display: grid; gap: 10px; padding: 12px; border: 1px solid var(--gmh-line); border-left: 3px solid #1D4ED8; border-radius: 10px; background: #F9FAFB; }
.pca-bidlist { display: grid; gap: 2px; max-height: 160px; overflow: auto; }
.pca-bidrow { display: flex; justify-content: space-between; gap: 10px; align-items: center; width: 100%; text-align: left; border: 0; background: #fff; border: 1px solid var(--gmh-line); border-radius: 8px; padding: 6px 10px; font-size: 12.5px; cursor: pointer; }
.pca-bidrow:hover { background: #FAF5FF; }
.pca-bidrow span { color: var(--gmh-grey); font-size: 11.5px; }
.pca-bidpicked { display: flex; flex-wrap: wrap; gap: 6px; }
.pca-bidchip { display: inline-flex; align-items: center; gap: 6px; background: var(--gmh-purple-soft); color: var(--gmh-purple-deep); border-radius: 999px; padding: 3px 10px; font-size: 12px; font-weight: 600; }
.pca-bidchip button { border: 0; background: none; color: inherit; cursor: pointer; font-size: 14px; line-height: 1; padding: 0; }

/* The internal expected fleet cost. Visually set apart from the totals above it, because
   it is not one of them and must never be read as a customer figure. */
.pca-estcost { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-top: 8px; padding: 8px 10px; border: 1px dashed var(--gmh-line); border-radius: 8px; background: #F9FAFB; font-size: 12.5px; color: var(--gmh-grey); }
.pca-estcost b { color: var(--gmh-ink); font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums; }

/* The engine's price in Create Job, accounted for line by line on the page rather than in a
   tooltip. A figure nobody can reconcile is a figure nobody trusts. */
.cj-engine { margin-top: 6px; font: 400 12px/1.5 var(--gmh-font); }
.cj-engine__fold { border: 1px solid var(--gmh-line); border-radius: 8px; background: #F9FAFB; }
.cj-engine__fold > summary { cursor: pointer; padding: 7px 10px; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; color: var(--gmh-purple-deep); }
.cj-engine__fold > summary b { font-weight: 700; }
.cj-engine__presented { color: var(--gmh-ink); font-weight: 600; }
.cj-engine__hint { color: var(--gmh-grey-faint); font-size: 11px; }
.cj-engine__lines { padding: 2px 10px 8px; display: grid; gap: 2px; }
.cj-engine__row { display: flex; justify-content: space-between; gap: 12px; color: var(--gmh-grey); }
.cj-engine__row b { color: var(--gmh-ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.cj-engine__note { color: var(--gmh-amber-ink, #92400E); font-size: 11.5px; padding-top: 2px; }
.cj-engine__cost { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin: 6px 10px 8px; padding-top: 7px; border-top: 1px dashed var(--gmh-line); color: var(--gmh-grey); }
.cj-engine__cost b { color: var(--gmh-ink); font-weight: 700; font-variant-numeric: tabular-nums; }
/* Visibility is CSS, not JavaScript, on purpose.

   It was a `hidden` attribute that only the script could remove, so a stale or failed script
   made the whole panel disappear rather than show an empty one. A feature that vanishes
   silently is worse than one that says nothing useful: there is nothing to report and nothing
   to refresh. Now the radio drives it directly, the script only fills it in, and the worst a
   broken script can do is leave the card showing its server-rendered line. */
/* The panel is shown by CSS, keyed off the radio, so a stale or failed script cannot leave
   it permanently hidden. It is relevant to two of the four answers: choosing one driver, and
   picking the order the club is offered the job in. */
.cj-match-card { display: none; }
.cj-step-body:has(input[name="cj_driver_choice"][value="assign"]:checked) .cj-match-card,
.cj-step-body:has(input[name="cj_driver_choice"][value="club"]:checked) .cj-match-card { display: block; }

/* The rejection window only means anything for the club offer. */
.cj-window { display: none; margin-top: 12px; padding: 10px 12px; border: 1px solid var(--gmh-line);
             border-radius: 8px; background: var(--gmh-bg-head, #F9FAFB); }
.cj-step-body:has(input[name="cj_driver_choice"][value="club"]:checked) .cj-window { display: block; }
.cj-window-opts { display: flex; flex-wrap: wrap; gap: 6px 14px; margin: 6px 0 4px; }
.cj-window-opts label { display: inline-flex; align-items: center; gap: 5px; font-size: 13px;
                        color: var(--gmh-ink); cursor: pointer; }

/* Driver rows, matched to the swap driver dialog so the two screens read as one product. */
.cj-drv { width: 100%; border-collapse: collapse; margin-top: 8px; font-size: 13px; }
.cj-drv th { background: #F9FAFB; font-size: 13px; font-weight: 500; color: #6B7280; text-align: left;
             padding: 8px 10px; border-bottom: 1px solid #E5E7EB; white-space: nowrap; }
.cj-drv td { padding: 9px 10px; border-bottom: 1px solid #F3F4F6; vertical-align: middle; }
.cj-drv tr:last-child td { border-bottom: 0; }
.cj-drv tr:hover td { background: #FAF5FF; }
.cj-who { display: flex; align-items: center; gap: 9px; }
.cj-av { width: 30px; height: 30px; border-radius: 50%; background: #F5E9F7; color: #7E22CE; flex: none;
         display: inline-flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 700; }
.cj-who b { display: block; font-weight: 600; color: #111827; }
.cj-who small { display: block; font-size: 11.5px; color: #9CA3AF; }
.cj-mpct { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; }
.cj-mbar { height: 5px; width: 70px; border-radius: 3px; background: #F3F4F6; margin-top: 3px; }
.cj-mbar i { display: block; height: 5px; border-radius: 3px; }
.cj-pick { font-size: 12.5px; font-weight: 600; padding: 5px 12px; border-radius: 8px; cursor: pointer;
           border: 1px solid #E5E7EB; background: #fff; color: #7E22CE; white-space: nowrap; }
.cj-pick.is-on { background: #9B3BAD; border-color: #9B3BAD; color: #fff; }
.cj-rank { display: inline-block; min-width: 20px; font-weight: 700; color: #7E22CE;
           font-variant-numeric: tabular-nums; }

/* "Who could take this" on the Create Job driver step. Ranking only: it assigns nobody, so
   it is deliberately flatter than the assign list and carries no action per row. */
.cj-match-refresh { float: right; border: 1px solid var(--gmh-line); background: #fff; color: var(--gmh-purple-deep); border-radius: 6px; padding: 2px 9px; font: 600 11.5px/1.6 var(--gmh-font); cursor: pointer; }
.cj-match-refresh:hover { background: var(--gmh-purple-soft); }
.cj-match-body { font: 400 12.5px/1.5 var(--gmh-font); color: var(--gmh-grey); display: grid; gap: 2px; }
.cj-match-row { display: grid; grid-template-columns: 34px minmax(0, 1fr) minmax(0, 1.3fr); gap: 10px; align-items: baseline; padding: 4px 0; border-top: 1px solid var(--gmh-line-soft); }
.cj-match-row:first-child { border-top: 0; }
.cj-match-score { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--gmh-ink); text-align: right; }
.cj-match-name { color: var(--gmh-ink); font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
.cj-match-name em { font-style: normal; font-size: 10.5px; font-weight: 700; color: var(--gmh-purple-deep); background: var(--gmh-purple-soft); border-radius: 5px; padding: 1px 5px; margin-left: 6px; }
.cj-match-why { color: var(--gmh-grey-faint); font-size: 11.5px; }
.cj-match-none { color: var(--gmh-amber-ink, #92400E); background: var(--gmh-amber-soft, #FFFBEB); border: 1px solid var(--gmh-amber, #FDE68A); border-radius: 8px; padding: 8px 10px; }
.cj-match-foot { color: var(--gmh-grey-faint); font-size: 11px; padding-top: 6px; }
@media (max-width: 640px) { .cj-match-row { grid-template-columns: 30px minmax(0, 1fr); } .cj-match-why { grid-column: 2; } }

/* Which rates and knobs decided the price, the same fold the Price a journey drawer shows.
   Nested inside the engine block, so it opens one level deeper and stays out of the way. */
.cj-engine__settings { margin: 0 10px 8px; padding-top: 6px; border-top: 1px dashed var(--gmh-line); }
.cj-engine__settings > summary { color: var(--gmh-grey-faint); font-size: 11.5px; padding: 2px 0; }
.cj-engine__settings > summary:hover { color: var(--gmh-purple); }
.cj-engine__settings .cj-engine__row { font-size: 11.5px; padding-top: 2px; }

/* A contradiction is not a clash: nothing is lost, two rows just answer one question. */
.rpm-clash--soft {
    background: #F9FAFB; border: 1px solid var(--gmh-line); border-left: 3px solid #1D4ED8;
}

/* Address search inside the drawer. Google's own .pac-container is appended to <body> at
   z-index 1000 and the drawer sits at 1090, so the list has to be drawn in here instead. */
.pca-addr { position: relative; }
.pca-suggest { display: none; position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 40; background: #fff; border: 1px solid #E5E7EB; border-radius: 10px; overflow: hidden; box-shadow: 0 14px 30px -12px rgba(17, 24, 39, .4); }
.pca-suggest-row { display: block; width: 100%; text-align: left; border: 0; background: #fff; padding: 8px 12px; font-size: 12.5px; cursor: pointer; border-bottom: 1px solid #F3F4F6; }
.pca-suggest-row:last-child { border-bottom: 0; }
.pca-suggest-row:hover { background: #FAF5FF; }
.pca-suggest-row b { display: block; font-weight: 600; color: #111827; }
.pca-suggest-row span { color: #6B7280; font-size: 11.5px; }

/* The resolved settlement margin, shown as a read-only fact rather than a field. */
.pca-marginres { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; padding: 8px 10px; border: 1px solid #E5E7EB; border-radius: 8px; background: #F9FAFB; font-size: 13.5px; color: #111827; }
.pca-marginres b { font-size: 15px; font-weight: 700; }
.pca-marginres__tag { border-radius: 6px; background: #FEF3C7; color: #92400E; padding: 1px 6px; font-size: 10.5px; font-weight: 700; text-transform: uppercase; }
.pca-marginover { margin-top: 8px; }

.pca-extras { display: flex; flex-direction: column; gap: 6px; padding: 8px 10px; border: 1px solid #E5E7EB; border-radius: 8px; background: #F9FAFB; }

.pca-presets { display: flex; flex-wrap: wrap; gap: 6px; }
.pca-preset { border: 1px solid #E5E7EB; background: #fff; color: #374151; border-radius: 999px; padding: 5px 12px; font-size: 12px; font-weight: 600; cursor: pointer; }
.pca-preset:hover { background: #FAF5FF; }
.pca-preset.is-on { background: #F5E9F7; border-color: #9B3BAD; color: #7E22CE; }

.pca-modes { display: flex; gap: 6px; padding: 0 12px 10px; }
.pca-mode { border: 1px solid #E5E7EB; background: #fff; color: #374151; border-radius: 8px; padding: 5px 12px; font-size: 12px; font-weight: 600; cursor: pointer; }
.pca-mode.is-on { background: #9B3BAD; border-color: #9B3BAD; color: #fff; }
.pca-mode--clear { margin-left: auto; color: #DC2626; }

.pca-map { min-height: 420px; }
.pca-resolved { padding: 8px 12px; font-size: 12.5px; color: #374151; border-top: 1px solid #F3F4F6; min-height: 20px; }
.pca-warn { color: #D97706; font-weight: 600; }

.pca-dists { display: flex; gap: 12px; padding: 0 12px 10px; }
.pca-dists .rpm-field { flex: 1; }

.pca-stops { display: flex; flex-direction: column; gap: 6px; padding: 0 12px 12px; }
.pca-stop { display: flex; align-items: center; gap: 8px; background: #FFFBEB; border: 1px solid #FDE68A; border-radius: 8px; padding: 6px 8px; font-size: 12px; color: #374151; }
.pca-stop label { display: flex; align-items: center; gap: 4px; margin: 0; font-size: 11.5px; color: #6B7280; }
.pca-stop input { border: 1px solid #E5E7EB; border-radius: 6px; padding: 3px 6px; font-size: 12.5px; width: 64px; }
.pca-stop .pca-stop__label { width: 110px; flex: 1; }

.pca-lines { display: flex; flex-direction: column; }
.pca-line { display: flex; justify-content: space-between; gap: 10px; padding: 6px 0; border-bottom: 1px solid #F3F4F6; font-size: 13px; color: #374151; }
.pca-line b { font-variant-numeric: tabular-nums; color: #111827; white-space: nowrap; }
.pca-line--margin { color: #7E22CE; }
.pca-line--margin b { color: #7E22CE; }

.pca-notes { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.pca-note { background: #FFFBEB; border: 1px solid #FDE68A; border-radius: 8px; padding: 6px 10px; font-size: 12px; color: #92400E; }

.pca-refused { background: #FEF2F2; border: 1px solid #FECACA; border-radius: 8px; padding: 10px 12px; font-size: 13px; color: #991B1B; margin-bottom: 8px; }

.pca-totals { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; margin-top: 12px; text-align: center; }
.pca-total { border-radius: 8px; padding: 8px 6px; border: 1px solid #E5E7EB; background: #F9FAFB; }
.pca-total span { display: block; font-size: 10.5px; color: #6B7280; }
.pca-total b { font-size: 15px; font-variant-numeric: tabular-nums; color: #111827; }
.pca-total--sell { background: #16A34A; border-color: #16A34A; }
.pca-total--sell span, .pca-total--sell b { color: #fff; }

.pca-settings { display: flex; flex-direction: column; }
.pca-set { display: flex; justify-content: space-between; gap: 10px; padding: 5px 0; border-bottom: 1px solid #F3F4F6; font-size: 12.5px; color: #6B7280; }
.pca-set b { color: #111827; font-weight: 600; text-align: right; }

/* --- the calculator as a step drawer ---------------------------------------
   The drawer needs room for a map, so it widens past the component's 320px filter
   default. Step panes swap; the stepper above them is re-dressed by JS. */
#pcaDrawer { width: 640px; max-width: 96vw; }
#pcaDrawer .gmh-drawer__body { gap: 10px; }
.pca-step { display: flex; flex-direction: column; gap: 10px; }
.pca-step[hidden] { display: none; }
.pca-map--drawer { min-height: 320px; height: 320px; border-radius: 8px; }
.pca-presetsrow { display: flex; flex-direction: column; gap: 6px; padding-bottom: 4px; border-bottom: 1px solid #F3F4F6; }
.pca-nav { display: flex; gap: 8px; align-items: center; margin-top: auto; padding-top: 10px; border-top: 1px solid #F3F4F6; }
.pca-navgap { flex: 1; }
.pca-settingsfold summary { font-size: 12.5px; font-weight: 600; color: #6B7280; cursor: pointer; padding: 4px 0; }

/* A step that can be reopened says so. The current step and any step with no answer
   yet are inert, so clicking never lands somewhere that has nothing to show. */
.rpm-step.is-clickable { cursor: pointer; }
.rpm-step.is-clickable:hover { border-color: var(--gmh-purple); background: var(--gmh-purple-soft); }

/* The drawer's fields are the standard x-gmh.field stack now, so the old flex row
   spacing does not apply to them. A field carries its own label and hint; these only
   space the stack and keep the map and the car photo in proportion. */
#pcaDrawer .gmh-field { margin-bottom: 10px; }
#pcaDrawer .pca-dim { display: block; margin-top: 4px; }
