/* ReviewTap brand overrides on top of Metronic's compiled style.bundle.css.
   Metronic ships no buildable Sass in this package (compiled CSS only), so
   these are runtime --bs-* custom property overrides rather than a Sass
   variable change - same technique already used elsewhere in this app to
   retheme Bootstrap defaults. !important is needed because style.bundle.css
   redeclares --bs-primary (and friends) directly at :root, at the same
   specificity, later in its own source order - see
   documentation/metronic-integration-plan.md. */
:root {
    --bs-primary: #2563eb !important;
    --bs-primary-active: #1d4ed8 !important;
    --bs-primary-light: #eff6ff !important;
    --bs-primary-inverse: #ffffff !important;
    --bs-primary-rgb: 37, 99, 235 !important;
    --bs-primary-clarity: rgba(37, 99, 235, 0.2) !important;
    --bs-primary-bg-subtle: #dbeafe !important;
    --bs-primary-border-subtle: #93c5fd !important;
    --bs-primary-text-emphasis: #1e40af !important;
    /* Metronic's own default (#F1F1F4) is barely visible - the design
       system calls for a slightly more defined, standard neutral border. */
    --bs-border-color: #E5E7EB !important;
}

/* Defensive fallback for Metronic's own sidebar-push CSS
   ([data-kt-app-sidebar-fixed=true] .app-wrapper, inside its own
   @media (min-width: 992px) block in style.bundle.css) - that rule is
   correctly written and KTDrawer.handleResize() in scripts.bundle.js is
   correctly wired to re-evaluate the sidebar's own off-canvas state on
   resize, but the *content* side (this margin) was observed staying
   stuck at its load-time value when an already-open window is resized
   narrower without a full page reload - the main content area gets
   squeezed into a sliver instead of reclaiming the sidebar's space,
   which is what made the Hűségkártya tab (and everything else) look
   broken/oversized at a resized narrow width. A plain media query here,
   loaded after style.bundle.css, is a low-risk way to guarantee this
   specific value stays correct regardless of that upstream timing -
   doesn't touch Metronic's own JS/CSS, just backstops the one property
   that was observed going stale. */
@media (max-width: 991.98px) {
    .app-wrapper {
        margin-left: 0 !important;
    }
}

/* Sitewide 90% density pass, admin panel only. Originally this file was
   only ever @included from admin.blade.php/admin login.blade.php, so a
   blanket html/body selector was an admin-only rule in effect - but
   layouts/portal.blade.php and portal/auth/login.blade.php (2026-08)
   later started loading this same file too (for its --bs-primary/
   --bs-gray-* overrides), which silently pulled this "admin only" density
   pass onto the client-facing portal as well, shrinking its header/nav/
   avatar to ~90% of the portal's own intended size. Scoped to
   html.rt-density-90 now (set on admin.blade.php's and admin/auth/
   login.blade.php's <html> tag - see rt-density-90 in git blame) so this
   rule only ever matches where it's deliberately opted into, instead of
   leaking onto any future page that links this stylesheet for an
   unrelated reason.
   The user compared the panel at 100% browser zoom against 90% zoom and
   preferred 90% across the board - not just smaller text, but smaller
   padding/gaps/icons/sidebar width too, since browser zoom scales
   literally everything together. Since Bootstrap (and this app's own
   .rt-* classes) size almost everything in rem, scaling the root
   font-size cascades that same reduction through nearly every measurement
   at once, without the other side effects of an actual browser zoom
   (cursor size, native dialog sizing, etc.).
   Metronic's own style.bundle.css already sets html/body font-size itself,
   with !important, at three responsive tiers (13px desktop, 12px tablet,
   12px mobile) - that base was invisibly already in effect (a first
   attempt here without !important and without matching those exact tiers
   silently did nothing, beaten by Metronic's !important). Multiplying
   each of Metronic's own tiers by 0.9 - not just adding a flat 16px-based
   override - is what actually reproduces "the whole panel at 90%" instead
   of landing on some unrelated size. Any hard-coded px value elsewhere
   (Metronic's own bundle, Keenicons glyph sizes) won't shrink with it -
   swept the main admin pages after this to check for anything left
   looking oversized. */
html.rt-density-90,
html.rt-density-90 body {
    font-size: 11.7px !important;
}

/* Reserves the vertical scrollbar's width permanently instead of only
   when a page is tall enough to need it - without this, switching to a
   shorter wallet-card tab (e.g. Extra, 1 box) vs. a taller one
   (Alapbeállítások, 5 boxes) makes the scrollbar appear/disappear, which
   shrinks/grows the whole page's content width by the scrollbar's size
   each time - the .wallet-section cards were never actually different
   widths, the *page* was silently resizing under them. */
html {
    scrollbar-gutter: stable;
}

@media (max-width: 991.98px) {
    html.rt-density-90,
    html.rt-density-90 body {
        font-size: 10.8px !important;
    }
}

/* The desktop sidebar's width is a flat 265px in style.bundle.css, not a
   rem value - it doesn't shrink on its own just because the root font-size
   did, which is exactly the "sidebar too" half of the request. Same 0.9
   multiplier, same @media (min-width: 992px) scoping Metronic itself uses
   for this var (that's also where .app-sidebar's own width:
   var(--bs-app-sidebar-width) rule lives), so this only touches the
   desktop expanded sidebar and leaves the minimize/sticky/collapsed
   variants (each redeclared under their own [data-kt-app-sidebar-*]
   attribute selector, higher specificity than plain :root) alone. */
@media (min-width: 992px) {
    :root {
        --bs-app-sidebar-width: 238.5px;
        --bs-app-sidebar-width-actual: 238.5px;
    }
}

/* Bootstrap 5.3's .text-secondary utility maps to the $secondary THEME
   color (buttons/badges), not a muted-text tone - Bootstrap's default
   $secondary (#6c757d) happens to double as readable gray text by
   coincidence, but Metronic redefines --bs-secondary to #F1F1F4 (a very
   light background/chip color), so every .text-secondary label rendered
   almost invisible. The correct utility is --bs-secondary-color (used by
   .text-body-secondary) - overriding .text-secondary itself here instead
   of hunting down every template that used the wrong class name. */
.text-secondary {
    color: var(--bs-secondary-color) !important;
}

/* Big bold stat-tile numbers - same recipe Metronic's own demo widgets use
   inline (fs-2hx fw-bold text-gray-900 lh-1 ls-n2), promoted to a reusable
   class instead of repeating 5 utility classes on every stat tile. */
.stat-value {
    font-size: 2.075rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1;
    color: var(--bs-gray-900);
}

/* Visual radio/checkbox-card picker (landing theme, redirect mode pickers)
   - Metronic has no equivalent component. Ported from the previous vanilla-
   Bootstrap build's Sass version to plain CSS, referencing Metronic's own
   exposed --bs-* custom properties instead of Sass variables (this package
   ships no buildable Sass to hook into). */
.picker-card {
    width: 140px;
    cursor: pointer;
}

.picker-card.picker-card-wide {
    width: 220px;
}

.picker-card input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
}

.picker-card:has(input:checked) .picker-card-thumb {
    border-color: var(--bs-primary) !important;
    color: var(--bs-primary) !important;
    box-shadow: 0 0 0 3px var(--bs-primary-clarity);
}

.picker-card-thumb {
    height: 78px;
    background-color: var(--bs-gray-100);
    background-size: cover;
    background-position: center;
    transition: border-color .15s ease, box-shadow .15s ease, color .15s ease;
}

.picker-card-thumb-icon {
    flex-direction: column;
    gap: .375rem;
    padding: 14px;
}

.picker-card-thumb-icon svg {
    width: 26px;
    height: 26px;
}

/* Modern, minimalist toggle switch (admin/partials/toggle-switch.blade.php)
   - replaces Bootstrap's default switch (a thin track with a small SVG
   circle drawn into the background-image) with a flat pill track and a
   real sliding thumb drawn via ::before, no markup changes needed since
   it's the exact same single <input type="checkbox" role="switch"> from
   the partial, just re-skinned. Bigger and higher-contrast so on/off reads
   clearly at a glance. Placed before the warning-variant rule below so
   that rule's :checked background-color (equal specificity, also
   !important) wins for that variant via source order. */
.form-switch .form-check-input {
    --bs-form-switch-bg: none !important;
    position: relative;
    width: 42px;
    height: 24px;
    background-image: none !important;
    background-color: var(--bs-gray-300) !important;
    background-position: initial !important;
    border: none !important;
    border-radius: 999px;
    margin-top: 0;
    transition: background-color .2s ease;
    cursor: pointer;
}

.form-switch .form-check-input::before {
    content: '';
    position: absolute;
    top: 3px;
    left: 3px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
    transition: transform .2s ease;
}

.form-switch .form-check-input:checked {
    background-color: var(--bs-primary) !important;
}

.form-switch .form-check-input:checked::before {
    transform: translateX(18px);
}

.form-switch .form-check-input:focus {
    box-shadow: 0 0 0 3px var(--bs-primary-clarity) !important;
}

/* Amber variant of the toggle-switch partial (admin/partials/toggle-switch.blade.php)
   - used where "on" means something to pay attention to (a locked physical
   card), rather than a neutral feature flag. */
.form-switch-warning .form-check-input:checked {
    background-color: var(--bs-warning) !important;
}

/* Wraps the toggle-switch partial directly in a .card with no .card-body
   (so it needs its own padding) - used for the physical-card lock switch.
   Ported from the retired public/css/admin.css: layouts/admin.blade.php
   stopped loading that file once Metronic landed, which silently made this
   rule dead code (the card rendered, just as a plain unstyled white box
   with no visual "this is locked" cue even when checked) - found while
   reorganizing cards/edit.blade.php, not a new component. */
.toggle-switch-card {
    padding: 20px 26px;
}

.toggle-switch-card.is-warning-on {
    border-color: var(--bs-warning) !important;
    background: var(--bs-warning-light) !important;
}

/* Uppercase section label (dashboard: "Ügyfelek" / "Bevétel" / "Beolvasások"). */
.section-label {
    font-size: .78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--bs-gray-600);
    margin: 1.75rem 0 .75rem;
}

.section-label:first-child {
    margin-top: 0;
}

/* .tab-btn elements are <button>s (see clients/show.blade.php's tab JS) -
   for reasons not fully tracked down (same issue seen with vanilla
   Bootstrap), a button.nav-link doesn't pick up the theme's nav-link text
   color and renders plain black. Forced explicitly here.
   Neutral-gray redesign (2026-08-13): deliberately no primary/blue accent
   here - the active tab reads as "selected" via a subtle gray fill + a
   short dark underline, not a color change, so the whole bar stays calm
   and doesn't compete with actual call-to-action buttons elsewhere on the
   page. Compact padding/font-size keeps the bar usable with long client
   names on narrower screens. */
.nav-tabs {
    gap: 2px;
}

.nav-tabs .nav-link {
    color: var(--bs-gray-600);
    font-weight: 500;
    font-size: .875rem;
    border: none;
    border-bottom: 2px solid transparent;
    border-radius: 6px 6px 0 0;
    padding: .5rem .875rem;
    background: transparent;
    transition: background-color .12s ease, color .12s ease;
}

.nav-tabs .nav-link:hover:not(.active) {
    color: var(--bs-gray-800);
    background: var(--bs-gray-100);
}

.nav-tabs .nav-link.active {
    color: var(--bs-gray-900) !important;
    font-weight: 600;
    background: var(--bs-gray-200);
    border-bottom: 2px solid var(--bs-gray-800);
}

/* Location edit/create form's tab bar (.lf-tabs, admin/locations/_form.blade.php)
   - a segmented row of bordered boxes rather than the underline-tab style
   above. The underline alone (only the active tab gets any visual
   treatment at all, inactive ones are bare text with no button/box
   boundary) read as plain unstyled text rather than "these are tabs,
   click one" - boxes sitting side by side make every tab look clickable,
   not just the active one - that reasoning still holds, so the boxed
   shape stays even after the 2026-08-13 neutral-tones pass. What changed:
   the active tab used to be a solid primary-blue fill with white text;
   now it's the same light-gray-fill + dark-text treatment as the
   underline tabs above, for one consistent "this is selected" language
   across the whole admin panel instead of two different ones. Same
   specificity as the rules above (two classes each) so this wins purely
   on source order, except the active color which needs !important to
   beat the !important above. */
