/* ============================================================
 * VoteRite — Accessibility overrides for low-vision voters
 * Loaded last so it overrides earlier styles. Plain CSS, no
 * build step required.
 *
 * Goals:
 *   - Every selectable row has a ≥ 44 × 44 CSS-px hit-target
 *     (WCAG 2.5.5 Target Size — Level AAA).
 *   - Visible focus indicator on the *visible* control
 *     even though the native input is hidden by the
 *     framework's Material checkbox/radio styling.
 *   - Unmistakable checked state: filled box + thick check
 *     glyph + row tint + bold label.
 *   - Honors the existing high-contrast themes
 *     (theme-black / theme-white / theme-yellowblue).
 * ============================================================ */

/* ---- 1. Row-level hit-target ---- */

.md-checkbox,
.md-radio {
    position: relative;
    min-height: 56px;
    padding: 6px 0 6px 48px;
    margin: 6px 0;
    border-radius: 8px;
    transition: background-color .15s ease, box-shadow .15s ease;
    /* Stop the tinted "selected" background from bleeding past the visible
     * card edge when a parent row uses Bootstrap negative-margins together
     * with an inline margin-left (e.g. review.blade.php has
     * .form-group.row style="margin-left:25px"). */
    max-width: 100%;
    box-sizing: border-box;
    overflow: hidden;
}

/* Neutralise Bootstrap's .row negative-right margin inside the voter forms.
 * On the review page nested .form-group.row elements stacked their −15 px
 * right margins together, so the candidate row pushed 15–30 px past the
 * card edge — visible as the tinted background bleeding past the right
 * border. Constraining the right margin to 0 inside the voter form keeps
 * everything inside the card.
 *
 * Scoped to .race-voter / .ballot-voter forms so we don't disturb other
 * uses of .form-group.row elsewhere in the app. */
.race-voter .form-group.row,
.ballot-voter .form-group.row {
    margin-right: 0 !important;
}
.race-voter .md-checkbox,
.race-voter .md-radio,
.ballot-voter .md-checkbox,
.ballot-voter .md-radio {
    padding-right: 12px;
}

/* The label becomes the full row, so the user can tap anywhere
 * along the candidate name — not just on the 23-px box icon. */
.md-checkbox label,
.md-radio label {
    display: flex;
    align-items: center;
    min-height: 44px;
    width: 100%;
    padding: 10px 12px 10px 0;
    margin: 0;
    cursor: pointer;
    font-size: 18px;
    line-height: 1.4;
    user-select: none;
    -webkit-tap-highlight-color: rgba(34, 64, 124, .15);
    touch-action: manipulation; /* eliminates 300 ms tap delay on mobile Safari */
}

/* ---- 2. Larger box / check ---- */

.md-checkbox label > .box,
.md-radio label > .box {
    /* The framework places .box at top:0 left:0 absolutely.
     * Move it inside the new row padding and enlarge. */
    top: 50% !important;
    left: 8px !important;
    transform: translateY(-50%) !important;
    width: 32px !important;
    height: 32px !important;
    border-width: 3px !important;
}

.md-checkbox label > .check,
.md-radio label > .check {
    /* Center the inner indicator inside the larger box.
     * Box is left:8px width:32px → its horizontal centre is at 24px.
     * translate(-50%, -50%) then anchors the .check around that point. */
    top: 50% !important;
    left: 24px !important;
    transform: translate(-50%, -50%) !important;
    width: 16px !important;
    height: 16px !important;
    border-radius: 4px !important;
    margin: 0 !important;
}

/* ---- 3. Visible focus ring ---- */

/* Native input is visually hidden by the framework, but it is the
 * element the keyboard focuses on. Project the focus ring onto the
 * outer .md-checkbox / .md-radio row so AT users can see it. */
.md-checkbox:focus-within,
.md-radio:focus-within {
    outline: 3px solid #005fcc;
    outline-offset: 2px;
    background-color: rgba(0, 95, 204, .06);
}

/* Remove the global *:focus outline from the hidden native input
 * (it would draw an invisible rectangle at 0 × 0). */
.md-check:focus,
.md-radiobtn:focus {
    outline: none !important;
}

/* ---- 4. Checked / confirmed state ---- */

.md-checkbox input[type="checkbox"]:checked ~ label,
.md-radio input[type="radio"]:checked ~ label {
    font-weight: 600;
}

.md-checkbox input[type="checkbox"]:checked,
.md-radio input[type="radio"]:checked {
    /* Highlight the parent row so the confirmation reads at a glance. */
}

