/*
 * SyncroHealth accessibility layer.
 *
 * Loaded after the vendored Bootstrap theme, which is not ours to restructure.
 * Everything here overrides a specific measured failure rather than restyling
 * the product: each rule below names the ratio or size it corrects and what it
 * was before.
 *
 * Measured in a real browser at 1440x900 and 375x812, logged in as each role.
 * The previous audit scored accessibility 4/4 from static analysis of the
 * templates and said plainly that no page had been opened; opening them gives
 * 1/4. Both numbers were honest about their method - this file closes the gap
 * between them.
 *
 * Contrast values were solved rather than eyeballed: each replacement walks
 * lightness in HLS until it clears the WCAG target, so the hue and saturation
 * that carry the brand survive untouched.
 */

/* --------------------------------------------------------------------------
 * 1. Focus visibility.  WCAG 2.4.7 (AA).
 *
 * The single worst finding of the audit. On the booking page 30 of 40
 * focusable elements produced no computed style change at all when focused;
 * on the patient dashboard, 9 of 17. A keyboard user cannot see where they
 * are, which on a page whose controls include "Book Appointment" and
 * "Emergency help" is not a cosmetic problem.
 *
 * Two rings rather than one: the inner teal carries the brand, the outer white
 * keeps it visible on the teal sidebar and the amber buttons, where a single
 * brand-coloured ring would disappear into its own background.
 * ------------------------------------------------------------------------ */

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--sh-brand, #1dbfc1) !important;
  outline-offset: 2px !important;
  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.9) !important;
  border-radius: 2px;
}

/* On the teal sidebar the white ring leads and the dark ring follows, so the
 * pair stays legible against the brand colour itself. */
.sidebar :where(a, button):focus-visible,
[class*="bg-primary"] :where(a, button):focus-visible {
  outline-color: #ffffff !important;
  box-shadow: 0 0 0 4px rgba(19, 123, 124, 0.9) !important;
}

/* The theme sets `outline: 0` on several controls. Losing focus entirely is
 * never the right trade, so this re-asserts it for keyboard users only -
 * :focus-visible leaves mouse clicks unringed, which is why the theme's
 * authors reached for `outline: 0` in the first place. */
:where(a, button, .btn, .nav-link):focus:not(:focus-visible) {
  outline: none;
}

/* --------------------------------------------------------------------------
 * 2. Contrast.  WCAG 1.4.3 (AA).
 * ------------------------------------------------------------------------ */

/* Specificity note, because it cost a debugging cycle. The theme scopes its
 * colour utilities under a theme class - `.theme-success .text-primary` - at
 * two-class specificity with !important. A single-class override here loses to
 * that no matter how late it loads, which is exactly what happened on the
 * first attempt: `.text-primary` was declared, the browser kept resolving the
 * name to rgb(29,191,193), and only inspecting the cascade showed why.
 *
 * `body[class*="theme-"]` matches whichever of the theme's colour schemes is
 * active without naming them, and clears the theme's specificity rather than
 * tying this file to one skin. */

/* White on the amber call-to-action measured 1.93:1 against a required 4.5.
 * Amber is a light colour; white text on it was the wrong way round from the
 * start. Darkening the amber to carry white would have cost the brand, so the
 * text goes dark instead and the amber is untouched: 8.74:1, and the button
 * still reads as the same button. This is the primary action on the booking
 * page, repeated once per doctor card. */
body[class*="theme-"] .btn-warning,
body[class*="theme-"] .btn-warning:hover,
body[class*="theme-"] .btn-warning:focus,
body[class*="theme-"] .bg-warning,
.btn-warning,
.btn-warning:hover,
.btn-warning:focus,
.bg-warning {
  color: #2b1900 !important;
}

/* The signed-in user's own name, teal on the pale panel, measured 2.07:1. It
 * appears in the header of every page in the application. The teal stays the
 * brand teal everywhere it is a fill; only as text on a light surface does it
 * darken, to 4.61:1. */
body[class*="theme-"] .text-primary,
.text-primary,
a.text-primary,
p.text-primary {
  color: #137b7c !important;
}

/* `.text-fade` measured 3.79:1 on white. It carries the doctor's specialty on
 * every card of the booking page - 34 elements there alone - which is the one
 * line a patient reads to decide who to book. The cool cast is kept and only
 * the lightness moves, so it still recedes from the name above it. */
body[class*="theme-"] .text-fade,
.text-fade {
  color: #70758e !important;
}

/* Muted labels measured 3.60:1 at 10px - below the floor and at the smallest
 * size in the interface, which is the combination that actually loses people. */
body[class*="theme-"] .text-mute,
body[class*="theme-"] .text-muted,
.text-mute,
.text-muted,
small.text-mute {
  color: #6f6f6f !important;
}

/* The danger red measured 4.03:1 both as text on white and as a button
 * background under white text. It is used for vital-sign alerts, so it is the
 * last colour in the product that should be hard to read. */