.lf-tabs {
    border-bottom: none;
    gap: 8px;
    row-gap: 8px;
}

.lf-tabs .nav-item {
    margin-bottom: 0;
}

.lf-tabs .lf-tab {
    border: 1px solid var(--bs-border-color);
    border-radius: 8px;
    background: #fff;
    color: var(--bs-gray-600);
    padding: 8px 16px;
    font-size: .88rem;
    font-weight: 500;
    transition: background-color .12s ease, border-color .12s ease, color .12s ease;
}

.lf-tabs .lf-tab:hover {
    color: var(--bs-gray-800);
    background: var(--bs-gray-100);
    border-color: var(--bs-gray-300);
}

.lf-tabs .lf-tab.active {
    color: var(--bs-gray-900) !important;
    font-weight: 600;
    background: var(--bs-gray-200);
    border: 1px solid var(--bs-gray-300);
}

/* Aliases for the older .status-success/-info/-warning/-neutral/-danger/
   -purple badge class names - App\Support\Badge was updated to emit
   Metronic's own badge-light-* classes directly, but a few places
   (clients/show.blade.php's JS-driven quick-toggle data-on-class/
   data-off-class attributes, a couple of static badges) still reference
   the old names directly. Same bg/color formula Metronic's own
   badge-light-* classes use (confirmed via computed style: background =
   --bs-{color}-light, text = --bs-{color}). */
.status-success { background-color: var(--bs-success-light) !important; color: var(--bs-success) !important; }
.status-info     { background-color: var(--bs-primary-light) !important; color: var(--bs-primary) !important; }
.status-warning  { background-color: var(--bs-warning-light) !important; color: var(--bs-warning) !important; }
.status-neutral  { background-color: var(--bs-secondary-light) !important; color: var(--bs-secondary-color) !important; }
.status-danger   { background-color: var(--bs-danger-light) !important; color: var(--bs-danger) !important; }
.status-purple   { background-color: var(--bs-info-light) !important; color: var(--bs-info) !important; }

/* ---- Components ported from the retired public/css/admin.css ----
   These were deliberately left un-converted during both Bootstrap passes
   (self-contained, no Bootstrap-class collisions, so "leave it be" was the
   right call each time) - but layouts/admin.blade.php no longer links
   admin.css at all under Metronic, so anything still depending on it needs
   a real home. Faithful ports, admin.css's own --var() names swapped for
   Metronic's equivalents. */

/* Always the last, header-less column in a table row (cards/index,
   wallet-cards/index) - right-aligned so the icons hug the table's right
   edge instead of sitting wherever the previous column's content happens
   to end. */
.icon-btn-row {
    display: flex;
    gap: 2px;
    align-items: center;
    justify-content: flex-end;
}

.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border: 1px solid var(--bs-border-color);
    border-radius: 8px;
    background: #fff;
    color: var(--bs-secondary-color);
    cursor: pointer;
    text-decoration: none;
    transition: background .15s ease, border-color .15s ease, color .15s ease;
}

.icon-btn:hover {
    background: var(--bs-gray-100);
    border-color: var(--bs-gray-300);
    color: var(--bs-gray-900);
    text-decoration: none;
}

.icon-btn-danger:hover {
    background: var(--bs-danger-light);
    color: var(--bs-danger);
}

.icon-btn:disabled {
    color: var(--bs-gray-300);
    cursor: not-allowed;
}

.icon-btn:disabled:hover {
    background: #fff;
    border-color: var(--bs-border-color);
}

/* Separates a destructive icon-btn (delete) from the neutral actions next
   to it (edit/view) in a dense action row, e.g. the physical cards table -
   the goal is a deliberate gap before the one click that can't be undone,
   not just another same-spaced icon in the row. */
.icon-btn-divider {
    width: 1px;
    height: 18px;
    background: var(--bs-border-color);
    margin: 0 6px;
}

/* Ghost/tertiary button - a neutral bordered white button for back/
   navigate/utility actions, sitting a step below .btn-outline-primary in
   the action hierarchy (solid primary > outline primary > ghost neutral).
   Metronic ships no matching variant: its own outline-* classes are all
   brand-colored, and plain .btn-secondary is a filled near-white chip, not
   a bordered neutral button - !important needed for the same reason as the
   --bs-* overrides above (Metronic's own .btn:not(.btn-outline)... rule
   forces border:0 at higher specificity via eight :not() clauses). */
.btn-ghost {
    color: var(--bs-gray-700) !important;
    background-color: #fff !important;
    border: 1px solid var(--bs-border-color) !important;
}

.btn-ghost:hover,
.btn-ghost:focus:not(.btn-active),
.btn-ghost:active:not(.btn-active) {
    color: var(--bs-gray-900) !important;
    background-color: var(--bs-gray-100) !important;
    border-color: var(--bs-gray-300) !important;
}

.btn-ghost i,
.btn-ghost .svg-icon {
    color: inherit;
}

/* Visszajelzések (feedback) admin page - each item is a native <details>,
   collapsed by default, so a list of even a handful of entries stays
   scannable (status/rating/location/date + a one-line message preview)
   instead of always showing every item's full message, contact info, and
   inline edit form expanded. */
.feedback-card > summary {
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 20px;
}

.feedback-card > summary::-webkit-details-marker {
    display: none;
}

.feedback-card.is-new {
    border-left: 3px solid var(--bs-primary);
}

.feedback-summary-main {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    flex-shrink: 0;
}

.feedback-summary-preview {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: .85rem;
}

.feedback-summary-chevron {
    flex-shrink: 0;
    width: 8px;
    height: 8px;
    border-right: 2px solid var(--bs-gray-500);
    border-bottom: 2px solid var(--bs-gray-500);
    transform: rotate(45deg);
    transition: transform .15s ease;
}

.feedback-card[open] .feedback-summary-chevron {
    transform: rotate(-135deg);
}

.feedback-reply-sent {
    background: var(--bs-primary-light);
    border: 1px solid var(--bs-primary-border-subtle);
    border-radius: 8px;
    padding: 10px 14px;
    font-size: .85rem;
    color: var(--bs-primary-text-emphasis);
}

.bulk-actions-bar {
    display: none;
    align-items: center;
    gap: 14px;
    padding: 10px 16px;
    margin-bottom: 12px;
    background: var(--bs-primary-light);
    border: 1px solid var(--bs-primary-border-subtle);
    border-radius: 8px;
    font-size: .85rem;
    color: var(--bs-primary-text-emphasis);
}

.bulk-actions-bar.is-visible {
    display: flex;
}

.field-hint,
.field-error {
    font-size: .78rem;
    margin-top: 4px;
    line-height: 1.4;
}

.field-hint {
    color: var(--bs-secondary-color);
}

.field-error {
    color: var(--bs-danger);
}

.nowrap {
    white-space: nowrap;
}

/* Physical-card / location "link block" pattern - a labeled readonly link
   input plus one or more action buttons. */
.link-block label {
    display: block;
    margin-bottom: 10px;
}

.link-block + .link-block {
    margin-top: 32px;
    padding-top: 28px;
    border-top: 1px solid var(--bs-border-color);
}

.link-copy-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.link-copy-row input {
    flex: 1 1 160px;
    min-width: 0;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .82rem;
}

.link-copy-row .btn {
    flex-shrink: 0;
}

.qr-preview {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px;
    margin-top: 18px;
}

.qr-preview img {
    border: 1px solid var(--bs-border-color);
    border-radius: 6px;
    background: #fff;
}

/* Side-by-side QR image + NFC/QR link fields, used on the client page's
   Fizikai kártyák tab. */
.card-link-layout {
    display: flex;
    gap: 24px;
    align-items: flex-start;
}

.card-link-qr {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
}

.card-link-qr img {
    border: 1px solid var(--bs-border-color);
    border-radius: 8px;
    background: #fff;
    padding: 6px;
}

.card-link-qr .btn {
    width: 100%;
}

.card-link-fields {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

@media (max-width: 700px) {
    .card-link-layout {
        flex-direction: column;
        align-items: stretch;
    }

    .card-link-qr {
        align-items: flex-start;
    }

    .card-link-qr .btn {
        width: auto;
    }
}

/* Custom pagination view (resources/views/vendor/pagination/admin.blade.php)
   - Laravel's default pagination views assume Tailwind, this app has never
   used that, so a hand-rolled view is registered globally instead. */
.pagination {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px;
    list-style: none;
    margin: 0;
    padding: 0;
}

.pagination a,
.pagination span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 32px;
    height: 32px;
    padding: 0 8px;
    border-radius: 6px;
    font-size: .85rem;
}

.pagination a {
    border: 1px solid var(--bs-border-color);
    color: var(--bs-gray-900);
}

.pagination a:hover {
    background: var(--bs-body-bg);
    text-decoration: none;
}

.pagination-current {
    background: var(--bs-primary);
    color: #fff;
    font-weight: 600;
}

.pagination-dots {
    color: var(--bs-secondary-color);
}

.pagination-disabled {
    color: var(--bs-secondary-color);
    opacity: .5;
}

.pagination-summary {
    margin: 10px 0 0;
    font-size: .82rem;
    color: var(--bs-secondary-color);
}

/* Shared destructive-action confirmation dialog (admin/partials/confirm-modal.blade.php)
   - replaces native confirm() everywhere in the admin panel. Centered via
   the browser's own showModal() behavior, same recipe as .edit-modal
   above. Red/danger is the default variant (icon + confirm button both
   pick up --bs-danger); .confirm-modal-icon-warning is the softer variant
   for a confirm that isn't a delete (e.g. cancelling a campaign). */
.confirm-modal {
    width: min(420px, 92vw);
    padding: 0;
    border: none;
    border-radius: 12px;
    box-shadow: 0 20px 50px -12px rgba(15, 23, 42, 0.35);
}

.confirm-modal::backdrop {
    background: rgba(15, 23, 42, 0.5);
}

.confirm-modal-body {
    padding: 28px 24px 24px;
    text-align: center;
}

.confirm-modal-icon {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 16px;
    background: var(--bs-danger-light);
    color: var(--bs-danger);
}

.confirm-modal-icon-warning {
    background: var(--bs-warning-light);
    color: var(--bs-warning);
}

.confirm-modal-title {
    font-size: 1.1rem;
    font-weight: 700;
    color: var(--bs-gray-900);
    margin-bottom: 8px;
}

.confirm-modal-message {
    font-size: .92rem;
    color: var(--bs-secondary-color);
    margin-bottom: 20px;
}

.confirm-modal-actions {
    display: flex;
    justify-content: center;
    gap: 10px;
}

.confirm-modal-actions .btn {
    min-width: 110px;
}

/* Rows-per-page select (admin/partials/per-page-select.blade.php). */
.per-page-form .form-select {
    padding-top: .25rem;
    padding-bottom: .25rem;
}

/* Tab counters (clients/show.blade.php's nav-tabs) - a small neutral gray
   pill, staying gray (just a shade darker) on the active tab too, per the
   2026-08-13 neutral-tones redesign - no color shift, so the badge never
   competes with the underline for "this is selected" duty. */
.tab-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    font-size: .68rem;
    font-weight: 700;
    background: var(--bs-gray-200);
    color: var(--bs-gray-700);
    margin-left: 4px;
}

.nav-tabs .nav-link.active .tab-count {
    background: var(--bs-gray-300);
    color: var(--bs-gray-800);
}

/* Label-over-value stat/definition grid - replaces the old "<strong>Label:</strong>
   value" inline pattern (client show page's account/email/feedback tabs) with
   something easier to scan at a glance. */
.info-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 16px 24px;
}

.info-item-wide {
    grid-column: 1 / -1;
}

.info-label {
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--bs-secondary-color);
    margin-bottom: 2px;
}

.info-value {
    font-size: .95rem;
    color: var(--bs-gray-900);
    font-weight: 500;
}

/* Compact location card (client show page's Üzlethelyek tab) - each labeled
   sub-section (public link / stats / active features) gets a divider and a
   small caption instead of running everything together in one paragraph. */
.location-section {
    padding: 12px 0;
    border-top: 1px solid var(--bs-border-color);
}

.location-section:first-child {
    padding-top: 0;
    border-top: none;
}

.location-section-label {
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--bs-secondary-color);
    margin-bottom: 10px;
}

.location-card .badge {
    cursor: pointer;
    border: none;
}

/* Small view-only physical-card chips on the Üzlethelyek tab
   (clients/show.blade.php) - deliberately tiny/no-frills compared to the
   real cards table (admin/cards/index.blade.php), since this is a glance
   preview, not the editing surface. */