.md-checkbox:has(input[type="checkbox"]:checked),
.md-radio:has(input[type="radio"]:checked) {
    background-color: rgba(69, 182, 175, .15);
    box-shadow: inset 4px 0 0 0 #45b6af;
}

/* Fallback for browsers without :has() — at least keep the bold label. */
.md-checkbox input[type="checkbox"]:checked ~ label::before,
.md-radio input[type="radio"]:checked ~ label::before {
    content: "";
}

/* Make the inner check / dot fully opaque + a touch larger when checked. */
.md-checkbox input[type="checkbox"]:checked ~ label > .check,
.md-radio input[type="radio"]:checked ~ label > .check {
    opacity: 1 !important;
    width: 18px !important;
    height: 18px !important;
}

/* ---- 5. Active / pressed feedback ---- */

.md-checkbox label:active,
.md-radio label:active {
    background-color: rgba(34, 64, 124, .08);
    border-radius: 8px;
}

/* ---- 6. Larger action buttons ----
 *
 * 44 × 44 CSS-px is the WCAG 2.5.5 AAA minimum. We deliberately do NOT add
 * extra vertical padding here: the framework's existing height/line-height
 * already render the visible button, and adding padding would extend the
 * click area beyond the visible edge — which in turn collides with the
 * absolute-positioned footer on shorter pages (ballot, mode, lang).
 *
 * The result: clickable area === visible area, mouse cursor matches the
 * button outline exactly. */
.btn-voter,
.btn-voter-back,
.btn-voter-else,
.btn-skip,
.btn-review,
.nextButton,
.nextBtn {
    min-height: 44px !important;
    min-width: 120px !important;
    font-size: 17px !important;
    line-height: 1.3 !important;
    touch-action: manipulation;
    box-sizing: border-box;
}

.btn-voter:focus,
.btn-voter-back:focus,
.btn-voter-else:focus,
.btn-skip:focus,
.btn-review:focus,
.nextButton:focus,
.nextBtn:focus {
    outline: 3px solid #ffbf47 !important;
    outline-offset: 3px !important;
}

/* Reserve space at the bottom of every client page so the action buttons
 * never sit behind layouts/footer.blade.php (which is position: absolute;
 * bottom: 0). The amount scales with the viewport:
 *   • desktop: 160 px clears the two footer rows + the red divider
 *   • phone: clamp drops to ~120 px so we don't waste 30 % of a short screen
 *   • iOS: add safe-area-inset-bottom so the buttons clear the home indicator
 *
 * Locking min-height to 100vh on the body keeps the absolute footer in a
 * stable position from the very first paint — without this, the page used
 * to be a few hundred px tall during HTML parse, then jumped to full height
 * once the inline jQuery height calculation ran (the "layout not applied
 * in time" flash). */
html, body.page-header-fixed {
    min-height: 100vh;
}

body.page-header-fixed main#main-content {
    padding-bottom: calc(clamp(120px, 18vh, 200px) + env(safe-area-inset-bottom, 0px));
}

/* Mobile fine-tuning: tighten the row hit-target padding so two long
 * candidate names still fit comfortably on a 360 px screen.
 *
 * Also resolves the overlap between the fixed accessibility buttons
 * (#helpBtn, #accessibilityBtn, #speechToggleBtn, #moveToTranslation)
 * and the Back / Next action buttons. On desktop the floating buttons
 * sit clearly to the right of the centered content, but on a narrow
 * phone they covered the Next button. The fix:
 *   • shrink the floating buttons from 55 → 44 px (still WCAG 2.5.5)
 *   • move them tighter against the edge (20 → 10 px)
 *   • reserve right-side padding on the content so it never sits
 *     beneath the floating column
 *   • allow the Back / Next row to wrap and add a real gap. */