body[class*="theme-"] .text-danger,
.text-danger {
  color: #e8133f !important;
}

/* :not(.btn-outline) because an outline button is defined by *not* having a
 * fill, so an !important background on the base class destroys it. On
 * /tabDashboard/ this filled ".btn-outline.btn-danger" with #e8133f while the
 * label stayed #ee3158 - red text on red, 1.13:1, a "Complete Appointment"
 * control nobody could see.
 *
 * Third time this layer has made that mistake: .btn-primary lost its white
 * label the same way, and the nav rules had to exclude .btn for the same
 * reason. An override that sets a background has to name the variants that
 * exist because they have none. */
body[class*="theme-"] .btn-danger:not(.btn-outline),
body[class*="theme-"] .bg-danger:not(.btn-outline),
.btn-danger:not(.btn-outline),
.bg-danger:not(.btn-outline) {
  background-color: #e8133f !important;
  color: #fff !important;
}

/* The outline variant: the same red as text, on the surface it sits on. */
body[class*="theme-"] .btn-outline.btn-danger,
.btn-outline.btn-danger {
  background-color: transparent !important;
  color: #d5123b !important;          /* 4.54:1 on white */
  border-color: currentColor;
}

/* White on the brand teal measured 2.26:1 as a button background - the
 * "Doctor Details" action, once per doctor card, fourteen times on the booking
 * page. The teal is bright enough that white sits on top of it rather than
 * against it.
 *
 * The button darkens rather than the label. Near-black text on a bright teal
 * primary button would read as a warning, not a primary action, and it would
 * contradict the amber button two lines up, where the label darkened because
 * amber is a *light* colour. The rule stays consistent: light surfaces take
 * dark text, saturated surfaces darken until white sits on them.
 *
 * It reuses the same deep teal as .text-primary above. One deep-brand value
 * doing both jobs is a palette; two near-identical teals is an accident. */