.mini-card-chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.mini-card-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    border: 1px solid var(--bs-border-color);
    border-radius: 8px;
    background: var(--bs-gray-100);
    text-decoration: none;
    font-size: .8rem;
    transition: background-color .12s ease, border-color .12s ease;
}

.mini-card-chip:hover {
    background: var(--bs-gray-200);
    border-color: var(--bs-gray-300);
}

.mini-card-chip-code {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-weight: 600;
    color: var(--bs-gray-800);
}

.mini-card-chip-status.badge {
    font-size: .65rem;
}

/* Per-store grouping of a client's own physical-card list
   (clients/show.blade.php's Fizikai kártyák tab, .pcard-row cards) - a
   plain div wrapper per location (not a table, so this can use a real
   <details> for "+N további" per store, unlike the main cards index
   table where <details> can't wrap table rows). */
.pcard-group + .pcard-group {
    margin-top: 20px;
    padding-top: 20px;
    border-top: 2px solid var(--bs-gray-200);
}

.pcard-group-header {
    margin-bottom: 10px;
}

.pcard-group-title {
    font-weight: 700;
    color: var(--bs-gray-900);
    font-size: .85rem;
}

.pcard-group-count {
    margin-left: 8px;
    font-size: .75rem;
    color: var(--bs-gray-600);
}

.pcard-group-more {
    display: inline-block;
    margin-top: 10px;
    font-size: .82rem;
    color: var(--bs-gray-700);
    cursor: pointer;
}

.pcard-group-more:hover {
    color: var(--bs-gray-900);
}

.mini-stat-row {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
}

.mini-stat {
    flex: 1 1 90px;
    text-align: center;
    padding: 10px 8px;
    border-radius: 8px;
    background: var(--bs-gray-100);
}

.mini-stat-value {
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--bs-gray-900);
    line-height: 1.2;
}

.mini-stat-label {
    font-size: .72rem;
    color: var(--bs-secondary-color);
    margin-top: 2px;
}

/* Fetch-loaded "Szerkesztés" dialog (client show + card mockups index) -
   used for both the client-edit and location-edit forms (and the mockup-edit
   form) so it needs to live globally rather than duplicated per page; it
   previously was duplicated identically in both files. Centered via the
   browser's own showModal() behavior, same recipe as .confirm-modal above. */
.edit-modal {
    /* Widened for the location edit/create form's tabs + live-preview
       sidebar, which felt cramped at the original 680px - still works fine
       for the simpler client-edit form that shares this same dialog, just
       with a bit more side margin. */
    width: min(900px, 94vw);
    max-height: 88vh;
    padding: 0;
    border: none;
    border-radius: 12px;
    box-shadow: 0 20px 50px -12px rgba(15, 23, 42, 0.35);
}

.edit-modal::backdrop {
    background: rgba(15, 23, 42, 0.5);
}

.edit-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 20px;
    border-bottom: 1px solid var(--bs-border-color);
    font-weight: 600;
    position: sticky;
    top: 0;
    background: #fff;
}

.edit-modal-close {
    background: none;
    border: none;
    font-size: 1.4rem;
    line-height: 1;
    color: var(--bs-secondary-color);
    cursor: pointer;
    padding: 4px 8px;
}

.edit-modal-close:hover {
    color: var(--bs-gray-900);
}

.edit-modal-body {
    padding: 20px;
    overflow-y: auto;
    max-height: calc(88vh - 57px);
}

.edit-modal-body .card {
    box-shadow: none;
}

/* Statisztika page (admin/stats/index.blade.php) - each client gets its own
   separate <table>, so with the browser's default table-layout:auto every
   table sizes its own columns independently based on that table's own
   content (a long location address vs. a short one), and the ÖSSZES/MA/NFC/
   etc. columns end up misaligned between different clients' cards. Fixed
   layout + a shared colgroup (same percentages on every table) forces every
   client's table to use identical column widths regardless of content
   length, so they line up vertically when stacked. */
.stats-table {
    table-layout: fixed;
}

.stats-table td:first-child {
    word-break: break-word;
}

/* Table headers used to have the same visual weight as their data rows,
   easy to lose track of which row is the header when scanning a dense
   table. Muted uppercase label + light background, consistently across
   every admin data table. */
.table > thead > tr > th {
    background: var(--bs-gray-100);
    color: var(--bs-secondary-color);
    font-size: .78rem;
    /* style.bundle.css's `.table:not(.table-bordered) th` rule is more
       specific than this selector and sets font-weight/text-transform to
       "inherit" - !important needed to actually win, same pattern as the
       --bs-* overrides at the top of this file. */
    font-weight: 700 !important;
    text-transform: uppercase !important;
    letter-spacing: .03em;
    border-bottom-width: 1px;
}

/* Location edit/create form (admin/locations/_form.blade.php) - tabbed
   redesign replacing what used to be one long single-column form. JS hooks
   live in layouts/admin.blade.php (data-lf-* attributes), styling here. */

/* Theme picker (_theme-picker.blade.php): category filter pills above a
   CSS-grid of theme cards, replacing the old per-group flex-wrap rows. */
.theme-category-pills {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.theme-category-pill {
    border: 1px solid var(--bs-border-color);
    background: #fff;
    color: var(--bs-secondary-color);
    border-radius: 999px;
    padding: 4px 14px;
    font-size: .82rem;
    font-weight: 500;
}

.theme-category-pill:hover {
    background: var(--bs-gray-100);
}

.theme-category-pill.active {
    background: var(--bs-primary);
    border-color: var(--bs-primary);
    color: #fff;
}

.theme-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: 14px;
}

/* .picker-card hardcodes width:140px for its original flex-wrap usage
   (theme/mode pickers elsewhere) - inside the grid here, the grid cell
   itself controls each card's width instead. */
.theme-grid .picker-card {
    width: auto;
}

.theme-selected-badge {
    font-size: .82rem;
}

/* Sticky Mentés/Mégse footer. position:sticky positions relative to the
   nearest scrolling ancestor, which is .edit-modal-body (overflow-y:auto)
   when this form is fetched into the client page's edit modal, or the
   viewport itself on the standalone full-page edit/create view - works
   correctly in both without needing to know which one it's in. */
.lf-sticky-footer {
    position: sticky;
    bottom: 0;
    z-index: 5;
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 20px;
    padding: 16px 0 4px;
    background: #fff;
    border-top: 1px solid var(--bs-border-color);
}

/* Small live preview sidebar (optional per the redesign ask) - a rough
   mock of the public landing page, not a real render of it, so it's
   updated instantly client-side without a server round-trip. */
.lf-preview-card {
    overflow: hidden;
    position: sticky;
    top: 12px;
}

.lf-preview-photo {
    height: 120px;
    background-size: cover;
    background-position: center;
    background-color: var(--bs-gray-200);
}

.lf-preview-eyebrow {
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--bs-secondary-color);
    margin-bottom: 6px;
}

.lf-preview-title {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--bs-gray-900);
    margin-bottom: 6px;
    word-wrap: break-word;
}

.lf-preview-description {
    font-size: .85rem;
    color: var(--bs-secondary-color);
    margin-bottom: 16px;
    word-wrap: break-word;
}

.lf-preview-google-btn {
    display: block;
    text-align: center;
    padding: 10px;
    border-radius: 8px;
    background: var(--bs-primary);
    color: #fff;
    font-weight: 600;
    font-size: .88rem;
}

.lf-preview-feature {
    background: var(--bs-gray-100);
    color: var(--bs-secondary-color);
    font-weight: 500;
    transition: background .15s ease, color .15s ease;
}

.lf-preview-feature.is-on {
    background: var(--bs-success-light);
    color: var(--bs-success);
}

/* Two-column field pairs (locations/_form.blade.php: name+address,
   notification_email+privacy_policy_url) - plain Bootstrap .row/.col-md-6
   lets each column's label wrap independently, so a longer label (e.g.
   "Publikus link azonosító (slug) *" wrapping to two lines) pushes that
   column's input down while the other column's input stays where its own
   one-line label left it, misaligning the two inputs. CSS subgrid fixes
   this at the source: both cells share the parent's row-track sizing, so
   the label row is always as tall as the tallest label across BOTH
   columns, and the input/helper rows line up horizontally no matter which
   label wrapped. */
.field-pair-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto auto;
    column-gap: 1.5rem;
    row-gap: .75rem;
}

/* Google Review link (locations/_form.blade.php's Alapadatok tab) - the
   single most important field on the whole form, deliberately not styled
   as just another peer input. A tinted, bordered container + a bold icon
   label makes it the visual anchor of the tab instead of competing
   equally with the slug/address fields around it. */
.google-review-field {
    background: var(--bs-primary-light);
    border: 1px solid var(--bs-primary-border-subtle);
    border-radius: 10px;
    padding: 16px;
}

.google-review-field .form-label {
    font-weight: 700;
    color: var(--bs-primary-text-emphasis);
}

.google-review-field .form-label i {
    color: var(--bs-primary);
}

.google-review-field .form-text {
    color: var(--bs-primary-text-emphasis);
    opacity: .85;
}

/* .google-review-highlight (a blue-tinted, then gray-tinted callout box)
   removed 2026-08-13 - the Google review link now renders with the exact
   same plain .location-section/.location-section-label/.readonly-link-row
   structure as "Publikus link" right below it, no special box at all. */

/* "Hogyan működik a rendszer?" explainer (client page, bottom of the
   Üzlethelyek tab, clients/show.blade.php) - a static 4-step walkthrough,
   same neutral-gray family as everything else touched in this pass. */
.how-it-works {
    background: var(--bs-gray-100);
    border-radius: 12px;
    padding: 20px 24px;
    margin-top: 20px;
}

.how-it-works-header {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 18px;
}

.how-it-works-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--bs-gray-900);
    color: #fff;
    flex-shrink: 0;
}

.how-it-works-icon i {
    font-size: .9rem;
}

.how-it-works-title {
    font-size: .95rem;
    font-weight: 700;
    color: var(--bs-gray-900);
    margin: 0;
}

.how-it-works-steps {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 20px;
}

.how-it-works-step i {
    display: block;
    color: var(--bs-gray-700);
    margin-bottom: 8px;
}

.how-it-works-step-title {
    font-size: .85rem;
    font-weight: 700;
    color: var(--bs-gray-900);
    margin-bottom: 4px;
}

.how-it-works-step-desc {
    font-size: .78rem;
    color: var(--bs-gray-600);
    line-height: 1.4;
}

@media (max-width: 767px) {
    .how-it-works-steps {
        grid-template-columns: 1fr;
    }
}

.field-pair-cell {
    display: grid;
    grid-template-rows: subgrid;
    grid-row: 1 / span 3;
}

.field-pair-cell > .form-label {
    grid-row: 1;
    align-self: start;
    margin-bottom: 0;
}

.field-pair-cell > input,
.field-pair-cell > textarea,
.field-pair-cell > select {
    grid-row: 2;
    align-self: start;
}

.field-pair-cell > .form-text {
    grid-row: 3;
    align-self: start;
    margin-top: 0;
}

@media (max-width: 700px) {
    .field-pair-row {
        display: block;
    }

    .field-pair-cell {
        display: block;
    }

    .field-pair-cell + .field-pair-cell {
        margin-top: 1rem;
    }
}

/* Physical cards tab (clients/show.blade.php) - compact grid row per card
   (QR thumb / info+badges / NFC+QR link boxes / actions) replacing the old
   oversized per-card .card block with a 120px QR image and full .form-control
   -styled readonly inputs. */
.pcard-row {
    display: grid;
    grid-template-columns: 56px minmax(140px, 190px) minmax(220px, 1fr) auto;
    align-items: center;
    gap: 16px;
    padding: 12px 0;
    border-top: 1px solid var(--bs-border-color);
}

.pcard-row:first-child {
    border-top: none;
    padding-top: 4px;
}

.pcard-row[hidden] {
    display: none;
}

.pcard-qr img {
    display: block;
    border: 1px solid var(--bs-border-color);
    border-radius: 6px;
    background: #fff;
}

.pcard-code {
    font-weight: 700;
    color: var(--bs-gray-900);
    margin-bottom: 4px;
}

.pcard-links {
    min-width: 0;
}

.pcard-link-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.pcard-link-row + .pcard-link-row {
    margin-top: 6px;
}

