/*
 * Buttons, links, fields and icons that can be seen and hit (user,
 * 2026-10-06: "improve the visibility and usability of buttons and icons.
 * Key is to enhance the mobile experience").
 *
 * css/app.css is the compiled Bootstrap 4.1.3 bundle and the image does not
 * rebuild it, so the changes live here, loaded straight after it. Measured
 * before, at 375x667 and 320x568:
 *  - every button 37px tall and the small ones 29px, the Remember Me box
 *    13px, the menu toggle 37px. 44px is the WCAG 2.5.5 / Apple HIG minimum
 *  - every field's text 14.4px, 12.6px in the small ones: iOS zooms the page
 *    into a field whose text is under 16px, and leaves it zoomed
 *  - /register was 440px wide on a 375px screen (the Sign Up button's
 *    offset-4), the dashboard 367px at 320 (a contact row that did not
 *    wrap), and a client system's Edit, Revoke and Remove sat at x=551-726
 *  - white on Bootstrap's blue was 3.98:1, on its green 3.13:1 and on its
 *    teal 3.04:1, the amber Revoke 1.63:1 on white, where text needs 4.5:1;
 *    the links, outline buttons and the green Verified badge with them
 * Colours, focus and icons apply at every width. Sizes and layout apply
 * below md, the navbar's own phone breakpoint: a desktop keeps Bootstrap's.
 */

/* -- Icons ---------------------------------------------------------------- */
/* Moved here from layouts/app's inline <style>; the font sits beside this
   file. block: while it loads an icon is blank, never its name in letters. */
@font-face {
    font-family: 'Material Icons';
    font-style: normal;
    font-weight: 400;
    font-display: block;
    src: url("MaterialIcons-Regular.woff2") format("woff2");
}