body[class*="theme-"] .btn-primary,
body[class*="theme-"] .bg-primary,
.btn-primary,
.bg-primary {
  background-color: var(--sh-brand-deep-accessible, #137b7c) !important;
  border-color: var(--sh-brand-deep-accessible, #137b7c) !important;
}

/* The label has to be pinned with the surface. The first version of this rule
 * set only the background, on the assumption that a primary button already
 * carried white text - and on most pages it did. On the marketing landing page
 * it does not: .btn-primary there inherits the navy #172b4c, which against this
 * teal measures 2.79:1. The override had *created* that failure, by moving one
 * half of a pair the theme had matched.
 *
 * Contrast is a property of two colours. Setting one of them and inheriting the
 * other is not an override, it is a coin toss against every stylesheet that
 * loads before this one. */
body[class*="theme-"] .btn-primary,
.btn-primary {
  color: #fff !important;
}

body[class*="theme-"] .btn-primary:hover,
.btn-primary:hover,
.btn-primary:focus {
  background-color: #0f6667 !important;
  border-color: #0f6667 !important;
}

/* The login page, which is the most visited surface in the product and was not
 * covered by the first pass at all - it is one of the 37 page roots that never
 * linked this layer.
 *
 * "SIGN IN" is .btn-info: white on #00d0ff, 1.83:1. The cyan is bright enough
 * that the label floats on it. Same treatment as the teal - darken the surface
 * until white sits on it, hue held. */
body[class*="theme-"] .btn-info,
.btn-info,
.bg-info {
  background-color: #00809d !important;
  border-color: #00809d !important;
}

.btn-info:hover,
.btn-info:focus {
  background-color: #006b83 !important;
  border-color: #006b83 !important;
}

/* The selected "Login" / "Register" tab: white on the brand teal, 2.26:1, the
 * same failure as the primary button and the same fix. */
.nav-link.active,
.nav-pills .nav-link.active,
body[class*="theme-"] .nav-link.active {
  background-color: var(--sh-brand-deep-accessible, #137b7c) !important;
}

/* `.text-success` and `.btn-success` are the brand teal again under another
 * name - the theme uses "success" for the brand rather than for a state. Both
 * measured 2.26:1 on the password-recovery page, as heading and as the submit
 * button. Same colour, same failure, same fix. */
body[class*="theme-"] .text-success,
.text-success {
  color: var(--sh-brand-deep-accessible, #137b7c) !important;
}

body[class*="theme-"] .btn-success,
body[class*="theme-"] .bg-success,
.btn-success,
.bg-success {
  background-color: var(--sh-brand-deep-accessible, #137b7c) !important;
  border-color: var(--sh-brand-deep-accessible, #137b7c) !important;
}

/* `.btn-danger-light` is an outline button: the danger red as *text* on the
 * page background rather than as a fill. It is the "Add" control on the device
 * page.
 *
 * A step darker than .text-danger, and the reason is worth recording. #e8133f
 * was solved against white and clears it at 4.57:1, but this control sits on
 * the pale panel #f1f5f8, where the same red gives 4.17:1 and fails. The
 * background a colour is solved against is part of the answer, not a detail -
 * "4.5:1" alone means nothing. #dd123c clears both: 4.54:1 on the panel,
 * 4.98:1 on white. */
body[class*="theme-"] .btn-danger-light,
.btn-danger-light,
.btn-outline.btn-danger-light {
  color: #dd123c !important;
}

/* --------------------------------------------------------------------------
 * 3. Touch targets.  WCAG 2.5.8 (AA, 24px) and the 44px comfort target.
 *
 * The booking page had 54 of 86 interactive elements under 44x44, including
 * every "Book Appointment" button at 161x39 and every "Add Device" link at
 * 72x22. Scoped to real controls: forcing 44px on inline text links would
 * break paragraph flow and help nobody.
 * ------------------------------------------------------------------------ */

.btn,
button:not(.close):not(.navbar-toggler),
input[type="submit"],
input[type="button"],
.page-link {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Text entry fields were missed by the first pass, which listed only the two
 * input types that are buttons. The theme renders .form-control at 37px, so
 * every search box, every date field and every login field on the site is a
 * 37px target - under WCAG 2.5.8's 24px floor once the border is discounted on
 * touch, and awkward for anyone with a tremor at any size.
 *
 * Checkboxes and radios are excluded deliberately: stretching the control
 * itself distorts the glyph. Their hit area belongs to the <label>, which is
 * the accessible fix, and is a separate change from this one. */
input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="range"]),
select,
textarea:not([rows]) {
  min-height: 44px;
}

/* The extra-small button variant is the one the theme uses inside cards and
 * table rows. It keeps its compact typography and gains the height. */
.btn-xs,
.btn-sm {
  min-height: 44px;
  padding-top: 0.35rem;
  padding-bottom: 0.35rem;
}

/* Icon-only controls need width as well as height, or they stay 22px wide. */
.btn:has(> i:only-child),
button:has(> i:only-child) {
  min-width: 44px;
}

/* The theme's nav toggle is built from bare <span> bars rather than an icon
 * font, so the :has(> i) rule above never matched it and it stayed 14px wide
 * while gaining the 44px height - a target twice as tall as it is wide. It is
 * the control that opens the entire menu on a phone. */
.toggle-bar,
.core-nav-toggle {
  min-width: 44px;
  justify-content: center;
}

/* An inline anchor wrapping an image reports the height of its line box, not
 * of the image inside it - 18px for a 200px photo. The image stays clickable,
 * so this is partly a measurement artefact, but a box that does not describe
 * its own contents also breaks hit-testing at the edges and any later attempt
 * to measure this page. Making it a block costs nothing visually. */
a:has(> img:only-child) {
  display: block;
}

/* --------------------------------------------------------------------------
 * 4. Browser surfaces.
 *
 * Selection, caret and scrollbar ship with defaults that belong to no design
 * system. Theming them costs four rules and is the difference between a page
 * that was assembled and one that was built.
 * ------------------------------------------------------------------------ */

::selection {
  background: rgba(29, 191, 193, 0.25);
  color: #10312f;
}

:where(input, textarea, [contenteditable]) {
  caret-color: var(--sh-brand, #1dbfc1);
}

* {
  scrollbar-width: thin;
  scrollbar-color: #b9c6cc transparent;
}

*::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

*::-webkit-scrollbar-thumb {
  background: #b9c6cc;
  border-radius: 6px;
  border: 2px solid transparent;
  background-clip: content-box;
}

*::-webkit-scrollbar-thumb:hover {
  background: #8fa3ac;
  background-clip: content-box;
}

/* Clinical numbers line up. Vital signs, doses, dates and appointment times
 * are read in columns and compared down the column, which proportional
 * numerals actively fight: a 1 is narrower than a 7, so the digits drift out
 * of alignment row to row. This is a readability fix for the data this
 * product exists to show, not a typographic flourish. */
:where(table, .table) :where(td, th),
.vital-value,
time,
.badge {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* --------------------------------------------------------------------------
 * 5. Empty states.
 *
 * 13 of 17 active doctors carry the literal string "Specialization" in the
 * field meant to hold their specialty, and the booking page renders it to
 * patients as though it were one. The data needs correcting separately; this
 * at least stops an unfilled field from masquerading as a filled one.
 * ------------------------------------------------------------------------ */

.sh-unset {
  color: #6f6f6f;
  font-style: italic;
}

/* --------------------------------------------------------------------------
 * 6. Motion.
 *
 * The reduced-motion block already in tokens.css handles the global case.
 * Focus rings are exempt from it deliberately: a user who has asked for less
 * motion has not asked to lose the one indicator that says where they are.
 * ------------------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  :where(a, button, input, select, textarea, [tabindex]):focus-visible {
    transition: none !important;
  }
}