.pcard-link-tag {
    flex: 0 0 30px;
    font-size: .68rem;
    font-weight: 700;
    color: var(--bs-secondary-color);
    text-transform: uppercase;
}

.pcard-link-value {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    background: var(--bs-gray-100);
    border: 1px solid var(--bs-border-color);
    border-radius: 6px;
    padding: 4px 8px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .78rem;
    color: var(--bs-gray-700);
}

.pcard-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    justify-content: flex-end;
}

.icon-copy-btn.is-copied {
    color: var(--bs-success);
}

@media (max-width: 700px) {
    .pcard-row {
        grid-template-columns: 56px 1fr;
        grid-template-areas:
            "qr info"
            "links links"
            "actions actions";
        row-gap: 10px;
    }

    .pcard-qr {
        grid-area: qr;
    }

    .pcard-info {
        grid-area: info;
    }

    .pcard-links {
        grid-area: links;
    }

    .pcard-actions {
        grid-area: actions;
        justify-content: flex-start;
    }
}

/* Metronic's .app-content default padding-top (30px desktop / 20px mobile)
   sits between the toolbar (page title/actions) and the page's own first
   content element - on pages whose content starts right with a tab bar
   (clients/show.blade.php, the location edit form) this reads as an
   oversized gap above the tabs. Tightened app-wide rather than patched per
   page, since "reduce unnecessary empty space" has been a running theme
   across this whole redesign, not just these two pages. !important needed
   since Metronic sets this inside its own @media block at equal
   specificity. */
@media (min-width: 992px) {
    .app-content {
        padding-top: 16px !important;
    }
}

@media (max-width: 991.98px) {
    .app-content {
        padding-top: 14px !important;
    }
}

/* Üzlethelyek tab's "Publikus link" field (clients/show.blade.php) - a
   flat, non-input-looking readonly box (unlike a bare <input readonly>,
   which still picks up the browser's default text-field chrome and reads
   as editable even without a value ever changing) plus the copy/open
   actions directly beside it. */
.readonly-link-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

/* `code.readonly-link-value`, not just `.readonly-link-value` - this is
   always applied to a <code> element, and Metronic's own base
   `code:not([class*=language-])` rule (style.bundle.css) is an
   element+:not() selector, MORE specific than a bare class alone, so a
   single-class selector here silently lost every property (background,
   border, color, padding, font-size, margin) to that base rule - the
   pink/magenta (--bs-code-color) text on this app's "Publikus link"/
   "Google Review link" boxes was that bug, not a deliberate design choice.
   Matching the element+class specificity, combined with loading after
   style.bundle.css, wins outright without needing !important anywhere. */
code.readonly-link-value {
    flex: 1 1 220px;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    background: var(--bs-gray-100);
    border: 1px solid var(--bs-border-color);
    border-radius: 8px;
    padding: 8px 12px;
    margin: 0;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .82rem;
    font-weight: 400;
    line-height: inherit;
    box-shadow: none;
    color: var(--bs-gray-700);
}

/* Aktív funkciók feature toggles - neutral gray by default (disabled),
   green with a check icon once enabled. Own class instead of reusing
   .status-success/.status-neutral directly so the enabled/disabled
   distinction reads consistently regardless of which status-* palette a
   future badge nearby happens to use. */
.feature-badge {
    background: var(--bs-gray-100);
    color: var(--bs-secondary-color);
}

.feature-badge.is-on {
    background: var(--bs-success-light);
    color: var(--bs-success);
}

/* #kt_app_header is fixed (body has data-kt-app-header-fixed="true"), so
   .app-wrapper always gets margin-top:var(--bs-app-header-height) to make
   room for it - reserving ~74px of blank space above the toolbar/heading
   on every single page. At desktop widths that header's own content
   (mobile menu toggle, logo) is d-lg-none - it renders completely empty,
   so most of that reserved band was dead space - shrunk (not zeroed:
   .app-sidebar-logo's own height is ALSO computed from this exact
   variable via calc(var(--bs-app-header-height) + 1px), so zeroing it
   collapsed the sidebar's ReviewTap brand logo down to 1px and clipped
   it - found the hard way). The sidebar logo gets its own fixed height
   below, decoupled from this variable, so the two concerns can be tuned
   independently. !important matches this file's established pattern for
   beating a same-specificity :root declaration in style.bundle.css. */
@media (min-width: 992px) {
    :root {
        --bs-app-header-height: 28px !important;
        --bs-app-header-height-actual: 28px !important;
    }

    .app-sidebar-logo {
        height: 64px !important;
    }
}

/* ==========================================================================
   Mobile/tablet responsive layer (< 992px, matches Metronic's own lg
   breakpoint everywhere else in this file) - additive only. Nothing in this
   section changes anything at >= 992px, so the existing desktop layout is
   untouched; every rule here is either inside this same max-width query or
   targets a mobile-only element that doesn't render on desktop at all.
   ========================================================================== */
@media (max-width: 991.98px) {

    /* Sidebar drawer - Metronic's own JS (scripts.bundle.js) toggles the
       `drawer-on` class correctly on click (confirmed: the hamburger
       button, .drawer-overlay backdrop, and body[data-kt-drawer="on"]
       scroll-lock all fire as expected), but never adds the base `.drawer`/
       `.drawer-start` CSS classes its own stylesheet expects alongside
       `drawer-on` for the actual slide-in positioning. Without those,
       style.bundle.css's blanket `[data-kt-drawer=true] { display: none; }`
       rule has nothing overriding it, so the sidebar never becomes visible
       at any point - the "hamburger does nothing" bug this section fixes.
       Reproducing the same positioning that combination was supposed to
       provide here, scoped to the sidebar's own ID so it's independent of
       whichever Metronic classes do or don't end up present. */
    #kt_app_sidebar {
        display: flex !important;
        position: fixed !important;
        top: 0;
        bottom: 0;
        z-index: 110;
        width: 250px !important;
        max-width: 82vw;
        /* Positioned via `left`, not `transform` - scripts.bundle.js runs
           its own Web Animations API animation on this element's
           `transform` the instant the drawer toggle is clicked (confirmed
           via element.getAnimations()), which no CSS rule can win against
           while it's active, not even an inline style set with
           setProperty(..., 'important') (verified directly - it's a
           genuine WAAPI-vs-CSS-cascade conflict, not a specificity bug on
           our end). `left` is a property that animation never touches, so
           controlling visibility through it sidesteps the fight entirely
           - the tradeoff is an instant show/hide instead of an animated
           slide, which is an acceptable trade for the drawer actually
           working at all. */
        left: -260px;
        transition: left 0.25s ease-in-out;
        box-shadow: 0 1px 9px 0 rgba(0, 0, 0, 0.08);
    }

    #kt_app_sidebar.drawer-on {
        left: 0 !important;
    }

    /* The sidebar pushes/reserves layout space at desktop widths
       (data-kt-app-sidebar-push-header/toolbar/footer="true") - at mobile
       widths it must go back to floating over the content instead (it's a
       fixed-position overlay drawer above), otherwise the page reserves a
       permanent empty gutter for a sidebar that's supposed to be hidden. */
    .app-wrapper,
    #kt_app_header {
        margin-left: 0 !important;
        padding-left: 0 !important;
    }

    /* Metronic's own header markup already has the hamburger toggle,
       ReviewTap wordmark, and a d-lg-none breadcrumb slot ready for
       mobile - just the drawer underneath it wasn't rendering. No header
       markup changes needed, only making sure it isn't clipped/squashed. */
    #kt_app_header {
        height: auto;
        min-height: 60px;
    }

    /* The toolbar's title row and its action buttons (Új..., Vissza,
       CSV export, etc.) share one flex row on desktop - at narrow widths
       that squeezed a multi-button toolbar down into overlapping/clipped
       text. Wrapping instead keeps every button fully readable and
       tappable, just on its own line if needed. */
    #kt_app_toolbar .d-flex.flex-stack {
        flex-wrap: wrap;
        row-gap: 10px;
    }

    #kt_app_toolbar [class*="toolbar-actions"],
    #kt_app_toolbar > .app-container > div:last-child {
        flex-wrap: wrap;
        row-gap: 8px;
    }

    .page-heading {
        font-size: 1.15rem !important;
    }

    /* ---- Containers/cards: always fit the viewport, never force a
       horizontal scrollbar on the page itself. ---- */
    .app-container,
    .card,
    .card-body {
        max-width: 100%;
    }

    .app-container {
        padding-left: 12px;
        padding-right: 12px;
    }

    .card-body {
        padding: 16px;
    }

    /* ---- Multi-column layouts stack to one column. Metronic/Bootstrap's
       own .row > .col-* grid already does this by default (they're
       already responsive), this only catches the handful of places in
       this app that used a bare flex row instead of the grid. ---- */
    .row {
        --bs-gutter-x: 12px;
    }

    /* ---- Forms: full-width, touch-sized controls. ---- */
    .form-control,
    .form-select,
    .btn {
        width: 100%;
        min-height: 44px;
    }

    /* Buttons that are meant to sit inline next to each other (icon
       buttons, a Mégse/Mentés pair, table row actions) shouldn't be
       forced full-width just because they're a .btn - only ones that
       were already block-level/full-width-intended on desktop should
       stay that way here. */
    .icon-btn,
    .icon-btn-row .btn,
    .d-flex.gap-2 > .btn,
    .d-flex.flex-wrap.gap-2 > .btn,
    .toggle-switch,
    .form-check.form-switch .btn {
        width: auto;
        min-height: 40px;
    }

    .icon-btn {
        min-height: 36px;
        min-width: 36px;
    }

    /* ---- Tabs (client show page etc.) - a row of 6-7 tab buttons
       doesn't fit a phone width; scrolling horizontally within its own
       strip (native touch-scroll, momentum included) keeps every tab
       reachable without wrapping into a multi-row jumble or overflowing
       the page itself. ---- */
    .nav-tabs {
        flex-wrap: nowrap !important;
        overflow-x: auto !important;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        padding-bottom: 2px;
    }

    .nav-tabs::-webkit-scrollbar {
        display: none;
    }

    .nav-tabs .nav-item {
        flex: 0 0 auto;
    }

    .nav-tabs .nav-link {
        white-space: nowrap;
    }

    /* ---- Long values (URLs, tokens, serials, emails) wrap or break
       instead of pushing their container wider than the viewport. ---- */
    .link-block,
    .link-copy-row,
    code,
    .field-hint,
    .text-break-mobile {
        overflow-wrap: break-word;
        word-break: break-word;
    }

    table {
        table-layout: auto;
    }

    /* ---- Data tables: keep the existing desktop table completely
       intact (same markup, same columns) but scoped to scroll only
       within its own strip - .table-responsive already does this
       project-wide, this is the safety net for the rare table missing
       that wrapper so it can never push the whole page wider than the
       viewport. ---- */
    .table-responsive {
        -webkit-overflow-scrolling: touch;
    }

    table:not(.table-responsive table) {
        max-width: 100%;
    }

    /* ---- Modals/dialogs (edit-modal, confirm-modal) - fixed pixel
       widths from the desktop design (min(900px, 94vw) etc.) already
       clamp to the viewport via the vw half of that min(), this just
       tightens the side margin so close/action buttons stay reachable
       on a narrow phone. ---- */
    .edit-modal {
        width: 96vw;
        margin: 0 2vw;
        max-height: 92vh;
    }

    /* Feedback list (clients/feedback.blade.php) - .feedback-summary-main
       had flex-shrink:0 (correct on desktop, where its badge/stars/
       location/date content comfortably fits one line) with no width
       constraint of its own, so on a narrow viewport it refused to shrink
       below its full unwrapped content width and pushed the whole summary
       row (and so the whole page) wider than the screen - the actual
       bug behind the widened-viewport false negatives this QA pass
       started catching. Allowing it to shrink lets its own already-present
       flex-wrap:wrap actually take effect within the real viewport width;
       the message preview moves to its own full-width line below instead
       of a truncated sliver squeezed in next to the rest. */
    .feedback-card > summary {
        flex-wrap: wrap;
    }

    .feedback-summary-main {
        flex-shrink: 1;
        min-width: 0;
        max-width: 100%;
    }

    .feedback-summary-preview {
        flex-basis: 100%;
        white-space: normal;
    }

    /* GET-search bars (Keresés) at the top of most admin index pages -
       an input squeezed down to ~150px next to a button is technically
       usable but not the "clean, touch-friendly" bar the mobile layer is
       for; stacking it gives the input its full width to actually read
       what's typed, button full-width below it. */
    .search-form {
        flex-direction: column;
    }
}