@media (max-width: 600px) {
    .md-checkbox,
    .md-radio {
        min-height: 52px;
        padding-left: 44px;
    }
    .md-checkbox label,
    .md-radio label {
        font-size: 17px;
    }
    .md-checkbox label > .box,
    .md-radio label > .box {
        left: 6px !important;
        width: 28px !important;
        height: 28px !important;
    }
    .md-checkbox label > .check,
    .md-radio label > .check {
        left: 20px !important;
        width: 14px !important;
        height: 14px !important;
    }
    .md-checkbox input[type="checkbox"]:checked ~ label > .check,
    .md-radio input[type="radio"]:checked ~ label > .check {
        width: 16px !important;
        height: 16px !important;
    }

    /* Smaller floating accessibility buttons on phones. */
    #helpBtn,
    #accessibilityBtn,
    #speechToggleBtn,
    #moveToTranslation,
    #reloadPage {
        width: 44px !important;
        height: 44px !important;
        right: 10px !important;
        font-size: 28px !important;
    }
    #helpBtn i,
    #accessibilityBtn i,
    #speechToggleBtn i,
    #moveToTranslation i,
    #reloadPage i {
        font-size: 22px !important;
    }
    #helpBtn        { bottom: calc(10px + env(safe-area-inset-bottom, 0px)); }
    #accessibilityBtn { bottom: calc(64px + env(safe-area-inset-bottom, 0px)); }
    #speechToggleBtn  { bottom: calc(118px + env(safe-area-inset-bottom, 0px)); }
    #moveToTranslation, #reloadPage { bottom: calc(172px + env(safe-area-inset-bottom, 0px)); }

    /* Keep the content card centred — no asymmetric page-level padding.
     * The floating accessibility column above is now only 54 px wide
     * (44 px button + 10 px gutter), and the action-button rows below
     * are kept centred with their own gap so they don't drift into the
     * floating buttons' lane. */

    /* Back / Next row: real gap, allow wrap so they never overlap, and
     * leave room on the right so the rightmost button can't sit under
     * the floating accessibility column. The row stays centred. */
    .col-md-12.form-actions,
    .btnMobile,
    .col-md-12[style*="display: flex"] {
        gap: 12px !important;
        flex-wrap: wrap !important;
        row-gap: 12px !important;
        padding-right: 54px !important;  /* clears the floating column */
        padding-left: 54px !important;   /* mirror so the row stays centred */
        justify-content: center !important;
    }
    .btn-voter,
    .btn-voter-back,
    .btn-voter-else,
    .nextButton,
    .nextBtn {
        margin-left: 6px !important;
        margin-right: 6px !important;
    }

    #a11y-live-announcer {
        bottom: calc(16px + env(safe-area-inset-bottom, 0px));
        font-size: 16px;
        padding: 8px 16px;
    }

    /* Speech-rate slider on mode.blade.php. Inline styles on the markup
     * set min-width: 240px on the range input and min-width: 90px on the
     * "Speech Rate" label, which pushes the row past the right edge of
     * the card on a phone. Drop the inline mins, stack the container as
     * label → slider → test-button, and let the range take the full
     * width available inside the card. */
    .speech-rate-container {
        flex-direction: column !important;
        align-items: stretch !important;
        gap: 10px !important;
        margin-top: 24px !important;
    }
    .speech-rate-container > span,
    .speech-rate-container > div {
        min-width: 0 !important;
        width: 100% !important;
    }
    .speech-rate-container input[type="range"],
    .speech-rate-container .speedInputW {
        min-width: 0 !important;
        width: 100% !important;
        max-width: 100% !important;
        box-sizing: border-box;
    }
    .speech-rate-container .mangeUnderSpeed {
        width: 100%;
    }
    .speech-rate-container .speachtestBTN {
        align-self: flex-start;
        padding-right: 28px !important;
    }
}

/* Very narrow phones (<= 360 px): force Back / Next to share one row by
 * shrinking the minimum width, so they stay side-by-side instead of one
 * wrapping onto its own line. */
@media (max-width: 360px) {
    .btn-voter,
    .btn-voter-back,
    .nextButton,
    .nextBtn {
        min-width: 96px !important;
        padding: 8px 12px !important;
        font-size: 16px !important;
    }
}

/* Tablet (601 – 950 px): the card is full-width or near full-width and the
 * fixed accessibility column on the right still overlaps content that flows
 * to the bottom-right corner (Cancel Ballot, etc.). Mirror the mobile rule
 * so the action-button row clears the column, but keep the standard mobile
 * row-tightening (smaller buttons, stacked layout) off. */
@media (min-width: 601px) and (max-width: 950px) {
    .col-md-12.form-actions,
    .btnMobile,
    .col-md-12[style*="display: flex"] {
        padding-right: 70px !important;
        padding-left: 70px !important;
        gap: 12px !important;
        flex-wrap: wrap !important;
    }
}

/* ---- 7. aria-live confirmation banner ---- */