.material-icons {
    font-family: 'Material Icons';
    font-weight: normal;
    font-style: normal;
    font-size: 24px;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    display: inline-block;
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
    -webkit-font-feature-settings: 'liga';
    font-feature-settings: 'liga';
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* <span class="material-icons" data-icon="delete" aria-hidden="true"></span>:
   the glyph comes from the stylesheet, so its name is never part of the
   text - a button reads "Remove", not "delete Remove", to a screen reader,
   to find-in-page and to a test. One square wide: if the font were missing
   the name would be clipped, not spelled out across the button. */
.material-icons[data-icon]::before {
    content: attr(data-icon);
}
.material-icons[data-icon] {
    width: 1em;
    height: 1em;
    overflow: hidden;
}

/* In a button, a menu item or a link: in line with its words and a little
   larger than them, so it reads as a sign rather than a letter. */
.btn > .material-icons,
.dropdown-item > .material-icons,
a > .material-icons {
    font-size: 1.25em;
    vertical-align: -0.25em;
    margin-right: 0.375rem;
}
.dropdown-item > .material-icons {
    color: #495057; /* 8.2:1 on white: the words stay the strongest thing */
}

/* -- Colours: 4.5:1 for every button's, link's and badge's words ------------ */
/* Bootstrap's own deeper shades of the same hues, so nothing changes colour,
   only depth: blue #0062cc (white on it 5.8:1), green #1e7e34 (5.1:1, the
   admin tables' Verified), teal #117a8b (5.0:1, their WhatsApp) and amber
   #b45309 (5.0:1 on white, the dialogs' warning icon). The pressed shades
   go deeper still. */
a { color: #0062cc; }
a:hover { color: #004a99; }
.text-primary { color: #0062cc !important; }

.btn-link { color: #0062cc; }
.btn-link:hover,
.btn-link:focus { color: #004a99; }

.btn-primary,
.btn-primary.disabled,
.btn-primary:disabled {
    background-color: #0062cc;
    border-color: #0062cc;
}
.btn-primary:hover {
    background-color: #0056b3;
    border-color: #004a99;
}
.btn-primary:not(:disabled):not(.disabled):active,
.btn-primary:not(:disabled):not(.disabled).active,
.show > .btn-primary.dropdown-toggle {
    background-color: #004a99;
    border-color: #003f80;
}

.btn-success,
.btn-success.disabled,
.btn-success:disabled {
    background-color: #1e7e34;
    border-color: #1e7e34;
}
.btn-success:hover {
    background-color: #19692c;
    border-color: #155724;
}
.btn-success:not(:disabled):not(.disabled):active,
.btn-success:not(:disabled):not(.disabled).active {
    background-color: #155724;
    border-color: #11461d;
}

.btn-info,
.btn-info.disabled,
.btn-info:disabled {
    background-color: #117a8b;
    border-color: #117a8b;
}
.btn-info:hover {
    background-color: #0f6674;
    border-color: #0c5460;
}
.btn-info:not(:disabled):not(.disabled):active,
.btn-info:not(:disabled):not(.disabled).active {
    background-color: #0c5460;
    border-color: #0a4650;
}

.btn-outline-primary,
.btn-outline-primary.disabled,
.btn-outline-primary:disabled {
    color: #0062cc;
    border-color: #0062cc;
}
.btn-outline-primary:hover,
.btn-outline-primary:not(:disabled):not(.disabled):active,
.btn-outline-primary:not(:disabled):not(.disabled).active {
    color: #fff;
    background-color: #0062cc;
    border-color: #0062cc;
}

.btn-outline-success,
.btn-outline-success.disabled,
.btn-outline-success:disabled {
    color: #1e7e34;
    border-color: #1e7e34;
}
.btn-outline-success:hover,
.btn-outline-success:not(:disabled):not(.disabled):active,
.btn-outline-success:not(:disabled):not(.disabled).active {
    color: #fff;
    background-color: #1e7e34;
    border-color: #1e7e34;
}

/* Revoke: Bootstrap's #ffc107 on white was 1.63:1, the hardest words on
   the page to read, on the button that cuts a system off. */
.btn-outline-warning,
.btn-outline-warning.disabled,
.btn-outline-warning:disabled {
    color: #b45309;
    border-color: #b45309;
}
.btn-outline-warning:hover,
.btn-outline-warning:not(:disabled):not(.disabled):active,
.btn-outline-warning:not(:disabled):not(.disabled).active {
    color: #fff;
    background-color: #b45309;
    border-color: #b45309;
}

.badge-primary { background-color: #0062cc; }
.badge-success { background-color: #1e7e34; }
.badge-info { background-color: #117a8b; }

/* The navbar's links (Login, Register, the signed-in name) were black at
   half strength, 3.95:1; the toggle's lines and edge as faint. */
.navbar-light .navbar-nav .nav-link { color: rgba(0, 0, 0, 0.7); }
.navbar-light .navbar-nav .nav-link:hover,
.navbar-light .navbar-nav .nav-link:focus { color: rgba(0, 0, 0, 0.9); }
.navbar-light .navbar-toggler { border-color: rgba(0, 0, 0, 0.3); }
.navbar-light .navbar-toggler-icon {
    background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.75)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E");
}

/* -- Focus: a ring that can be found ------------------------------------- */
/* Bootstrap's is a pale half-transparent glow, about 1.5:1 on white, and
   none at all on a link. 7:1 on white, outside the control. */
.btn:focus-visible,
a:focus-visible,
summary:focus-visible,
.close:focus-visible,
.navbar-toggler:focus-visible,
.dropdown-item:focus-visible {
    outline: 3px solid #0056b3;
    outline-offset: 2px;
}
.btn:focus-visible {
    box-shadow: none;
}

/* -- Admin: the three user counts ---------------------------------------- */
/* Spaced by the row rather than by each button's mx-3, so on a phone they
   can stack (below) without margins pushing them off the card. */
.admin-stats {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.75rem 2rem;
}

/* -- Contact rows (shared/contact-status) --------------------------------- */
/* A value and its badges: they wrap under the value when the line is full
   (at 320px "Verified" ran 47px past the screen). The actions are spaced by
   the row's gap, not by a margin on each control, so a line that wraps is
   spaced like one that does not. */
.contact-line {
    gap: 0.25rem 0.5rem;
}
/* An email address has nowhere to break: at 320px a long one ran past the
   card's edge. */
.contact-line > span {
    min-width: 0;
    overflow-wrap: anywhere;
}
.contact-actions {
    gap: 0.5rem;
}
.contact-actions > form {
    display: inline-flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 0.5rem;
}

/* -- Long words ------------------------------------------------------------ */
/* .text-break is Bootstrap 4.3's, and this bundle is 4.1: the views that ask
   for it got nothing, and on /profile a long email address and its Verified
   badge ran 6px past a 320px phone (test_mobile, 2026-10-15). anywhere, not
   break-word: only anywhere lets a flex item (a list row's value) shrink
   below the whole address, and min-width 0 lets it try. */
.text-break {
    min-width: 0;
    overflow-wrap: anywhere;
}

/* -- Pay pages (resources/views/pay) -------------------------------------- */
/* A pay page's buttons, one under the other at every width: the page is one
   decision, top to bottom. The views of 2026-10-12 asked for this with
   Bootstrap 5's d-grid and gap-2, which this Bootstrap 4.1 bundle does not
   define, so Pay and Pay another way sat side by side, touching. A form in
   the column (Pay another way) is a column too, so its button spans it. */
.pay-actions {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}
.pay-actions > form {
    display: flex;
    flex-direction: column;
}
/* Try again beside Pay another way, wrapping on a narrow phone. */
.pay-actions.pay-actions-row {
    flex-direction: row;
    flex-wrap: wrap;
}
/* The checking page's turning circle (Bootstrap 4.1 has no spinner-border). */
.pay-spinner {
    display: inline-block;
    width: 2rem;
    height: 2rem;
    border: 0.25em solid #0062cc;
    border-right-color: transparent;
    border-radius: 50%;
    animation: pay-spin 0.75s linear infinite;
}
@keyframes pay-spin {
    to { transform: rotate(360deg); }
}
/* Slower, not stopped: a still circle would say nothing is happening. */
@media (prefers-reduced-motion: reduce) {
    .pay-spinner {
        animation-duration: 2.5s;
    }
}

/* ===========================================================================
   Phones (below md): targets, fields and layout
   =========================================================================== */
@media (max-width: 767.98px) {
    /* 44px (WCAG 2.5.5 / Apple HIG). By padding and min-height, not by
       turning the button into a flex box: it keeps its display, so its
       words and their neighbours read as they did. */
    .btn {
        min-height: 2.75rem;
        padding-top: 0.625rem;
        padding-bottom: 0.625rem;
        touch-action: manipulation;
    }
    .btn-sm {
        font-size: 0.875rem;
        line-height: 1.6;
        padding-left: 0.75rem;
        padding-right: 0.75rem;
    }
    .btn-lg {
        padding-top: 0.5rem;
        padding-bottom: 0.5rem;
    }

    .navbar-toggler,
    .close {
        min-width: 2.75rem;
        min-height: 2.75rem;
        touch-action: manipulation;
    }
    .navbar-brand {
        min-height: 2.75rem;
    }
    .navbar-nav .nav-link,
    .dropdown-item {
        display: flex;
        align-items: center;
        min-height: 2.75rem;
    }

    /* Fields: 16px words, so iOS does not zoom into them, and 44px tall. */
    .form-control,
    .custom-select {
        font-size: 1rem;
        min-height: 2.75rem;
    }

    /* The phone field's country list (intl-tel-input): its search field
       zoomed like any other, and its countries were 34px apart. */
    .iti__search-input {
        font-size: 1rem;
    }
    /* The dial code button sits inside the field's 1px edge: 42px. (.iti
       first: the widget's stylesheet is loaded after this one.) */
    .iti .iti__country-container {
        padding: 0;
    }
    .iti__country {
        min-height: 2.75rem;
    }

    /* A ticked box: the whole line is the target, not the 13px box. */
    .checkbox > label,
    .form-check {
        display: flex;
        align-items: center;
        min-height: 2.75rem;
        margin-bottom: 0;
    }
    .form-check {
        padding-left: 0;
    }
    .form-check-label {
        display: flex;
        align-items: center;
        min-height: 2.75rem;
    }
    .checkbox input[type="checkbox"],
    .form-check-input {
        position: static;
        flex: none;
        width: 1.25rem;
        height: 1.25rem;
        margin: 0 0.5rem 0 0;
    }

    /* A disclosure in running text (a loyalty number's "Recent"). */
    #loyalty-points details > summary {
        line-height: 2.75rem;
    }

    /* Status words a little larger: 10.8px bold was hard to read at arm's
       length. */
    .badge {
        font-size: 0.8125rem;
        padding: 0.3em 0.5em;
    }

    /* A contact that is not proven yet: the code and its Verify button
       take a line of their own, the field as wide as the line allows. */
    .contact-actions > .contact-verify {
        flex: 1 1 100%;
        min-width: 0; /* else the field's natural width holds the form wider than the row */
    }
    .contact-verify > .form-control {
        flex: 1 1 auto;
        width: auto;
        min-width: 0;
    }
    /* A button in a row keeps its size and its words on one line (the field
       beside Verify squeezed it into "Veri-fy" under its icon), and the
       channel list is as wide as its words, not the whole line. */
    .contact-actions .btn {
        flex: none;
    }
    .contact-actions > form:not(.contact-verify) > .form-control {
        width: auto;
    }

    /* Client systems: a table six columns wide put Edit, Revoke and Remove
       past the right edge of the phone, behind a sideways scroll. Below md
       each system is a card of labelled lines with its buttons at the foot. */
    .table-stack,
    .table-stack tbody,
    .table-stack tbody tr:not(.collapse),
    .table-stack tbody tr.collapse.show,
    .table-stack tbody th,
    .table-stack tbody td {
        display: block;
        width: 100%;
    }
    .table-stack thead {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
    }
    .table-stack tbody tr:not(.collapse) {
        border-top: 2px solid #dee2e6;
        padding: 0.5rem 0;
    }
    .table-stack tbody tr:first-child {
        border-top: 0;
    }
    .table-stack tbody th,
    .table-stack tbody td {
        border-top: 0;
        padding: 0.25rem 0;
        text-align: left !important; /* over text-center / text-right */
        white-space: normal !important; /* over text-nowrap */
        overflow-wrap: anywhere;
    }
    .table-stack [data-label]::before {
        content: attr(data-label);
        display: block;
        font-size: 0.75rem;
        font-weight: 600;
        color: #495057; /* 8.2:1 on white */
    }
    .table-stack .table-actions {
        display: flex;
        flex-wrap: wrap;
        gap: 0.5rem;
        padding-top: 0.5rem;
    }
    .table-stack code {
        word-break: break-all;
    }
}

/* Below sm: the main action of a form, and the buttons that stand alone,
   span the phone - one large target where the thumb is, not a small one at
   the left edge with a link squeezed beside it. */
@media (max-width: 575.98px) {
    .btn-phone-block {
        display: block;
        width: 100%;
        white-space: normal; /* a long label wraps inside the card, not past it */
    }
    .btn-phone-block + .btn-phone-block {
        margin-top: 0.5rem;
    }
    .admin-stats .btn {
        width: 100%;
    }

    /* A contact section's header, rows and footer 12px in from its edge
       rather than 20px: at 320px a row's channel and Send code need the
       room. All four move together, so the icon, the values and the Add
       still start on one left edge. */
    .contact-section > .card-header,
    .contact-section > .card-body,
    .contact-section > .list-group > .list-group-item,
    .contact-section > .card-footer {
        padding-left: 0.75rem;
        padding-right: 0.75rem;
    }
}