/* Phone-width-specific: table -> stacked record cards. Narrower than the
   991.98px breakpoint above on purpose - a tablet portrait width (768-
   991px) still comfortably fits most of these tables with the internal
   .table-responsive scroll from the block above; a real phone doesn't, and
   an unlabeled horizontal scroll strip is a much worse reading experience
   there than a labeled stacked card per row.

   Zero-JS, CSS-only technique: hide <thead> (labels move onto each <td>
   instead via ::before + the td's own data-label attribute), then turn
   every table/tbody/tr/td into a block so each <tr> becomes its own
   bordered card and each <td> becomes a labeled row inside it. Opt-in via
   the .table-stack class (added alongside the existing table classes, not
   replacing them) rather than a blanket `table` selector, so this only
   touches tables that have been given a data-label per <td> - the
   markup this needs. Currently applied to the clients index; the same
   class + data-label attributes extend the same treatment to any other
   table. */
@media (max-width: 767.98px) {
    .table-stack thead {
        display: none;
    }

    .table-stack,
    .table-stack tbody,
    .table-stack tr,
    .table-stack td {
        display: block;
        width: 100%;
    }

    .table-stack tr {
        margin-bottom: 12px;
        border: 1px solid var(--bs-border-color);
        border-radius: 10px;
        padding: 4px 14px;
    }

    .table-stack tr:last-child {
        margin-bottom: 0;
    }

    .table-stack td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        padding: 10px 0;
        border-bottom: 1px solid var(--bs-border-color);
        text-align: right;
        white-space: normal;
    }

    .table-stack td:last-child {
        border-bottom: none;
    }

    .table-stack td[data-label=""] {
        justify-content: flex-end;
    }

    .table-stack td::before {
        content: attr(data-label);
        font-weight: 600;
        font-size: 0.8rem;
        color: var(--bs-gray-700);
        text-align: left;
        flex-shrink: 0;
    }

    .table-stack td[data-label=""]::before {
        content: none;
    }

    .table-stack .icon-btn-row {
        justify-content: flex-end;
        width: 100%;
    }
}

/* Wallet card settings page (admin/wallet-cards/form.blade.php) - a
   spread row for a toggle switch, used instead of the shared
   toggle-switch partial's inline label+switch layout wherever the switch
   needs to sit at the row's right edge with its title/hint on the left. */
.wallet-setting-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
}

.wallet-setting-row-text {
    flex: 1 1 auto;
    min-width: 0;
}

.wallet-setting-row-title {
    font-weight: 600;
    font-size: .925rem;
    color: var(--bs-gray-900);
}

.wallet-setting-row-hint {
    font-size: .8rem;
    color: var(--bs-secondary-color);
    margin-top: 2px;
    line-height: 1.4;
}

.wallet-setting-row .form-check.form-switch {
    flex: 0 0 auto;
    margin: 0;
    padding-left: 3rem;
}

/* Color swatch + hex text pair, replacing a bare <input type="color">
   with something closer to a design-tool color picker. The native color
   input still IS the field that submits background_color - only its
   chrome is stripped down to a plain square via the vendor swatch
   pseudo-elements below, the hex text input alongside it is a synced
   read/write mirror (see the page's own <script>), and the pencil badge
   is a purely decorative affordance layered on top (pointer-events:none
   so clicks still reach the color input underneath). */
.wallet-color-group {
    display: flex;
    align-items: center;
    gap: 12px;
    max-width: 280px;
}

.wallet-color-swatch-wrap {
    position: relative;
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
}

.wallet-color-swatch {
    width: 44px;
    height: 44px;
    padding: 0;
    border: 1px solid var(--bs-border-color);
    border-radius: 8px;
    cursor: pointer;
    background: none;
}

.wallet-color-swatch::-webkit-color-swatch-wrapper {
    padding: 0;
    border-radius: 7px;
}

.wallet-color-swatch::-webkit-color-swatch {
    border: none;
    border-radius: 7px;
}

.wallet-color-swatch::-moz-color-swatch {
    border: none;
    border-radius: 7px;
}

.wallet-color-swatch:disabled {
    cursor: not-allowed;
    opacity: .5;
}

.wallet-color-swatch-pencil {
    position: absolute;
    right: -5px;
    bottom: -5px;
    width: 18px;
    height: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #fff;
    border: 1px solid var(--bs-border-color);
    border-radius: 50%;
    font-size: 9px;
    color: var(--bs-secondary-color);
    pointer-events: none;
}

.wallet-color-hex {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    text-transform: uppercase;
}

/* Drag-and-drop logo upload zone - the real <input type="file"> sits
   absolutely positioned over the whole zone at opacity:0, so native
   click-to-browse AND native drag/drop both keep working with zero JS;
   the page's own <script> only adds the dragover/dragleave highlight
   class, which is cosmetic. */
.wallet-dropzone {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    text-align: center;
    padding: 28px 16px;
    border: 1.5px dashed var(--bs-border-color);
    border-radius: 10px;
    background: var(--bs-gray-100);
    transition: border-color .12s ease, background-color .12s ease;
}

.wallet-dropzone.is-dragover {
    border-color: var(--bs-primary);
    background: var(--bs-primary-light);
}

.wallet-dropzone-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

.wallet-dropzone-icon {
    font-size: 1.6rem;
    color: var(--bs-secondary-color);
}

/* Live loyalty-card mockup on the right column - a scaled-down stand-in
   for the real Google Wallet pass (see GoogleWalletProvider/
   StampProgressBanner for the real artifact), kept in sync with the form
   fields by the page's own <script> so an admin sees the effect of a
   color/stamp-count/reward change before saving. Split into two zones
   (.wallet-preview-native/.wallet-preview-hero below) matching a real
   installed card's actual structure - confirmed against real device
   photos that everything down through the serial box is Google's fixed
   native layout (solid hexBackgroundColor only, no image support), and
   only the area below it is the real freeform heroImage canvas a
   background photo can appear in. */
.wallet-preview-card {
    border-radius: 16px;
    overflow: hidden;
    color: #fff;
}

.wallet-preview-business {
    font-size: 1rem;
    font-weight: 700;
}

.wallet-preview-headline {
    font-size: 1.4rem;
    font-weight: 800;
    line-height: 1.25;
}

.wallet-preview-divider {
    height: 1px;
    background: rgba(255, 255, 255, .3);
    margin: 14px 0;
}

.wallet-preview-stamps {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px;
}

.wallet-preview-stamp {
    width: 40px;
    height: 40px;
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(255, 255, 255, .18);
    border: 1.5px solid rgba(255, 255, 255, .55);
    font-weight: 700;
    font-size: .85rem;
}

/* Custom stamp icon (WalletCard::stamp_icon_path) inside a preview slot,
   in place of the plain number - the design-preview here always shows
   every slot at full strength (it's not simulating real customer
   progress, see StampProgressBanner for the collected/uncollected
   version that actually is). */
.wallet-preview-stamp img {
    width: 62%;
    height: 62%;
    object-fit: contain;
}

/* Összegzés (summary) list - simple label/value rows, thin dividers
   between them only (not around the whole list, the card's own border
   already frames it). */
.wallet-summary-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 0;
}

.wallet-summary-row + .wallet-summary-row {
    border-top: 1px solid var(--bs-border-color);
}

.wallet-summary-label {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--bs-secondary-color);
    font-size: .875rem;
}

.wallet-summary-value {
    font-weight: 600;
    font-size: .875rem;
    color: var(--bs-gray-900);
    text-align: right;
}

.wallet-summary-value.text-success {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* Phase 1 Wallet-card redesign additions below - generic small button-
   group "radio styled as buttons" pattern, reused for the stamp-count
   presets, background type/position/fit, and stamp alignment. A real
   visually-hidden radio input per button (not a JS-only toggle) so it
   degrades to plain functional radios with no JS, matching this project's
   minimal-JS convention. */
.wallet-radio-group {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.wallet-radio-btn {
    position: relative;
}

.wallet-radio-btn input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
}

.wallet-radio-btn label {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    border: 1.5px solid var(--bs-border-color);
    border-radius: 8px;
    font-size: .825rem;
    font-weight: 600;
    color: var(--bs-gray-700);
    cursor: pointer;
    transition: border-color .12s ease, background-color .12s ease, color .12s ease;
    margin: 0;
}

.wallet-radio-btn input:checked ~ label {
    border-color: var(--bs-primary);
    background: var(--bs-primary-light);
    color: var(--bs-primary);
}

.wallet-radio-btn .wallet-legacy-tag {
    display: inline-block;
    font-size: .65rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--bs-warning);
}

/* Small inline note marking a control that only affects the admin preview
   / pre-install web page, never the real card once it's installed on a
   phone - Google's own Wallet template fixes the header (logo size and
   position) regardless of what we send. Used sparingly - only where the
   gap between preview and reality is real, per
   documentation/Google Wallet Loyalty Card Redesign Prompt – Phase 1.md
   section 10's "no fake mockup" requirement. */
.wallet-preview-only-note {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    font-size: .78rem;
    color: var(--bs-secondary-color);
    background: var(--bs-gray-100);
    border-radius: 8px;
    padding: 8px 10px;
    margin-top: 10px;
}

.wallet-preview-only-note .ki-outline {
    color: var(--bs-warning);
    font-size: 1rem;
    margin-top: 1px;
}

/* Opacity/percentage sliders (background overlay, per-stamp-state opacity,
   admin-only preview progress) - native <input type="range"> with a live
   numeric readout, no slider library. */
.wallet-slider-row {
    display: flex;
    align-items: center;
    gap: 12px;
}

.wallet-slider-row input[type="range"] {
    flex: 1 1 auto;
}

.wallet-slider-value {
    flex: 0 0 auto;
    min-width: 42px;
    text-align: right;
    font-weight: 700;
    font-size: .875rem;
    color: var(--bs-gray-900);
    font-variant-numeric: tabular-nums;
}

/* Background-image dropzone thumbnail, same "current upload + remove"
   pairing as the existing logo/stamp-icon dropzones above. */
.wallet-bg-thumb {
    width: 100%;
    max-width: 220px;
    height: 90px;
    object-fit: cover;
    border-radius: 8px;
    border: 1px solid var(--bs-border-color);
}

/* Stamp state sub-panel (Completed / Incomplete) inside the Stamp design
   card - a light nested card so the two states read as clearly separate
   groups of controls without a full second .card's heavier border. */
.wallet-stamp-state {
    border: 1px solid var(--bs-border-color);
    border-radius: 10px;
    padding: 16px;
}

.wallet-stamp-state-title {
    font-weight: 700;
    font-size: .85rem;
    color: var(--bs-gray-900);
    margin-bottom: 12px;
    display: flex;
    align-items: center;
    gap: 8px;
}

.wallet-stamp-state-title .badge {
    font-weight: 600;
}

.wallet-mini-color-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
}

.wallet-mini-color-row label {
    flex: 1 1 auto;
    font-size: .8rem;
    color: var(--bs-secondary-color);
    margin: 0;
}

.wallet-mini-color-row input[type="color"] {
    flex: 0 0 auto;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 1px solid var(--bs-border-color);
    border-radius: 6px;
    cursor: pointer;
}

/* Live preview additions - logo image (the old preview never showed one),
   the reference-number placeholder box (spec section 11), and the native-
   style two-column stats row (mirrors how Google Wallet itself renders
   loyaltyPoints/secondaryLoyaltyPoints - see GoogleWalletProvider).
   Visual hierarchy redesign (2026-08-16): header/headline (.wallet-preview-
   top) then the inset photo + overlapping stamp pill (.wallet-preview-hero-
   wrap) then stats/ref (.wallet-preview-bottom) - matching the requested
   mockup order exactly, since this preview (unlike the real installed
   card) isn't bound by Google's fixed header->stats->barcode->heroImage
   stack. .wallet-preview-top/.wallet-preview-bottom share one continuous
   solid card color (set via JS) since only the hero-wrap's inset rectangle
   can ever show a photo, same real constraint as before. */
.wallet-preview-top {
    padding: 20px 20px 4px;
    transition: background-color .15s ease;
}

.wallet-preview-bottom {
    padding: 4px 20px 20px;
    transition: background-color .15s ease;
}