#a11y-live-announcer {
    position: fixed;
    left: 50%;
    bottom: 24px;
    transform: translateX(-50%);
    max-width: 90vw;
    min-width: 220px;
    padding: 10px 22px;
    background: #22407c;
    color: #fff;
    font-size: 18px;
    font-weight: 600;
    border-radius: 24px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .25);
    z-index: 99998;
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s ease;
    text-align: center;
}

#a11y-live-announcer.visible {
    opacity: 1;
}

/* Visually hidden but still announced by assistive technology. */
.sr-only {
    position: absolute !important;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ---- 8. Reduce visual clutter on the ballot for low vision ---- */

/* Tighten very tight rows so successive options don't overlap on small screens. */
.form-group.row {
    margin-bottom: 4px !important;
}

/* Increase contrast of the small candidate / party thumbnails: nothing
 * functional rests on them, so give them a subtle border so they stop
 * blending into the page background. */
.md-checkbox + div img.img-circle,
.md-radio + div img.img-circle {
    border: 1px solid rgba(34, 64, 124, .25);
    background: #fff;
}

/* ---- 9. Theme overrides — keep checked-row tint readable ---- */

body.theme-black .md-checkbox:has(input:checked),
body.theme-black .md-radio:has(input:checked) {
    background-color: rgba(255, 255, 255, .15);
    box-shadow: inset 4px 0 0 0 #ffffff;
}

body.theme-white .md-checkbox:has(input:checked),
body.theme-white .md-radio:has(input:checked) {
    background-color: rgba(0, 0, 0, .08);
    box-shadow: inset 4px 0 0 0 #000000;
}

body.theme-yellowblue .md-checkbox:has(input:checked),
body.theme-yellowblue .md-radio:has(input:checked) {
    background-color: rgba(255, 255, 0, .18);
    box-shadow: inset 4px 0 0 0 #ffff00;
}

/* ---- 10. Special / Visually-Impaired focused-row override ----
 * The original race.blade.php uses .special-focused to amber-ring the
 * currently-cycled option. Keep it but make the whole row glow, not
 * just the small box icon. */
body.special-mode-active .form-group.row.special-focused:not(.special-selected) {
    background-color: rgba(245, 166, 35, .18);
    box-shadow: inset 0 0 0 3px #f5a623;
    border-radius: 10px;
}

/* ---- 11. Special-mode click isolation ----
 * In visually-impaired mode the voter interacts exclusively through the
 * mouse-gesture protocol (left = cycle, double-left = re-read, right =
 * next, double-right = back). Direct clicks on options or action buttons
 * are intentionally inert so a stray click can never fight or override
 * the gesture. The gesture handlers themselves drive everything via
 * programmatic clicks / .checked assignments, which bypass pointer-events
 * because they aren't user-generated events.
 *
 * Gated on body.special-mode-active — set ONLY by pages whose script
 * actually attaches a gesture handler (ballot, lang, mode, race). Pages
 * without a gesture handler (prop, review) intentionally don't set the
 * class so their YES/NO clicks still work even in special mode.
 *
 * Floating accessibility controls (mute, settings, help, translate) are
 * deliberately EXEMPT so the voter can always silence speech or open
 * help even while in special mode.
 */
body.special-mode-active .md-checkbox,
body.special-mode-active .md-radio,
body.special-mode-active .md-checkbox *,
body.special-mode-active .md-radio *,
body.special-mode-active .btn-voter,
body.special-mode-active .btn-voter-back,
body.special-mode-active .btn-voter-else,
body.special-mode-active .btn-skip,
body.special-mode-active .btn-review,
body.special-mode-active .btn-back,
body.special-mode-active .btn-next,
body.special-mode-active .nextButton,
body.special-mode-active .nextBtn,
body.special-mode-active form.race-voter input.spinner-input,
body.special-mode-active .spinner-up,
body.special-mode-active .spinner-down {
    pointer-events: none !important;
}

/* Floating accessibility column stays interactive in special mode. */
body.special-mode-active #speechToggleBtn,
body.special-mode-active #accessibilityBtn,
body.special-mode-active #helpBtn,
body.special-mode-active #moveToTranslation,
body.special-mode-active #reloadPage,
body.special-mode-active #accessibilityModal,
body.special-mode-active #accessibilityModal *,
body.special-mode-active #helpModal,
body.special-mode-active #helpModal * {
    pointer-events: auto !important;
}

/* ---- 11. Reduced motion preference ---- */

@media (prefers-reduced-motion: reduce) {
    .md-checkbox,
    .md-radio,
    .md-checkbox label,
    .md-radio label,
    #a11y-live-announcer {
        transition: none !important;
    }
}