.wallet-preview-hero-wrap {
    position: relative;
    padding: 0 20px;
    margin-top: 14px;
    margin-bottom: 32px;
}

.wallet-preview-hero {
    position: relative;
    height: 170px;
    border-radius: 14px;
    overflow: hidden;
    background-size: cover;
    background-position: center;
    transition: background-color .15s ease;
}

.wallet-preview-bg-overlay {
    position: absolute;
    inset: 0;
    background: #000;
    opacity: 0;
    pointer-events: none;
}

.wallet-preview-stamps-pill {
    position: absolute;
    left: 50%;
    bottom: -32px;
    transform: translateX(-50%);
    /* Without an explicit width, left:50% with no `right` shrink-fits
       against the space remaining after that offset (roughly half the
       container), not the pill's actual content - a wider stamp-count
       preset (8/10) could wrap onto multiple lines well before it needed
       to. max-content sizes it to its real content instead. */
    width: max-content;
    background: #fff;
    border-radius: 999px;
    padding: 12px 16px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .12);
}

.wallet-preview-header {
    display: flex;
    align-items: center;
    gap: 10px;
}

.wallet-preview-logo {
    flex: 0 0 auto;
    border-radius: 8px;
    object-fit: cover;
    background: rgba(255, 255, 255, .15);
}

.wallet-preview-logo.is-size-small { width: 32px; height: 32px; }
.wallet-preview-logo.is-size-medium { width: 44px; height: 44px; }
.wallet-preview-logo.is-size-large { width: 60px; height: 60px; }

.wallet-preview-stats {
    display: flex;
    gap: 20px;
    margin-top: 16px;
}

.wallet-preview-stat {
    flex: 1 1 0;
}

.wallet-preview-stat-label {
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    opacity: .8;
}

.wallet-preview-stat-value {
    font-size: 1.4rem;
    font-weight: 800;
    margin-top: 2px;
}

.wallet-preview-ref {
    background: rgba(255, 255, 255, .95);
    color: var(--bs-gray-900);
    border-radius: 10px;
    padding: 10px 14px;
    text-align: center;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-weight: 700;
    letter-spacing: .04em;
    font-size: .9rem;
    margin-bottom: 16px;
}

/* Illustrative barcode/QR preview (2026-08-25) - see the comment above its
   markup in wallet-cards/form.blade.php for why this is a static
   placeholder rather than a real generated code. */
.wallet-preview-barcode-wrap {
    background: rgba(255, 255, 255, .95);
    border-radius: 10px;
    padding: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.wallet-preview-barcode svg { display: block; height: auto; }
.wallet-preview-barcode-qr svg { width: 120px; }
.wallet-preview-barcode-linear svg { width: 100%; max-width: 220px; }

.wallet-preview-stamps.is-align-left { justify-content: flex-start; }
.wallet-preview-stamps.is-align-right { justify-content: flex-end; }

.wallet-preview-stamps-row {
    display: flex;
    justify-content: center;
    gap: 10px;
    margin-bottom: 10px;
}

.wallet-preview-stamps-row.is-align-left { justify-content: flex-start; }
.wallet-preview-stamps-row.is-align-right { justify-content: flex-end; }
.wallet-preview-stamps-row:last-child { margin-bottom: 0; }

/* Sticky right column so the preview stays visible while scrolling a
   long settings form on the left, desktop only - on narrower widths the
   columns stack and stickiness would just pin the preview awkwardly. */
@media (min-width: 992px) {
    .wallet-preview-sticky {
        position: sticky;
        top: 90px;
    }
}

/* .row is display:flex by default (Bootstrap), so the two columns already
   stretch to match each other's height - these just make the visible card
   inside each column fill that stretched height instead of shrink-wrapping
   its own content, so a shorter tab (e.g. Alapbeállítások) doesn't leave a
   blank gap below its card while the taller sibling column (whichever tab
   or the preview has more content) sets the row's real height. */
.wallet-form-card,
.wallet-preview-sticky > .card {
    --bs-card-height: 100%;
}

/* Equal-height tab panels (2026-08-25) - CSS Grid stacking so
   Alapbeállítások/Megjelenés/Extra all occupy the same cell at once; the
   grid row's height comes from the tallest of the three regardless of
   which is currently shown, instead of the settings card (and, via
   --bs-card-height above, the live-preview card next to it) visibly
   growing or shrinking every time the tab changes. Content-driven, not a
   guessed pixel value - stays correct if a tab's content changes later.
   [hidden]'s default display:none would drop a panel out of the grid
   entirely (defeating the whole point), so it's overridden to
   visibility:hidden instead - still fully laid out for sizing purposes,
   just not painted or interactive. */
.wallet-form-card > .card-body {
    display: grid;
}

.wallet-tab-panel {
    grid-column: 1;
    grid-row: 1;
    min-width: 0;
}

.wallet-tab-panel[hidden] {
    /* Bootstrap's own reset ships [hidden] { display: none !important; } -
       nothing without !important can ever beat that, regardless of
       specificity or source order. */
    display: block !important;
    visibility: hidden;
    pointer-events: none;
}

/* Full-width action bar at the bottom of the form, replacing the plain
   button row - its own card-like surface (rather than living inside the
   last settings card) makes clear it applies to the whole page, not just
   Arculat. */
.wallet-action-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 24px;
    padding: 18px 24px;
    background: #fff;
    border: 1px solid var(--bs-border-color);
    border-radius: 12px;
    box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
}

.wallet-action-bar-hint {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: .8rem;
    color: var(--bs-secondary-color);
}

.wallet-action-bar-hint .ki-outline {
    color: var(--bs-success);
    font-size: 1rem;
}

/* Áttekintés (admin/dashboard/index.blade.php) redesign - Stripe/Linear-
   style minimal SaaS look: white cards, thin borders instead of shadows,
   restrained color (blue = primary, orange = the one "needs attention"
   metric, gray = secondary, green only inside the source/conversion
   charts). Scoped to .rt-dashboard (and the toolbar bits below, which
   render outside it via the layout's @yield('toolbar-actions')) so nothing
   here touches any other admin page. */
.rt-dashboard .card {
    border: 1px solid var(--bs-border-color);
    border-radius: 12px;
    box-shadow: none;
}

/* Metronic's default --bs-card-spacer-y/x (~26px computed) is generous
   enough on its own that six stacked sections push the whole dashboard
   past one screen - tightened here rather than globally so every other
   admin page keeps its normal card padding. */
.rt-dashboard .card-body {
    padding: .85rem 1.1rem;
}

.rt-card-title {
    font-size: .88rem;
    font-weight: 600;
    color: var(--bs-gray-900);
    margin-bottom: .5rem;
}

.rt-note {
    font-size: .72rem;
    line-height: 1.35;
    color: var(--bs-secondary-color);
    margin-bottom: 0;
}

.rt-link-muted {
    font-size: .8rem;
    font-weight: 500;
    color: var(--bs-secondary-color);
}

.rt-link-muted:hover {
    color: var(--bs-primary);
}

/* Header toolbar: static "last 14 days" pill (the dashboard has no real
   date-range picker yet - this reflects the fixed trailing-14-day window
   every chart on this page actually uses, not a live control) + a refresh
   button that does a real reload of this route. */
.rt-toolbar-actions {
    display: flex;
    align-items: center;
    gap: .5rem;
}

.rt-range-pill {
    display: flex;
    align-items: center;
    gap: .4rem;
    font-size: .82rem;
    font-weight: 500;
    color: var(--bs-gray-900);
    background: #fff;
    border: 1px solid var(--bs-border-color);
    border-radius: 8px;
    padding: .5rem .8rem;
    line-height: 1;
}

.rt-range-pill .ki-outline {
    font-size: .95rem;
    color: var(--bs-gray-600);
}

.rt-refresh-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border: 1px solid var(--bs-border-color);
    border-radius: 8px;
    background: #fff;
    color: var(--bs-gray-600);
    transition: background-color .12s ease, color .12s ease;
}

.rt-refresh-btn:hover {
    background: var(--bs-gray-100);
    color: var(--bs-primary);
}

/* KPI row - 6 compact cards, icon-in-tinted-circle + big value + label.
   white-space:nowrap on value/label keeps every card the same natural
   height - without it, one long label wrapping to two lines stretches
   every card in the row to match (CSS Grid's default align-items:stretch),
   leaving dead space in the other five. */
.rt-kpi-row {
    display: grid;
    grid-template-columns: repeat(6, minmax(150px, 1fr));
    gap: .85rem;
    margin-bottom: .85rem;
}

.rt-kpi-card {
    background: #fff;
    border: 1px solid var(--bs-border-color);
    border-radius: 12px;
    padding: .6rem .85rem;
}

.rt-kpi-top {
    display: flex;
    align-items: center;
    gap: .65rem;
}

.rt-kpi-icon {
    width: 34px;
    height: 34px;
    border-radius: 999px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.05rem;
    flex-shrink: 0;
}

.rt-kpi-icon-blue {
    background: var(--bs-primary-light);
    color: var(--bs-primary);
}

.rt-kpi-icon-purple {
    background: #F3E8FF;
    color: #7C3AED;
}

.rt-kpi-icon-gray {
    background: var(--bs-gray-100);
    color: var(--bs-gray-600);
}

.rt-kpi-icon-orange {
    background: #FEF3E7;
    color: #d97706;
}

.rt-kpi-icon-indigo {
    background: #E0E7FF;
    color: #4338CA;
}

.rt-kpi-icon-teal {
    background: #CCFBF1;
    color: #0D9488;
}

.rt-kpi-value {
    font-size: 1.3rem;
    font-weight: 700;
    color: var(--bs-gray-900);
    line-height: 1.15;
    letter-spacing: -0.01em;
    white-space: nowrap;
}

.rt-kpi-label {
    font-size: .74rem;
    color: var(--bs-secondary-color);
    margin-top: .1rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* "vs previous period" badge - green/up, red/down, gray for a flat or
   brand-new (previous value was zero) reading. Every card gets both lines
   regardless of trend direction, so the six cards stay the same height
   (see the white-space:nowrap note above). */
.rt-kpi-trend {
    display: flex;
    align-items: center;
    gap: .2rem;
    font-size: .74rem;
    font-weight: 600;
    margin-top: .45rem;
}

.rt-kpi-trend-arrow {
    font-size: .8rem;
    line-height: 1;
}

.rt-kpi-trend-up,
.rt-kpi-trend-new {
    color: #16a34a;
}

.rt-kpi-trend-down {
    color: #dc2626;
}

.rt-kpi-trend-flat {
    color: var(--bs-secondary-color);
}

.rt-kpi-trend-period {
    font-size: .68rem;
    color: var(--bs-secondary-color);
    margin-top: .1rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Main analytics row - trend chart (left, ~2/3) + source donut (right, ~1/3).
   minmax(0, Xfr) instead of a bare Xfr everywhere in this file's grids -
   without the 0 floor, a track's minimum defaults to its content's
   min-content size (a long unbroken table cell, a wide SVG...), which
   silently forces the whole grid - and the page - wider than the viewport
   instead of letting the content shrink/wrap/scroll inside its own track. */
.rt-analytics-row {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    gap: .85rem;
    margin-bottom: .85rem;
    align-items: stretch;
}

.rt-analytics-row .card {
    height: 100%;
}

/* Both cards in this row are stretched to match the taller one (see
   .rt-analytics-row above) - without this, the donut card's fixed-size
   content just sits at the top of that extra height, leaving dead space
   below it. Making card-body a column flex and growing the content block
   to fill it lets .rt-donut-body's own align-items:center vertically
   center the SVG + legend within the full card height instead. */
.rt-analytics-row .card-body {
    display: flex;
    flex-direction: column;
    height: 100%;
}

.rt-trend-chart-wrap {
    min-height: 120px;
    flex: 1;
    display: flex;
    align-items: center;
}

.rt-donut-body {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.1rem;
    flex-wrap: wrap;
    flex: 1;
    min-height: 118px;
}

.rt-donut-legend {
    display: flex;
    flex-direction: column;
    gap: .45rem;
    flex: 1;
    min-width: 130px;
}

.rt-donut-legend-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    font-size: .84rem;
}

.rt-donut-legend-label {
    display: flex;
    align-items: center;
    gap: .55rem;
    color: var(--bs-gray-900);
}

.rt-donut-dot {
    width: 8px;
    height: 8px;
    border-radius: 999px;
    flex-shrink: 0;
}

.rt-donut-legend-value {
    font-weight: 600;
    color: var(--bs-gray-900);
}

/* Middle content: traffic table (left, narrower) + revenue KPI cards &
   table (right, wider - revenue is the more important figure of the two).
   The right column is also usually the taller one (revenue cards + a
   second table), so the traffic card is stretched to match it (rather than
   hugging its own 2-10 rows) - otherwise it sits short next to a large
   blank gap before the next section, which reads as a layout bug rather
   than empty space inside a card. Table stays top-aligned (that's the
   natural reading order for rows) - the "+N more" footer link is what
   absorbs the leftover height (see .rt-table-more further down), pinned to
   the bottom of the card instead of floating right under a short table. */
.rt-middle-row {
    display: grid;
    grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr);
    gap: .85rem;
    margin-bottom: .85rem;
    align-items: stretch;
}

.rt-middle-row > .card {
    height: 100%;
    min-width: 0;
}

.rt-middle-row > .card > .card-body {
    display: flex;
    flex-direction: column;
    height: 100%;
}

.rt-middle-right {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: .5rem;
    min-width: 0;
}

/* Disclaimer badge floats over the top-right corner instead of sitting in
   its own row - a row of its own, even a thin one, would push the revenue
   cards down and throw off their top edge against the Ügyfélforgalom card
   next to them (both are direct children of the same .rt-middle-row grid
   row, so they only line up if both start their visible content at y:0). */
.rt-revenue-header {
    position: absolute;
    top: -6px;
    right: -6px;
}

.rt-info-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    border-radius: 999px;
    background: var(--bs-gray-100);
    color: var(--bs-gray-600);
    font-size: .68rem;
    font-weight: 700;
    cursor: help;
    flex-shrink: 0;
}

.rt-info-badge:hover,
.rt-info-badge:focus-visible {
    background: var(--bs-gray-200);
    color: var(--bs-gray-900);
    outline: none;
}

.rt-revenue-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: .55rem;
}

.rt-revenue-grid .rt-kpi-card {
    padding: .85rem 1rem;
}

.rt-kpi-icon-green {
    background: #DCFCE7;
    color: #16a34a;
}

/* Compact table treatment (Ügyfélforgalom / Ügyfelenkénti bevétel) - small
   uppercase gray headers, tighter row padding, no double borders. */
.rt-dashboard .rt-table thead th {
    text-transform: uppercase;
    font-size: .66rem;
    letter-spacing: .03em;
    font-weight: 600;
    color: var(--bs-gray-600);
    border-bottom: 1px solid var(--bs-border-color);
    padding-top: .35rem;
    padding-bottom: .35rem;
    white-space: nowrap;
}

.rt-dashboard .rt-table td {
    padding-top: .4rem;
    padding-bottom: .4rem;
    font-size: .82rem;
    color: var(--bs-gray-900);
    border-bottom: 1px solid var(--bs-border-color);
}

.rt-dashboard .rt-table tbody tr:last-child td {
    border-bottom: none;
}

.rt-table-more {
    margin-top: auto;
    padding-top: .6rem;
    border-top: 1px solid var(--bs-border-color);
    text-align: center;
}

/* Bottom conversion-rate card - three compact tiles side by side (dot +
   label, big percentage, thin bar) instead of three full-width stacked
   rows. The old stacked-row layout put a thin bar on a ~220px-to-full-width
   track, which read as mostly empty horizontal space for just three
   numbers; putting the tiles side by side uses that same width to show
   more at a glance in a fraction of the height. */
.rt-conversion-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1.25rem;
}

.rt-conversion-tile-head {
    display: flex;
    align-items: center;
    gap: .5rem;
    font-size: .8rem;
    color: var(--bs-secondary-color);
    margin-bottom: .3rem;
}

.rt-conversion-dot {
    width: 8px;
    height: 8px;
    border-radius: 999px;
    flex-shrink: 0;
}

.rt-conversion-tile-value {
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--bs-gray-900);
    line-height: 1.15;
    letter-spacing: -0.01em;
    margin-bottom: .45rem;
}

.rt-conversion-track {
    height: 8px;
    border-radius: 999px;
    background: var(--bs-gray-100);
    overflow: hidden;
}

.rt-conversion-fill {
    height: 100%;
    border-radius: 999px;
}

@media (max-width: 1399.98px) {
    .rt-kpi-row {
        grid-template-columns: repeat(3, 1fr);
    }
}

@media (max-width: 1199.98px) {
    .rt-middle-row {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 991.98px) {
    .rt-analytics-row {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 767.98px) {
    .rt-kpi-row {
        grid-template-columns: repeat(2, 1fr);
    }

    .rt-conversion-grid {
        grid-template-columns: 1fr;
        gap: .85rem;
    }
}

@media (max-width: 575.98px) {
    .rt-kpi-row {
        grid-template-columns: 1fr;
    }

    .rt-revenue-grid {
        grid-template-columns: 1fr;
    }
}

/* ===== Statisztika page ===== */

/* Functional twin of .rt-range-pill (a static label on the dashboard,
   which has no real range picker yet) - same look, but a real <select>
   that submits the page with ?range=. Native select styling is reset back
   to the pill's own chrome instead of the browser default box. */
.rt-range-select {
    appearance: none;
    -webkit-appearance: none;
    font-size: .82rem;
    font-weight: 500;
    color: var(--bs-gray-900);
    background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath fill='%2399a1b7' d='M1 1l4 4 4-4'/%3E%3C/svg%3E") no-repeat right .75rem center;
    border: 1px solid var(--bs-border-color);
    border-radius: 8px;
    padding: .5rem 1.9rem .5rem .8rem;
    line-height: 1;
    cursor: pointer;
}

.rt-range-select:hover {
    border-color: var(--bs-gray-300);
}

/* Legend above the trend chart ("Beolvasások" / "Előző időszak") - only
   rendered when a previous-period comparison line is actually on the
   chart, so it doesn't show up for the "Minden idő" range (no previous
   period to compare against). */
.rt-trend-legend {
    display: flex;
    align-items: center;
    gap: 1.1rem;
    font-size: .78rem;
    color: var(--bs-secondary-color);
    margin-bottom: .35rem;
}

.rt-trend-legend-item {
    display: flex;
    align-items: center;
    gap: .4rem;
}

.rt-trend-legend-dot {
    width: 8px;
    height: 8px;
    border-radius: 999px;
    background: var(--bs-primary);
    flex-shrink: 0;
}

.rt-trend-legend-dash {
    width: 12px;
    height: 0;
    border-top: 2px dashed #B6BAC4;
    flex-shrink: 0;
}

/* Secondary analytics sections (Visszajelzések / Hűségkártya / E-mail
   kampányok / Előfizetések / Fizikai kártyák) - compact icon+value tiles,
   same visual language as the KPI row but no trend row (these are
   supporting detail, not the page's headline numbers) and packed 3-4 to a
   card instead of spanning the full row. */
.rt-secondary-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: .85rem;
}

.rt-secondary-card .rt-kpi-top {
    margin-bottom: 0;
}

.rt-secondary-card-body {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: .7rem;
}

/* Client-side filter box above the Ügyfelenkénti beolvasások table - pure
   JS row-hide, no server round-trip (unlike the Ügyfelek page's own ?q=
   search), since every row for this table is already on the page. */
.rt-table-search {
    position: relative;
    max-width: 280px;
}

.rt-table-search input {
    padding-left: 2.1rem;
}

.rt-table-search .ki-outline {
    position: absolute;
    left: .75rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--bs-gray-500);
    font-size: .95rem;
    pointer-events: none;
}

.rt-table-company {
    font-weight: 600;
    color: var(--bs-gray-900);
}

.rt-table-company-sub {
    font-size: .72rem;
    color: var(--bs-secondary-color);
    margin-top: .05rem;
}

@media (max-width: 767.98px) {
    .rt-secondary-card-body {
        grid-template-columns: 1fr;
    }
}

/* Explanatory footer note, closing out the page - light blue tint instead
   of the plain white/bordered card treatment used everywhere else on this
   page, so it visually reads as "context", not another data section. */
.rt-info-panel {
    display: flex;
    gap: .75rem;
    align-items: flex-start;
    background: var(--bs-primary-light);
    border: 1px solid var(--bs-primary-border-subtle);
    border-radius: 12px;
    padding: .9rem 1.1rem;
    color: var(--bs-gray-900);
}

.rt-info-panel > .ki-outline {
    color: var(--bs-primary);
    flex-shrink: 0;
    margin-top: .1rem;
}

.rt-info-panel-title {
    font-weight: 600;
    margin-bottom: .25rem;
}

.rt-info-panel p {
    font-size: .82rem;
    color: var(--bs-gray-700);
    line-height: 1.5;
}

/* ===== Wallet card editor tabs (admin/wallet-cards/form.blade.php) =====
   Deliberately a separate class from the existing .nav-tabs (used by
   clients/show.blade.php) rather than reusing it - that one is a past,
   intentionally-neutral-gray redesign (see its own comment above), while
   this page's reference mockup calls for the classic blue-underline
   active state, so the two coexist as different tab styles for different
   pages rather than one fighting the other's own explicit design call. */
.wallet-tabs {
    display: flex;
    gap: 4px;
    padding: 0 1.1rem;
    border-bottom: 1px solid var(--bs-border-color);
}

.wallet-tab-btn {
    display: flex;
    align-items: center;
    gap: .45rem;
    padding: .85rem .25rem;
    margin-bottom: -1px;
    border: none;
    border-bottom: 2px solid transparent;
    background: transparent;
    font-size: .875rem;
    font-weight: 500;
    color: var(--bs-secondary-color);
    cursor: pointer;
    transition: color .12s ease, border-color .12s ease;
}

.wallet-tabs .wallet-tab-btn + .wallet-tab-btn {
    margin-left: 1.1rem;
}

.wallet-tab-btn:hover:not(.is-active) {
    color: var(--bs-gray-800);
}

.wallet-tab-btn.is-active {
    color: var(--bs-primary);
    font-weight: 600;
    border-bottom-color: var(--bs-primary);
}

.rt-dashboard .wallet-tabs ~ .card-body {
    padding-top: 1.1rem;
}

.wallet-divider {
    border: none;
    border-top: 1px solid var(--bs-border-color);
    margin: 1.5rem 0 1.1rem;
}

.wallet-subsection-title {
    font-size: .8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--bs-gray-600);
    margin-bottom: .85rem;
}

/* Alapbeállítások tab restructure (2026-08-25) - each settings group
   (Hűségkártya aktív, Alapadatok, Jutalom, Azonosítás, Kártyán megjelenő
   feliratok) gets its own bordered card with an icon+heading, instead of
   one long undifferentiated scroll of rows - matches the reference
   design's clearer hierarchy. Long explanatory paragraphs that used to
   sit inline under a field now live on a small (i) icon's title tooltip
   instead, so the card reads at a glance rather than as a wall of text -
   the full explanation is still one hover away, never actually removed. */
.wallet-section {
    background: #fff;
    border: 1px solid var(--bs-border-color);
    border-radius: 14px;
    padding: 1.35rem 1.5rem;
    margin-bottom: 1.1rem;
}

.wallet-section:last-child { margin-bottom: 0; }

.wallet-section-head {
    display: flex;
    align-items: center;
    gap: .65rem;
    margin-bottom: 1.15rem;
    padding-bottom: 1.15rem;
    border-bottom: 1px solid var(--bs-border-color);
}

.wallet-section-title {
    font-size: .95rem;
    font-weight: 700;
    color: var(--bs-gray-900);
    margin: 0;
}

.wallet-section-icon {
    width: 34px;
    height: 34px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.05rem;
    flex-shrink: 0;
}

.wallet-section-icon-blue { background: var(--bs-primary-light); color: var(--bs-primary); }
.wallet-section-icon-purple { background: #f2ecfe; color: #7c3aed; }
.wallet-section-icon-indigo { background: #eef0fe; color: #4f46e5; }
.wallet-section-icon-orange { background: #fff1e6; color: #ea580c; }
.wallet-section-icon-green { background: #e9f9f1; color: #16a34a; }

/* Compact icon+label+value mini-stat (client show page's Előfizetés
   section) - a lighter-weight sibling of .info-grid for a row of small,
   individually-iconed facts, reusing .wallet-section-icon's color tones
   for visual consistency with the section headers above it. */
.info-mini-grid {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 16px;
}

@media (max-width: 992px) {
    .info-mini-grid { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 576px) {
    .info-mini-grid { grid-template-columns: repeat(2, 1fr); }
}

.info-mini-stat {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.info-mini-stat-label {
    font-size: .72rem;
    color: var(--bs-secondary-color);
    margin-bottom: 2px;
}

.info-mini-stat-value {
    font-size: .92rem;
    font-weight: 700;
    color: var(--bs-gray-900);
}

.wallet-char-count {
    font-size: .72rem;
    color: var(--bs-secondary-color);
    white-space: nowrap;
}

/* Compact "current asset + swap/remove" row, replacing a full dropzone box
   once a logo/background/icon already exists - only the empty state (see
   .wallet-dropzone, unchanged) shows the bigger drag-and-drop zone. */
.wallet-asset-row {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin-bottom: .5rem;
}

.wallet-asset-thumb {
    width: 52px;
    height: 52px;
    object-fit: cover;
    border-radius: 8px;
    border: 1px solid var(--bs-border-color);
    background: #fff;
    flex-shrink: 0;
}

.wallet-asset-thumb-wide {
    width: 84px;
    height: 52px;
}

.wallet-asset-thumb-sm {
    width: 36px;
    height: 36px;
    object-fit: contain;
    padding: 4px;
}

.wallet-asset-actions {
    display: flex;
    align-items: center;
    gap: .6rem;
    flex-wrap: wrap;
}

.wallet-asset-remove {
    border: none;
    background: none;
    padding: 0;
    font-size: .8rem;
    font-weight: 500;
    color: var(--bs-secondary-color);
    cursor: pointer;
}

.wallet-asset-remove:hover {
    color: var(--bs-danger);
}

.wallet-asset-link {
    font-size: .8rem;
    font-weight: 600;
    color: var(--bs-primary);
    cursor: pointer;
}

.wallet-asset-link:hover {
    text-decoration: underline;
}

.wallet-asset-row-compact {
    margin-bottom: .4rem;
}

.wallet-dropzone-sm {
    padding: 12px;
}

.wallet-preview-hint {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    font-size: .78rem;
    color: var(--bs-secondary-color);
    margin-top: 1rem;
}

.wallet-preview-hint .ki-outline {
    color: var(--bs-primary);
    font-size: 1rem;
    margin-top: 1px;
    flex-shrink: 0;
}

.wallet-save-state-dot {
    width: 7px;
    height: 7px;
    border-radius: 999px;
    background: var(--bs-warning);
    flex-shrink: 0;
}

.wallet-action-bar-hint.is-dirty {
    color: var(--bs-warning);
    font-weight: 500;
}

.wallet-resync-card .card-body {
    padding: 16px 24px;
}

.wallet-resync-label {
    font-size: .85rem;
    font-weight: 500;
    color: var(--bs-gray-700);
}

.wallet-resync-label .ki-outline {
    font-size: 1rem;
    margin-right: 2px;
}

.wallet-resync-count {
    font-size: .8rem;
    font-variant-numeric: tabular-nums;
    color: var(--bs-secondary-color);
}

/* Minimal static card mockup (admin/wallet-cards/_mini-preview.blade.php) -
   the client page's Hűségkártya tab, quick-glance only. Same visual
   hierarchy as .wallet-preview-* (form.blade.php's full JS-driven "Élő
   előnézet") and public/wallet-coming-soon.blade.php's .wcard - header ->
   headline -> hero photo with an overlapping white stamp pill -> stats -
   just smaller and server-rendered. The white pill isn't optional: the
   incomplete-stamp colors are designed for contrast against white, and
   read as washed-out gray blobs directly on the card's own background
   color without it. background-color set inline per card since it's the
   card's own effectiveColor(). */
.wcard-mini {
    position: relative;
    max-width: 320px;
    border-radius: 14px;
    padding: 22px 24px;
    color: #fff;
    overflow: hidden;
}

.wcard-mini-header {
    display: flex;
    align-items: center;
    gap: 8px;
}

.wcard-mini-logo {
    width: 26px;
    height: 26px;
    border-radius: 6px;
    object-fit: cover;
    flex-shrink: 0;
    background: rgba(255, 255, 255, .15);
}

.wcard-mini-business {
    font-size: .8rem;
    font-weight: 700;
}

.wcard-mini-divider {
    height: 1px;
    background: rgba(255, 255, 255, .3);
    margin: 10px 0;
}

.wcard-mini-headline {
    font-size: .92rem;
    font-weight: 700;
    line-height: 1.3;
}

.wcard-mini-hero-wrap {
    position: relative;
    margin: 14px 0 26px;
}

.wcard-mini-hero {
    position: relative;
    height: 100px;
    border-radius: 10px;
    overflow: hidden;
    background-color: rgba(255, 255, 255, .08);
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}

.wcard-mini-overlay {
    position: absolute;
    inset: 0;
    background: #000;
}

.wcard-mini-stamps-pill {
    position: absolute;
    left: 50%;
    bottom: -22px;
    transform: translateX(-50%);
    width: max-content;
    background: #fff;
    border-radius: 999px;
    padding: 8px 12px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, .16);
}

.wcard-mini-stamps-row {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: 6px;
}

.wcard-mini-stamps-row + .wcard-mini-stamps-row {
    margin-top: 6px;
}

.wcard-mini-stamps-row.is-align-left { justify-content: flex-start; }
.wcard-mini-stamps-row.is-align-right { justify-content: flex-end; }

.wcard-mini-stamp {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    flex-shrink: 0;
}

.wcard-mini-stats {
    display: flex;
    gap: 20px;
}

.wcard-mini-stat-label {
    font-size: .58rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    opacity: .85;
}

.wcard-mini-stat-value {
    font-size: 1.05rem;
    font-weight: 800;
    margin-top: 1px;
}

/* Detail list beside the mini preview (admin/wallet-cards/_summary-card.
   blade.php) - a plain label/value row per fact, not a table, since it's
   always exactly one card's worth of facts, never multiple rows. */
.wcard-summary-details > div {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 8px 0;
    border-bottom: 1px solid var(--bs-border-color);
}

.wcard-summary-details > div:first-child {
    padding-top: 0;
}

.wcard-summary-details > div:last-child {
    border-bottom: none;
    padding-bottom: 0;
}

.wcard-summary-details dt {
    font-size: .8rem;
    color: var(--bs-secondary-color);
    font-weight: 500;
    margin: 0;
}

.wcard-summary-details dd {
    font-size: .85rem;
    font-weight: 600;
    color: var(--bs-gray-800);
    margin: 0;
    text-align: right;
}

@media (max-width: 767.98px) {
    .wallet-tabs {
        overflow-x: auto;
        padding: 0 .75rem;
    }

    .wallet-tab-btn {
        white-space: nowrap;
    }
}

/* Popover date-range picker (admin/clients/show.blade.php's Analitika tab,
   rt-daterange.js) - replaces the old always-visible preset-buttons + bare
   date-input row with a single trigger button that opens a calendar
   popover, closer to common modern analytics-dashboard date pickers.
   Submits via the exact same ?range= / ?from=&to= query contract as
   before (App\Support\DateRange::resolve()) - this is a UI-only change,
   nothing server-side needed touching. */
.rt-daterange {
    position: relative;
    margin-top: 12px;
}

.rt-daterange-trigger {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    background: #fff;
    border: 1px solid var(--bs-border-color);
    border-radius: 10px;
    font-size: .85rem;
    font-weight: 600;
    color: var(--bs-gray-800);
    cursor: pointer;
}

.rt-daterange-trigger:hover {
    border-color: var(--bs-primary);
}

.rt-daterange-trigger .ki-calendar {
    color: var(--bs-primary);
    font-size: 1rem;
}

.rt-daterange-chevron {
    font-size: .6rem;
    color: var(--bs-secondary-color);
    transition: transform .15s ease;
}

.rt-daterange.is-open .rt-daterange-chevron {
    transform: rotate(180deg);
}

.rt-daterange-popover {
    position: absolute;
    z-index: 50;
    top: calc(100% + 8px);
    left: 0;
    width: 640px;
    max-width: calc(100vw - 48px);
    background: #fff;
    border: 1px solid var(--bs-border-color);
    border-radius: 14px;
    box-shadow: 0 12px 32px rgba(15, 23, 42, .14);
    overflow: hidden;
}

.rt-daterange-body {
    display: flex;
}

.rt-daterange-presets {
    flex: 0 0 150px;
    padding: 14px 10px;
    border-right: 1px solid var(--bs-border-color);
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.rt-daterange-preset-btn {
    text-align: left;
    padding: 8px 10px;
    border: none;
    background: transparent;
    border-radius: 8px;
    font-size: .83rem;
    font-weight: 500;
    color: var(--bs-gray-700);
    cursor: pointer;
}

.rt-daterange-preset-btn:hover {
    background: var(--bs-gray-100);
}

.rt-daterange-preset-btn.is-active {
    background: var(--bs-primary-light);
    color: var(--bs-primary);
    font-weight: 700;
}

.rt-daterange-main {
    flex: 1 1 auto;
    padding: 14px 18px;
    min-width: 0;
}

.rt-daterange-inputs {
    display: flex;
    align-items: flex-end;
    gap: 10px;
    margin-bottom: 14px;
}

.rt-daterange-inputs > div {
    flex: 1 1 0;
}

.rt-daterange-inputs label {
    display: block;
    font-size: .7rem;
    font-weight: 600;
    color: var(--bs-secondary-color);
    text-transform: uppercase;
    letter-spacing: .03em;
    margin-bottom: 4px;
}

.rt-daterange-inputs input[type="date"] {
    width: 100%;
    padding: 6px 8px;
    border: 1px solid var(--bs-border-color);
    border-radius: 8px;
    font-size: .82rem;
}

.rt-daterange-input-sep {
    padding-bottom: 8px;
    color: var(--bs-secondary-color);
}

.rt-daterange-cal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
}

.rt-daterange-cal-header button {
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--bs-border-color);
    background: #fff;
    border-radius: 7px;
    cursor: pointer;
    color: var(--bs-gray-700);
}

.rt-daterange-cal-header button:hover {
    background: var(--bs-gray-100);
}

.rt-daterange-month-label {
    font-size: .85rem;
    font-weight: 700;
    color: var(--bs-gray-800);
}

.rt-daterange-weekdays,
.rt-daterange-days {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
}

.rt-daterange-weekdays span {
    text-align: center;
    font-size: .68rem;
    font-weight: 600;
    color: var(--bs-secondary-color);
    padding-bottom: 6px;
}

.rt-daterange-day {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 32px;
    border: none;
    background: transparent;
    font-size: .8rem;
    color: var(--bs-gray-800);
    cursor: pointer;
    border-radius: 999px;
}

.rt-daterange-day:hover:not(.is-empty):not(:disabled) {
    background: var(--bs-gray-100);
}

.rt-daterange-day.is-empty {
    cursor: default;
}

.rt-daterange-day.is-today {
    font-weight: 700;
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* In-range days sit on a continuous flat band, not individually rounded
   pills - the row wrapper below draws that band; start/end still get
   their own solid circle on top so the range's edges stay unambiguous. */
.rt-daterange-day.is-in-range {
    background: var(--bs-primary-light);
    border-radius: 0;
}

.rt-daterange-day.is-range-start {
    border-radius: 999px 0 0 999px;
}

.rt-daterange-day.is-range-end {
    border-radius: 0 999px 999px 0;
}

.rt-daterange-day.is-range-start.is-range-end {
    border-radius: 999px;
}

.rt-daterange-day.is-range-start::after,
.rt-daterange-day.is-range-end::after {
    content: '';
    position: absolute;
    inset: 2px;
    border-radius: 999px;
    background: var(--bs-primary);
    z-index: -1;
}

.rt-daterange-day.is-range-start,
.rt-daterange-day.is-range-end {
    color: #fff;
    font-weight: 700;
}

.rt-daterange-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 18px;
    background: var(--bs-gray-100);
    border-top: 1px solid var(--bs-border-color);
}

.rt-daterange-summary {
    font-size: .8rem;
    color: var(--bs-secondary-color);
}

@media (max-width: 575.98px) {
    .rt-daterange-popover {
        width: 320px;
    }

    .rt-daterange-body {
        flex-direction: column;
    }

    .rt-daterange-presets {
        flex-direction: row;
        flex-wrap: wrap;
        border-right: none;
        border-bottom: 1px solid var(--bs-border-color);
    }
}
