/* ========================================
   Component Styles
   MGH ED Patient Portal
   ======================================== */

/* ========================================
   Header
   ======================================== */

.site-header {
  padding-top: var(--space-sm);
  padding-bottom: var(--space-xs);
  background-color: var(--bg);
  border-bottom: 1px solid var(--glass-border);
  box-shadow: var(--glass-inner-glow);
  /* Positioning lives on .ios-top-bar in ios.css (position: sticky,
     z-index: 100). Declaring position/z-index here too would silently
     depend on stylesheet order to resolve the conflict. */
}

/* Removed: .header-row, .header-group, .site-title. The iOS top bar replaced
   that header structure; no element carries these classes on any tab (the page
   title is `<p class="sr-only" id="site-title">`, an id, not this class). */

.header-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--min-touch-target);
  height: var(--min-touch-target);
  border: none;
  background: none;
  cursor: pointer;
  color: var(--text);
  border-radius: var(--border-radius-sm);
  transition: background-color var(--transition-fast);
  flex-shrink: 0;
}

.header-btn:hover {
  background-color: var(--glass-bg-medium);
}

.header-btn:focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-offset);
}

.header-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.header-icon {
  width: var(--icon-size);
  height: var(--icon-size);
}

/* Font Size Popover - inline horizontal control inside the gear menu.
   Wrapped in `.ios-gear-menu` to outrank any earlier absolute-positioned
   variants that may live elsewhere in the cascade. */
/* Removed: .font-size-wrapper - no element carries it; the font-size popover
   now lives directly inside the gear menu. */

.ios-gear-menu .font-size-popover {
  position: static;
  transform: none;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-xs);
  width: 100%;
  padding: var(--space-xs);
  background-color: var(--ios-bg-nested, var(--bg-surface));
  border: 1px solid var(--ios-border, var(--border));
  border-radius: var(--border-radius-sm);
  box-shadow: none;
  min-height: 52px;
  z-index: auto;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

.font-size-popover[hidden] {
  display: none;
}

.ios-gear-menu .font-size-step {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: none;
  background: none;
  cursor: pointer;
  color: var(--text);
  font-size: 1.75rem;
  font-weight: 300;
  border-radius: 50%;
  transition: background-color var(--transition-fast);
  line-height: 1;
  flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
}

.ios-gear-menu .font-size-step:hover {
  background-color: var(--border);
}

.ios-gear-menu .font-size-step:active {
  background-color: var(--border);
}

.ios-gear-menu .font-size-step:focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-offset);
}

.ios-gear-menu .font-size-step:disabled {
  opacity: 0.25;
  cursor: not-allowed;
}

.ios-gear-menu .font-size-divider {
  width: 1px;
  height: 28px;
  background-color: var(--border);
  flex-shrink: 0;
}

.ios-gear-menu .font-size-track {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 18px;
  flex: 1;
  padding: 0;
}

.ios-gear-menu .font-size-dot {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid var(--text-muted);
  background: transparent;
  transition: background-color var(--transition-fast), border-color var(--transition-fast), transform var(--transition-fast);
}

.font-size-dot.active {
  /* Dark brand green, not lime: the active dot is a non-text state
     indicator and needs 3:1 against the surface (lime is ~1.3:1). */
  background-color: var(--brand-secondary);
  border-color: var(--brand-secondary);
  transform: scale(1.15);
}

/* Language Selector */
/* Removed: .language-wrapper class rules. The element is
   `<div id="language-wrapper" class="sr-only">` - translate.js finds it by id,
   and .sr-only does the hiding. Nothing ever carried the class. */

.language-select {
  width: var(--min-touch-target);
  height: var(--min-touch-target);
  border: none;
  background-color: transparent;
  cursor: pointer;
  color: transparent;
  border-radius: var(--border-radius-sm);
  transition: background-color var(--transition-fast);
  font-size: 0;
  padding: 0;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231A1A1A' stroke-width='2'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cline x1='2' y1='12' x2='22' y2='12'/%3E%3Cpath d='M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: var(--icon-size);
}

[data-theme="dark"] .language-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23E5E5E5' stroke-width='2'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cline x1='2' y1='12' x2='22' y2='12'/%3E%3Cpath d='M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z'/%3E%3C/svg%3E");
}

.language-select:hover {
  background-color: var(--bg-surface);
}

.language-select:focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-offset);
}

/* Translate Disclaimer Banner */
.translate-disclaimer {
  /* Pinned to the top, above the header/content but below the map overlay
     (z 1000) so the map still covers it when open - as it did before. During a
     page transition it is raised above the sliding ghost (see the
     html[data-page-transition] rule in ios.css) so the pages slide UNDER it
     instead of the banner being cloned, hidden, and flashed back - the flicker
     this fixes. Fixed (not in flow), so the top bar's padding-top reserves its
     height; centred to the app column like the header. */
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 500;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  max-width: var(--max-width);
  margin: 0 auto;
  padding: var(--space-sm);
  background-color: var(--section-yellow);
  border-bottom: 1px solid var(--section-yellow-end);
}

.translate-disclaimer[hidden] {
  display: none;
}

.translate-disclaimer-message {
  margin-bottom: 0;
  font-size: var(--font-size-sm);
  color: var(--text);
}

.translate-restore-btn {
  border: 1px solid var(--border);
  background-color: var(--bg);
  color: var(--text);
  border-radius: var(--border-radius-sm);
  min-height: var(--min-touch-target);
  padding: 0 var(--space-sm);
  font: inherit;
  font-size: var(--font-size-sm);
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
}

/* Hide Google Translate's own UI elements */
.goog-te-banner-frame,
.goog-te-menu-frame,
#goog-gt-tt,
.goog-te-balloon-frame {
  display: none !important;
}

/* Google Translate parks its loading spinner offscreen (position: fixed at
   -1000, -1000) but leaves the animation running for the life of the page.
   The spinner-dash keyframes animate stroke-dasharray, which is a layout
   property on SVG, so an invisible element costs a style recalc plus a
   layout on every frame, forever - measured at 60 layouts/second while the
   page sits idle. That competes with map gestures for frame budget on
   exactly the low-end phones this site is built for. Stop the animation but
   keep the element, so Google can still position and show it mid-translate
   (as a static ring). Class names are Google's obfuscated ones: if they
   change, the rule simply stops matching and we are back to today's cost. */
.VIpgJd-ZVi9od-aZ2wEe-wOHMyf svg,
.VIpgJd-ZVi9od-aZ2wEe-wOHMyf circle {
  animation: none !important;
}

#google_translate_element {
  position: absolute;
  left: -9999px;
  height: 0;
  overflow: hidden;
}

.skiptranslate {
  height: 0 !important;
  overflow: hidden !important;
  visibility: hidden !important;
}

body {
  top: 0 !important;
  position: static !important;
}

/* Appearance choice - Auto / Light / Dark.
   Replaced a single toggle that previewed the destination theme. A toggle can
   only express two states, and the third (Auto - follow the phone) is the
   default and the one a patient needs to be able to get BACK to; see the
   markup note in index.template.html. */
.theme-choice {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.25rem;
  padding: 0.25rem;
  background: var(--ios-bg-nested);
  border: 1px solid var(--ios-border);
  border-radius: var(--border-radius-sm);
}

.theme-choice__btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  /* Full 44px target: this is tapped one-handed, often by someone unwell. */
  min-height: 44px;
  padding: 0.5rem 0.25rem;
  border: 1px solid transparent;
  border-radius: var(--border-radius-sm);
  background: transparent;
  color: var(--ios-muted);
  font-family: var(--font-family);
  font-size: 0.8125rem;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast),
    transform var(--transition-fast);
}

.theme-choice__btn svg {
  width: 18px;
  height: 18px;
}

.theme-choice__btn:hover {
  color: var(--ios-ink);
  background: var(--ios-bg-card);
}

.theme-choice__btn:focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-offset);
}

/* The selected state is carried by aria-pressed, not a class: the accessible
   state and the visible state cannot drift apart if they are the same thing. */
.theme-choice__btn[aria-pressed="true"] {
  background: var(--ios-bg-card);
  border-color: var(--ios-border);
  color: var(--ios-ink);
  box-shadow: var(--shadow-sm);
}

/* Colour alone must not carry the selection (WCAG 1.4.1), and the fill also
   survives forced-colors, where our background/shadow are discarded. */
.theme-choice__btn[aria-pressed="true"] svg {
  color: var(--ios-accent-strong);
}

@media (forced-colors: active) {
  .theme-choice__btn[aria-pressed="true"] {
    border-color: Highlight;
    border-width: 2px;
  }
}

/* ========================================
   Accordion Sections
   ======================================== */

.accordion-section {
  margin-bottom: var(--space-sm);
  overflow-anchor: none;
}

.accordion-section:first-child {
  margin-top: var(--space-sm);
}

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

.accordion-heading {
  margin: 0;
  font-size: inherit;
  font-weight: inherit;
}

.accordion-header {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  width: 100%;
  min-height: 72px;
  padding: var(--space-sm);
  border: 1px solid var(--glass-border);
  border-radius: var(--border-radius);
  cursor: pointer;
  font-family: inherit;
  font-size: var(--font-size-lg);
  font-weight: 700;
  color: var(--text);
  text-align: left;
  box-shadow: var(--glass-inner-glow);
  transition: box-shadow var(--transition-fast);
  scroll-margin-top: var(--space-sm);
  position: relative;
  overflow: hidden;
}

/* Glass gloss highlight on top half */
.accordion-header::before {
  content: "";
  position: absolute;
  inset: 0 0 50% 0;
  background: linear-gradient(180deg, var(--glass-gloss) 0%, var(--glass-gloss-end) 100%);
  border-radius: var(--border-radius) var(--border-radius) 0 0;
  pointer-events: none;
  z-index: 1;
}

.accordion-header:hover {
  box-shadow: var(--shadow-md), var(--glass-inner-glow);
}

.accordion-header:focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-offset);
}

/* Section colors (translucent glass gradients) */
[data-color="red"] .accordion-header { background: linear-gradient(160deg, var(--section-red-glass), var(--section-red-glass-end)); }
[data-color="orange"] .accordion-header { background: linear-gradient(160deg, var(--section-orange-glass), var(--section-orange-glass-end)); }
[data-color="yellow"] .accordion-header { background: linear-gradient(160deg, var(--section-yellow-glass), var(--section-yellow-glass-end)); }
[data-color="green"] .accordion-header { background: linear-gradient(160deg, var(--section-green-glass), var(--section-green-glass-end)); }
[data-color="teal"] .accordion-header { background: linear-gradient(160deg, var(--section-teal-glass), var(--section-teal-glass-end)); }
[data-color="blue"] .accordion-header { background: linear-gradient(160deg, var(--section-blue-glass), var(--section-blue-glass-end)); }
[data-color="gray"] .accordion-header { background: linear-gradient(160deg, var(--section-gray-glass), var(--section-gray-glass-end)); }

/* Section icon */
.section-icon {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
}

/* Accordion title */
.accordion-title {
  flex: 1;
}

/* Accordion arrow */
.accordion-arrow {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform var(--transition-normal);
}

.accordion-arrow::before {
  content: "";
  display: block;
  width: var(--arrow-size);
  height: var(--arrow-size);
  border-right: var(--arrow-border-width) solid var(--text);
  border-bottom: var(--arrow-border-width) solid var(--text);
  transform: rotate(45deg);
  transition: transform var(--transition-normal);
}

/* Arrow rotates when expanded */
.accordion-header[aria-expanded="true"] .accordion-arrow::before {
  transform: rotate(-135deg);
}

/* Sticky accordion header when section is open */
.accordion-header[aria-expanded="true"] {
  position: sticky;
  top: 0;
  z-index: 50;
  border-radius: var(--border-radius) var(--border-radius) 0 0;
  box-shadow: var(--shadow-md);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
}

.details-summary-label {
  flex: 1;
}

.details-chevron {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-left: var(--space-sm);
  color: var(--details-chevron-color, var(--text-secondary));
}

.details-chevron-icon {
  width: var(--details-chevron-size, 16px);
  height: var(--details-chevron-size, 16px);
  overflow: visible;
  transform-origin: center;
  transition: transform var(--transition-normal);
}

/* Accordion content */
.accordion-content {
  overflow: hidden;
}

.accordion-content[hidden] {
  display: none;
}

.accordion-content:not([hidden]) {
  display: block;
}

.accordion-body {
  padding: var(--space-sm);
}

/* ========================================
   Collapsible Subsections (Inside Accordions)
   ======================================== */

.subsection {
  border-bottom: 1px solid var(--border);
  overflow-anchor: none;
  scroll-margin-top: var(--space-sm);
}

.subsection:last-child {
  border-bottom: none;
}

.subsection summary {
  display: flex;
  align-items: center;
  cursor: pointer;
  padding: var(--space-sm) 0;
  min-height: var(--min-touch-target);
  list-style: none;
}

.subsection summary::-webkit-details-marker {
  display: none;
}

.subsection summary::marker {
  display: none;
  content: "";
}

.subsection summary :is(h2, h3) {
  margin: 0;
  flex: 1;
}

.subsection .details-chevron {
  --details-chevron-size: 16px;
}

.subsection:not([open]) .details-chevron-icon {
  transform: rotate(180deg);
}

.subsection[open] .details-chevron-icon {
  transform: rotate(0deg);
}

.subsection summary:focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-offset);
  border-radius: var(--border-radius-sm);
}

.subsection-content {
  padding-bottom: var(--space-sm);
}

/* ========================================
   Expanded Cards (layout: "expanded-cards")
   Mirrors the FAQ category pattern: an <h2> heading above a bordered
   card, collapsibility only on nested .inline-details.
   ======================================== */

.expanded-card-section {
  display: block;
  scroll-margin-top: var(--space-md);
}

.expanded-card-section + .expanded-card-section {
  margin-top: var(--space-md);
}

.expanded-card-heading {
  margin: 0 0 var(--space-xs);
}

.expanded-card {
  margin: 0;
  background-color: var(--bg-surface);
  border: 1px solid var(--glass-border);
  border-radius: var(--border-radius-sm);
  padding: 0 var(--space-sm);
  box-shadow: var(--shadow-sm);
  display: flow-root;
}

.expanded-card > :first-child:not(.inline-details) { margin-top: var(--space-sm); }
.expanded-card > :last-child:not(.inline-details) { margin-bottom: var(--space-sm); }

/* Inside a card: strip the inline-details pill chrome and use a
   horizontal divider between adjacent items instead. Matches .faq-item. */
.expanded-card .inline-details {
  border: none;
  border-radius: 0;
  border-bottom: 1px solid var(--border);
  margin: 0;
  padding: 0;
  scroll-margin-top: var(--space-md);
}

.expanded-card .inline-details:last-child {
  border-bottom: none;
}

.expanded-card .inline-details > summary {
  padding: var(--space-sm) 0;
}

/* Kicker-lite treatment for sub-headings inside a card (e.g. "Good to know"). */
.expanded-card h4 {
  margin: var(--space-sm) 0 var(--space-2xs);
  font-size: var(--type-kicker);
  letter-spacing: var(--tracking-kicker);
  text-transform: uppercase;
  color: var(--text-secondary);
  font-weight: 600;
}

/* ========================================
   Zone Cards (Inside How the ED Works)
   ======================================== */

.zone-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  margin-top: var(--space-sm);
  margin-bottom: var(--space-sm);
}

.zone-card {
  background-color: var(--bg-surface);
  border: 1px solid var(--glass-border);
  border-radius: var(--border-radius-sm);
  padding: var(--space-sm);
  box-shadow: var(--shadow-sm);
}

.zone-card h4 {
  margin-top: 0;
  margin-bottom: var(--space-xs);
}

.zone-card p {
  margin-bottom: 0;
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
}

/* ========================================
   Content Cards (Generic info grouping)
   ======================================== */

.content-card {
  background-color: var(--bg-surface);
  border: 1px solid var(--glass-border);
  border-radius: var(--border-radius-sm);
  padding: var(--space-sm);
  margin-bottom: var(--space-xs);
  box-shadow: var(--shadow-sm);
}

.content-card :is(h3, h4) {
  margin-top: 0;
  margin-bottom: var(--space-xs);
}

.content-card p:last-child,
.content-card ul:last-child,
.content-card ol:last-child {
  margin-bottom: 0;
}

.collapsible-card {
  padding: 0;
}

.collapsible-card summary {
  display: flex;
  align-items: center;
  cursor: pointer;
  padding: var(--space-sm);
  list-style: none;
  min-height: var(--min-touch-target);
}

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

.collapsible-card summary::marker {
  display: none;
  content: "";
}

.collapsible-card summary :is(h3, h4) {
  margin: 0;
  flex: 1;
}

.collapsible-card:not([open]) .details-chevron-icon {
  transform: rotate(180deg);
}

.collapsible-card[open] .details-chevron-icon {
  transform: rotate(0deg);
}

.collapsible-card[open] summary {
  border-bottom: 1px solid var(--border);
}

.collapsible-card summary:focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-offset);
  border-radius: var(--border-radius-sm);
}

.collapsible-card-content {
  padding: var(--space-sm);
}

.collapsible-card-content p:last-child,
.collapsible-card-content ul:last-child,
.collapsible-card-content ol:last-child {
  margin-bottom: 0;
}

/* ========================================
   Map Embed
   ======================================== */

.map-embed-wrapper {
  position: relative;
  width: 100%;
  padding-bottom: 75%;
  margin: var(--space-xs) 0;
  border-radius: var(--radius, 8px);
  overflow: hidden;
}

.map-embed-wrapper iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* ========================================
   Test Cards (Inside Assessments & Tests)
   ======================================== */

.test-card {
  background-color: var(--bg-surface);
  border: 1px solid var(--glass-border);
  border-radius: var(--border-radius-sm);
  padding: var(--space-sm);
  margin-bottom: var(--space-xs);
  box-shadow: var(--shadow-sm);
}

.test-card h4 {
  margin-top: 0;
  margin-bottom: var(--space-2xs);
}

.test-card p {
  margin-bottom: 0;
  color: var(--text-secondary);
}

/* ========================================
   FAQ Items (Using <details>/<summary>)
   ======================================== */

.faq-list {
  margin-top: var(--space-xs);
  margin-bottom: var(--space-sm);
  background-color: var(--bg-surface);
  border: 1px solid var(--glass-border);
  border-radius: var(--border-radius-sm);
  padding: 0 var(--space-sm);
  box-shadow: var(--shadow-sm);
}

.faq-item {
  border-bottom: 1px solid var(--border);
}

.faq-item:last-child {
  border-bottom: none;
}

.faq-item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-sm) 0;
  cursor: pointer;
  font-weight: 600;
  list-style: none;
  min-height: var(--min-touch-target);
  color: var(--text);
}

/* Remove default marker */
.faq-item summary::-webkit-details-marker {
  display: none;
}

.faq-item summary::marker {
  display: none;
  content: "";
}

.faq-item .details-chevron {
  --details-chevron-size: 14px;
}

.faq-item:not([open]) .details-chevron-icon {
  transform: rotate(180deg);
}

.faq-item[open] .details-chevron-icon {
  transform: rotate(0deg);
}

.faq-item summary:hover {
  color: var(--link);
}

.faq-item summary:focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-offset);
  border-radius: var(--border-radius-sm);
}

.faq-item p,
.faq-item div {
  padding-bottom: var(--space-sm);
  color: var(--text);
}

.faq-item div > p {
  margin: 0;
  padding-bottom: var(--space-xs);
}

.faq-item div > ul {
  margin-top: var(--space-xs);
  margin-bottom: var(--space-xs);
  padding-left: var(--space-md);
}

.faq-item div > p:last-child {
  padding-bottom: 0;
}

.disclaimer {
  font-size: var(--font-size-sm);
  color: var(--text-muted);
  font-style: italic;
  margin-top: var(--space-sm);
}

/* ========================================
   Error & Loading States
   ======================================== */

.section-loading,
.load-error {
  text-align: center;
  color: var(--text-muted);
  font-style: italic;
  padding: var(--space-md) var(--space-sm);
}

/* -------- Skeleton placeholders + content reveal (smoothness pass) --------
   While a section's JSON is in flight the body shows shimmer bars instead of
   the old "Loading content..." sentence - placeholders read as "arriving",
   not "empty". The bars are decorative (aria-hidden) with an sr-only text
   fallback; the nomodule / slow-boot watchdogs in index.template.html write
   their honest message via textContent on .section-loading, which replaces
   the bars wholesale - that path needs no changes here. */
.skeleton-bar {
  display: block;
  position: relative;
  overflow: hidden;
  height: 0.875rem;
  width: 100%;
  margin: 0 auto 0.75rem;
  border-radius: var(--border-radius-sm);
  background: var(--skeleton-bar);
}

.skeleton-bar--w85 { width: 85%; }
.skeleton-bar--w70 { width: 70%; }

@media (prefers-reduced-motion: no-preference) {
  .skeleton-bar::after {
    content: "";
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, var(--skeleton-sheen), transparent);
    animation: skeleton-sweep 1.6s ease-in-out infinite;
  }
}

@keyframes skeleton-sweep {
  to { transform: translateX(100%); }
}

/* When a section's real content lands (render.js adds .is-filled after the
   innerHTML swap), it rises in softly instead of popping - one animation per
   section container, not per child, so a full-page load stays at ~15 cheap
   compositor animations. One-shot for real: render.js removes the class on
   animationend, because a matching element that goes display:none ->
   rendered again (tab switches, WebKit renderer re-attach when a nearby
   details toggles) restarts the animation and flashes the whole section. */
@media (prefers-reduced-motion: no-preference) {
  .accordion-body.is-filled {
    animation: content-reveal-in var(--transition-normal);
  }
}

@keyframes content-reveal-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
}

/* Expanding surfaces get the same soft entrance: the chevron already eases,
   but the revealed body used to pop in the same frame - a visible mismatch.
   These all go display:none -> rendered, which restarts the animation on
   each open. Close stays instant (iOS convention). Print kills all
   animation (utilities.css) so beforeprint's open-everything never
   snapshots a mid-fade frame.
   Excluded: .flow-step and .subsection. accordion.js drives those through
   a close-sibling-then-smooth-scroll sequence; a fade running while the
   page travels reads as a top-of-page flicker on iOS Safari (Alvin,
   Steps page, 2026-07-23).
   Simple opens (FAQ, inline details, support cards) keep the reveal. */
@media (prefers-reduced-motion: no-preference) {
  details[open]:not(.flow-step):not(.subsection) > *:not(summary),
  .team-tile.is-active .team-tile__expanded,
  .test-tile.is-active .test-tile__expanded,
  .zone-detail:not([hidden]),
  .zone-flow-content:not([hidden]) {
    animation: content-reveal-in var(--transition-normal);
  }
}

.map-loading {
  text-align: center;
  color: var(--text-muted);
  padding: var(--space-xl);
}

/* ========================================
   Footer
   ======================================== */

/* Brand Book skyline strip (brochure footer motif): lime silhouettes
   standing directly on the footer's top rule. Decorative only. */
.footer-skyline {
  display: block;
  width: 100%;
  max-width: var(--max-width);
  height: auto;
  margin: var(--space-lg) auto 0;
  padding: 0 var(--space-xs);
  fill: var(--brand-primary);
}

.footer-skyline + .site-footer {
  /* The skyline supplies the visual gap; buildings sit on the rule. */
  margin-top: 0;
}

@media (min-width: 481px) {
  .footer-skyline {
    /* Track the .site-footer container padding step-up (base.css). */
    padding: 0 var(--space-sm);
  }
}

.site-footer {
  margin-top: var(--space-md);
  padding-top: var(--space-md);
  padding-bottom: var(--space-lg);
  border-top: 1px solid var(--glass-border);
}

.footer-content {
  text-align: center;
}

.footer-updated {
  font-size: var(--font-size-sm);
  color: var(--text-muted);
  margin-bottom: var(--space-xs);
}

.footer-disclaimer {
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
  margin-bottom: var(--space-xs);
}

.footer-security {
  font-size: var(--font-size-sm);
  color: var(--text-muted);
}

.footer-feedback {
  font-size: var(--font-size-sm);
  margin-top: var(--space-xs);
  margin-bottom: 0;
}

.footer-feedback-link {
  color: var(--link);
  text-decoration: underline;
}

.footer-feedback-link:hover {
  color: var(--link-hover);
}

/* ========================================
   App Update Banner
   ======================================== */

.app-update-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  max-width: var(--max-width);
  margin: 0 auto;
  padding: var(--space-sm);
  background-color: var(--bg-surface);
  border-bottom: 1px solid var(--glass-border);
}

.app-update-banner[hidden] {
  display: none;
}

.app-update-message {
  margin-bottom: 0;
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
}

.site-status-banner {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: var(--space-sm);
  border-bottom: 1px solid var(--glass-border);
  font-size: var(--font-size-sm);
}

.site-status-banner-info {
  background-color: var(--section-blue);
  color: var(--text);
}

.site-status-banner-warning {
  background-color: var(--section-yellow);
  color: var(--text);
}

.update-refresh-btn {
  border: 1px solid var(--border);
  /* Brand primary button: lime surface, charcoal label */
  background-color: var(--brand-primary);
  color: var(--text-on-brand);
  border-radius: var(--border-radius-sm);
  min-height: var(--min-touch-target);
  padding: 0 var(--space-sm);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.update-refresh-btn:focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-offset);
}

.update-refresh-btn:disabled {
  opacity: 0.7;
  cursor: progress;
}

/* Removed: .feedback-unavailable - no element carries it (render.js builds
   the feedback card's unavailable state from other classes). */

/* ========================================
   Flow Steps (Process Flow in How the ED Works)
   ======================================== */

.flow-steps {
  list-style: none;
  padding: 0;
  margin: 0;
}

.flow-steps > li {
  position: relative;
}

.flow-step {
  border: 1px solid var(--glass-border);
  border-radius: var(--border-radius);
  background-color: var(--bg-surface);
  box-shadow: var(--shadow-sm);
  overflow-anchor: none;
  scroll-margin-top: var(--space-sm);
}

.flow-step summary {
  display: flex;
  align-items: center;
  cursor: pointer;
  padding: var(--space-sm);
  min-height: var(--min-touch-target);
  list-style: none;
  gap: var(--space-sm);
}

.flow-step summary::-webkit-details-marker {
  display: none;
}

.flow-step summary::marker {
  display: none;
  content: "";
}

.flow-step-number {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  min-width: 32px;
  border-radius: 50%;
  background-color: var(--flow-step-bg, var(--brand-primary));
  /* Falls back to --text-on-brand, not --text: the default bg is the lime,
     where the deep charcoal is the AAA (8.27:1) pairing. */
  color: var(--flow-step-text, var(--text-on-brand));
  font-weight: 700;
  font-size: var(--font-size-base);
  flex-shrink: 0;
  box-shadow: 0 2px 8px var(--brand-primary-shadow, rgba(118, 176, 67, 0.3));
}

.flow-step summary h3 {
  margin: 0;
  flex: 1;
}

.flow-step .details-chevron {
  --details-chevron-size: 16px;
}

.flow-step:not([open]) .details-chevron-icon {
  transform: rotate(180deg);
}

.flow-step[open] .details-chevron-icon {
  transform: rotate(0deg);
}

.flow-step summary:focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-offset);
  border-radius: var(--border-radius);
}

.flow-step[open] summary {
  border-bottom: 1px solid var(--border);
}

.flow-step-content {
  padding: var(--space-sm);
}

/* Flow arrows between steps */
.flow-arrow {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 4px 0;
}

.flow-arrow::before {
  content: "";
  display: block;
  width: 2px;
  height: 10px;
  background-color: var(--text-muted, #999);
}

.flow-arrow::after {
  content: "";
  display: block;
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 6px solid var(--text-muted, #999);
}

/* Inline details (urgency levels nested toggle) */
.inline-details {
  border: 1px solid var(--glass-border);
  border-radius: var(--border-radius-sm);
  margin: var(--space-sm) 0;
}

.inline-details summary {
  display: flex;
  align-items: center;
  cursor: pointer;
  padding: var(--space-xs) var(--space-sm);
  list-style: none;
  font-weight: 600;
  color: var(--text-secondary);
  min-height: var(--min-touch-target);
}

.inline-details summary::-webkit-details-marker {
  display: none;
}

.inline-details summary::marker {
  display: none;
  content: "";
}

.inline-details .details-chevron {
  --details-chevron-size: 14px;
}

.inline-details:not([open]) .details-chevron-icon {
  transform: rotate(180deg);
}

.inline-details[open] .details-chevron-icon {
  transform: rotate(0deg);
}

.inline-details summary:focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-offset);
  border-radius: var(--border-radius-sm);
}

.inline-details > :not(summary) {
  padding: var(--space-sm);
  padding-top: var(--space-sm);
}

.inline-details ul,
.inline-details ol {
  margin-top: 0;
  margin-bottom: var(--space-sm);
}

.inline-details li {
  margin-bottom: var(--space-2xs);
}

.inline-details li:last-child {
  margin-bottom: 0;
}

/* CTAS Triage Level Badges (replace bullet markers) */
li:has(.ctas-badge) {
  list-style: none;
  position: relative;
}

.ctas-badge {
  position: absolute;
  left: -1.2em;
  top: 0.55em;
  width: 10px;
  height: 10px;
  border-radius: 50%;
}

.ctas-1 { background-color: #0072C6; }
.ctas-2 { background-color: #D32F2F; }
.ctas-3 { background-color: #F9A825; }
.ctas-4 { background-color: #388E3C; }
.ctas-5 {
  background-color: #FFFFFF;
  border: 1.5px solid var(--text-secondary);
}

[data-theme="dark"] .ctas-5 {
  background-color: transparent;
}

/* ========================================
   Zone Selector (Interactive Zone Picker)
   ======================================== */

.zone-selector {
  margin: var(--space-sm) 0;
}

.zone-selector-intro {
  margin-bottom: var(--space-sm);
}

.zone-selector-grid {
  display: grid;
  /* minmax(0, 1fr), not 1fr: a bare `1fr` means `minmax(auto, 1fr)`, so each
     column refuses to shrink below its content's min-content width. At the
     larger text sizes that floor exceeds the container and the grid pushes
     the whole page into horizontal scrolling - on exactly the accessibility
     path that needs it least. minmax(0, ...) lets the text wrap instead.
     (screens.css `.zone-grid` already had this right.) */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-xs);
  margin-bottom: var(--space-sm);
}

@media (max-width: 359px) {
  .zone-selector-grid {
    grid-template-columns: 1fr;
  }
}

.zone-btn {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  padding: var(--space-sm);
  min-height: var(--min-touch-target);
  border: 1px solid var(--glass-border);
  border-left: 4px solid var(--zone-color, var(--border));
  border-radius: var(--border-radius-sm);
  background-color: var(--zone-bg, var(--bg-surface));
  cursor: pointer;
  font-family: inherit;
  font-size: var(--font-size-base);
  color: var(--text-primary);
  width: 100%;
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-normal), border-color var(--transition-normal), transform var(--transition-normal);
}

.zone-btn:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}

.zone-btn:focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-offset);
}

.zone-btn-name {
  font-weight: 600;
}

.zone-btn-alt {
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
  font-weight: 400;
}

.zone-btn.active .zone-btn-alt {
  margin-left: var(--space-sm);
}

/* Zone color definitions */
.zone-btn[data-zone="red"] {
  --zone-color: #FF3B30;
  --zone-bg: rgba(255, 59, 48, 0.1);
}
.zone-btn[data-zone="blue"] {
  --zone-color: #4A90E2;
  --zone-bg: rgba(74, 144, 226, 0.1);
}
.zone-btn[data-zone="pink"] {
  --zone-color: #FF9CCF;
  --zone-bg: rgba(255, 156, 207, 0.1);
}
.zone-btn[data-zone="green"] {
  --zone-color: #34C759;
  --zone-bg: rgba(52, 199, 89, 0.1);
}
.zone-btn[data-zone="raz"] {
  --zone-color: #FFE066;
  --zone-bg: rgba(255, 224, 102, 0.1);
}
.zone-btn[data-zone="yellow"] {
  --zone-color: #FFF59D;
  --zone-bg: rgba(255, 245, 157, 0.1);
}
.zone-btn[data-zone="purple"] {
  --zone-color: #8E7CF0;
  --zone-bg: rgba(142, 124, 240, 0.1);
}
.zone-btn[data-zone="cyez"] {
  --zone-color: #00CFE8;
  --zone-bg: rgba(0, 207, 232, 0.1);
}

/* Dark mode: increase tint opacity. Keyed to the resolved in-app theme
   ([data-theme], stamped by preferences.js) - not prefers-color-scheme -
   so a user who picks Light on an OS-dark phone gets light-mode tints,
   matching every other themed surface (see the convention note in ios.css). */
[data-theme="dark"] .zone-btn[data-zone="red"] { --zone-bg: rgba(255, 59, 48, 0.15); }
[data-theme="dark"] .zone-btn[data-zone="blue"] { --zone-bg: rgba(74, 144, 226, 0.15); }
[data-theme="dark"] .zone-btn[data-zone="pink"] { --zone-bg: rgba(255, 156, 207, 0.15); }
[data-theme="dark"] .zone-btn[data-zone="green"] { --zone-bg: rgba(52, 199, 89, 0.15); }
[data-theme="dark"] .zone-btn[data-zone="raz"] { --zone-bg: rgba(255, 224, 102, 0.15); }
[data-theme="dark"] .zone-btn[data-zone="yellow"] { --zone-bg: rgba(255, 245, 157, 0.15); }
[data-theme="dark"] .zone-btn[data-zone="purple"] { --zone-bg: rgba(142, 124, 240, 0.15); }
[data-theme="dark"] .zone-btn[data-zone="cyez"] { --zone-bg: rgba(0, 207, 232, 0.15); }

.zone-btn-arrow {
  display: none;
  width: var(--arrow-size);
  height: var(--arrow-size);
  border-right: var(--arrow-border-width) solid var(--text-secondary);
  border-bottom: var(--arrow-border-width) solid var(--text-secondary);
  transform: rotate(-45deg);
  transition: transform var(--transition-fast);
  flex-shrink: 0;
  margin-left: auto;
}

.zone-btn.active {
  border-left-width: 6px;
  cursor: pointer;
  grid-column: 1 / -1;
  flex-direction: row;
  align-items: center;
  scroll-margin-top: var(--space-sm);
  box-shadow: var(--shadow-md), var(--glass-inner-glow);
}

.zone-btn.active .zone-btn-arrow {
  display: block;
  transform: rotate(-135deg);
}

.zone-btn[hidden] {
  display: none;
}

/* Zone detail panel (expanded zone content) */
.zone-detail {
  padding: 0;
}

.zone-detail[hidden] {
  display: none;
}

.zone-detail-rooms {
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
  font-weight: 600;
  margin-bottom: var(--space-xs);
}

.zone-detail-description {
  margin-bottom: var(--space-sm);
  color: var(--text-secondary);
}

.zone-bridge-link {
  display: block;
  margin-top: var(--space-sm);
  padding-top: var(--space-sm);
  border-top: 1px solid var(--border);
  color: var(--link);
  font-weight: 600;
}

.zone-after-note {
  font-size: var(--font-size-base);
  color: var(--text-muted);
  font-style: italic;
}

/* ========================================
   Language Selection Modal (First Visit)
   ======================================== */

.language-modal-overlay {
  position: fixed;
  inset: 0;
  /* Above the dock (ios.css z-index 9001) and the page-transition ghost
     (9100): a modal dialog must cover ALL navigation - the dock was floating
     over the backdrop, visibly and tappably, letting patients navigate away
     under an open modal. */
  z-index: 9300;
  background-color: var(--bg-overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-sm);
  opacity: 0;
  transition: opacity var(--transition-normal);
}

.language-modal-overlay.active {
  opacity: 1;
}

.language-modal {
  background-color: var(--glass-bg-heavy);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  border: 1px solid var(--glass-border);
  border-radius: var(--border-radius);
  width: 100%;
  max-width: 400px;
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  box-shadow: var(--glass-shadow), var(--glass-inner-glow);
  overflow: hidden;
  opacity: 0;
  transform: scale(0.95);
  transition: opacity var(--transition-normal), transform var(--transition-normal);
}

.language-modal-overlay.active .language-modal {
  opacity: 1;
  transform: scale(1);
}

.language-modal:focus {
  outline: none;
}

.language-modal-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: var(--space-sm);
  gap: var(--space-xs);
}

.language-modal-title {
  margin: 0;
  font-size: var(--font-size-xl);
  font-weight: 700;
  color: var(--text);
  line-height: var(--line-height-tight);
  flex: 1;
}

/* Text button, not an icon: "Continue in English" must be readable at a
   glance by the users least fluent with web conventions. */
.language-modal-close {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--min-touch-target);
  padding: 0.375rem 0.75rem;
  border: 1px solid var(--border);
  background: var(--bg-surface);
  border-radius: var(--border-radius-sm);
  cursor: pointer;
  color: var(--text);
  font-size: var(--font-size-base);
  font-weight: 600;
  /* May wrap to two lines on 320px phones - shrinking beats overflowing
     the modal (the header row clipped at 320px with nowrap behavior). */
  min-width: 0;
  text-align: center;
}

.language-modal-close:hover {
  background-color: var(--bg-surface);
}

.language-modal-close:focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-offset);
}

/* Active-language strip under the header (only rendered when a language is
   selected): checkmark + native name + English name, for the patient and any
   staff helping them. flex-shrink 0 so the list can never squash it. */
.language-modal-current {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  margin: 0 var(--space-sm) var(--space-xs);
  padding: 0.75rem 1rem;
  background: var(--bg-surface);
  border: 1px solid var(--primary, #B2D235);
  border-radius: var(--border-radius-sm);
}

.language-modal-current__label {
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
}

.language-modal-current__value {
  font-size: var(--font-size-lg);
  font-weight: 700;
  color: var(--text);
}

.language-modal-body {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 0 var(--space-sm) var(--space-sm);
}

.language-modal-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.language-modal-btn {
  width: 100%;
  min-height: var(--min-touch-target);
  padding: var(--space-xs) var(--space-sm);
  border: none;
  background: none;
  cursor: pointer;
  font-family: var(--font-family);
  font-size: var(--font-size-base);
  color: var(--text);
  text-align: left;
  border-radius: var(--border-radius-sm);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 0.5rem;
}

/* English gloss after the native name, for staff who cannot read the script. */
.language-modal-btn__english {
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
}

/* The active language, marked in the list as well as the header strip. */
.language-modal-btn.is-current {
  background-color: var(--bg-surface);
  font-weight: 700;
}

.language-modal-btn.is-current .language-modal-btn__native::before {
  content: "\2713\00a0";
  color: var(--primary, #B2D235);
}

.language-modal-btn:hover {
  background-color: var(--glass-bg-medium);
}

/* List rows flash their background on press (iOS list convention) rather
   than scaling - instant, and equally present under reduced motion. */
.language-modal-btn:active {
  background-color: var(--glass-bg-medium);
}

.language-modal-btn:focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-offset);
}

.language-modal-btn-featured {
  font-size: var(--font-size-lg);
  font-weight: 500;
}

.language-modal-separator {
  height: 1px;
  background-color: var(--border);
  margin: var(--space-xs) 0;
}

/* ========================================
   Staffing Indicator
   ======================================== */

.staffing-indicator {
  font-size: var(--font-size-sm);
  font-weight: 600;
  color: var(--text-secondary);
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: var(--border-radius-sm);
  padding: var(--space-xs) var(--space-sm);
  margin-bottom: var(--space-sm);
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  .language-modal-overlay,
  .language-modal {
    transition: none;
  }

  .details-chevron-icon {
    transition: none;
  }
}


/* ================================================================
   Hub redesign (While You Wait + After Your Visit hub pages
   and their subpages). Uses the global iOS green accent
   (--ios-accent / --ios-accent-soft / --ios-accent-strong)
   throughout, matching Home / Process / FAQ. The data-color
   "orange" / "yellow" attributes still exist on the section
   shells for any future use, but no visual orange/yellow chrome
   is rendered - the page palette is cream + green like the
   rest of the site.
   ================================================================ */

/* ----------------------------------------------------------------
   Feature card (top "Right now in your zone" card)
   Cream surface matching the stacked-card pattern on Process / Home -
   no gradient, no left accent bar. Distinguished from a regular
   stacked-card only by its content (pulsing dot + kicker + stat tiles).
   ---------------------------------------------------------------- */
.feature-card {
  margin: 0 var(--space-xs) var(--space-sm);
  border-radius: var(--radius-card);
  padding: 1.25rem;
  background: var(--ios-bg-card);
  border: 1px solid var(--ios-border);
  box-shadow: var(--shadow-card);
  position: relative;
}
.feature-card__kicker {
  font-size: var(--type-kicker);
  font-weight: 700;
  letter-spacing: var(--tracking-kicker);
  text-transform: uppercase;
  color: var(--ios-accent-strong);
  margin: 0 0 0.625rem;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
.feature-card__dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--ios-accent);
  box-shadow: 0 0 0 4px var(--ios-accent-soft);
  animation: feature-pulse 1.8s ease-in-out infinite;
}
@keyframes feature-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.4; transform: scale(0.7); }
}
.feature-card__title {
  margin: 0 0 0.625rem;
  font-size: 1.375rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ios-ink);
  line-height: 1.2;
}
.feature-card__body {
  margin: 0 0 var(--space-sm);
  color: var(--ios-ink);
  font-size: 1rem;
  line-height: 1.5;
}
.feature-card__stats {
  display: grid;
  /* minmax(0, 1fr), not 1fr: a bare `1fr` means `minmax(auto, 1fr)`, so each
     column refuses to shrink below its content's min-content width. At the
     larger text sizes that floor exceeds the container and the grid pushes
     the whole page into horizontal scrolling - on exactly the accessibility
     path that needs it least. minmax(0, ...) lets the text wrap instead.
     (screens.css `.zone-grid` already had this right.) */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 0.625rem;
  margin: 0 0 0.5rem;
  align-items: stretch;
}
.feature-card__stat {
  background: var(--ios-accent-soft);
  border: 1px solid var(--ios-border);
  border-radius: 14px;
  padding: 0.625rem 0.75rem;
  display: flex;
  flex-direction: column;
  height: 100%;
}
.feature-card__stat-num {
  font-size: 1.25rem;
  font-weight: 800;
  color: var(--ios-accent-strong);
  letter-spacing: -0.02em;
  line-height: 1;
  margin: 0 0 0.25rem;
  /* Deliberately NOT `white-space: nowrap`. Values like "3-10+ hours" already
     sit on one line at every size that fits, so nowrap bought nothing - but it
     made the string unshrinkable, which set the grid column's min-content floor
     and pushed the page into horizontal scrolling at the larger text sizes.
     Letting it wrap only ever takes effect when it genuinely cannot fit. */
  min-width: 0;
}
.feature-card__stat-label {
  font-size: 0.875rem;
  color: var(--ios-muted);
  line-height: 1.3;
  margin: 0;
}
.feature-card__foot {
  margin: 0.625rem 0 0;
  color: var(--ios-ink);
  font-size: 0.9375rem;
  line-height: 1.5;
}

/* ----------------------------------------------------------------
   Action grid (subpage tiles) - reuses .ios-tile from ios.css
   ---------------------------------------------------------------- */
.action-grid {
  display: grid;
  /* minmax(0, 1fr), not 1fr: a bare `1fr` means `minmax(auto, 1fr)`, so each
     column refuses to shrink below its content's min-content width. At the
     larger text sizes that floor exceeds the container and the grid pushes
     the whole page into horizontal scrolling - on exactly the accessibility
     path that needs it least. minmax(0, ...) lets the text wrap instead.
     (screens.css `.zone-grid` already had this right.) */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 0.625rem;
  padding: 0 var(--space-xs);
  margin-bottom: 0.75rem;
}
/* Wide variant: icon LEFT, title RIGHT of the icon (vertically centered),
   subtitle below spanning full width - mirrors `.team-tile__head` + preview
   pattern (Doctors / Nurses tiles) so the AYV "Admission or transfer" tile
   reads like a peer of the team tiles. Specificity bump (`.ios-tile.ios-tile--wide`,
   0,2,0) wins over the base `.ios-tile { flex-direction: column }` rule
   (0,1,0) which loads later in ios.css. */
.ios-tile.ios-tile--wide {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 0.625rem;
  row-gap: 0.25rem;
  align-items: center;
  min-height: 0;
  padding: 0.875rem 1rem 1.5rem;
}
.ios-tile.ios-tile--wide .ios-tile__icon {
  grid-column: 1;
  grid-row: 1;
  flex-shrink: 0;
}
.ios-tile.ios-tile--wide .ios-tile__body {
  display: contents;
}
.ios-tile.ios-tile--wide .ios-tile__title {
  grid-column: 2;
  grid-row: 1;
  margin: 0;
}
.ios-tile.ios-tile--wide .ios-tile__subtitle {
  grid-column: 1 / -1;
  grid-row: 2;
  margin: 0;
}

/* ----------------------------------------------------------------
   Team scroller (horizontal expand-in-place tiles). Mirrors the
   .test-scroller pattern so "Who is looking after you" reads as
   peer with "Tests you may have".
   ---------------------------------------------------------------- */
.team-scroller-wrap {
  margin: 0 0 var(--space-xs);
  position: relative;
}
/* Inline-end edge fade hints there's more content to scroll to. Hidden when
   a tile is expanded so it doesn't overlap the active card. The gradient
   direction is overridden under [dir="rtl"] so RTL users see the fade on
   the correct edge. */
.team-scroller-wrap::after {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  inset-inline-end: 0;
  width: 28px;
  pointer-events: none;
  background: linear-gradient(to right, transparent, var(--ios-bg-body));
  opacity: 1;
  transition: opacity 200ms ease;
}
[dir="rtl"] .team-scroller-wrap::after {
  background: linear-gradient(to left, transparent, var(--ios-bg-body));
}
.team-scroller-wrap:has(.team-scroller.has-active)::after { opacity: 0; }
.team-scroller {
  display: flex;
  gap: 0.5rem;
  /* Inline-start padding aligns the first tile's left edge with the
     action-grid tiles above (e.g. "Prepare while waiting"), which sit at
     16px from the viewport via `.action-grid { padding: 0 var(--space-xs) }`.
     Also gives the prev arrow 8px of breathing room before it overlaps tile
     content at scrollLeft=0. RTL: padding-inline-start flips automatically.
     `scroll-padding-inline-start` matches the padding so scroll-snap counts
     the padding as the snap origin - without it, mandatory snapping pulls
     scrollLeft to the first tile's offsetLeft (8px), which makes the prev
     arrow appear on first load and visually "scrolls past" the padding. */
  padding: 0.25rem 0 0.5rem;
  padding-inline-start: var(--space-xs);
  scroll-padding-inline-start: var(--space-xs);
  overflow-x: auto;
  /* Proximity (not mandatory) so prev/next arrow `scrollBy({ behavior: 'smooth' })`
     animates cleanly. Mandatory snap forces an instant snap to the nearest
     snap point on the destination side, which Safari treats as a jump rather
     than a smooth animation. Proximity still snaps on manual swipe end when
     the scroll comes to rest near a tile, which is the only place where the
     snap behavior is user-visible. */
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.team-scroller::-webkit-scrollbar { display: none; }
.team-scroller::after {
  content: "";
  flex: 0 0 0.25rem;
}
.team-tile {
  /* Sized so the next tile is partially visible on phones (peek affordance);
     capped at 200px so tablet/desktop don't get oversized cards. */
  flex: 0 0 calc(60% - 0.25rem);
  max-width: 200px;
  scroll-snap-align: start;
  background: var(--ios-bg-card);
  border: 1px solid var(--ios-border);
  border-radius: var(--radius-tile);
  padding: 0.875rem;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  transition: background var(--transition-fast), border-color var(--transition-fast),
    transform var(--transition-fast);
}
.team-tile.is-active {
  border-color: var(--ios-accent);
  flex: 1 1 100%;
  /* Override the collapsed-state cap so the active tile fills the scroller. */
  max-width: none;
  min-width: 0;
  position: relative;
}
/* Chevron affordance in the head row: down when collapsed, rotates 180deg
   to up when active. Replaces the previous "X close" badge so there is one
   consistent indicator that signals "this tile is tappable" in both states. */
.team-tile__chev {
  margin-left: auto;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--ios-divider);
  color: var(--ios-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: transform var(--transition-normal);
}
.team-tile__chev svg { width: 14px; height: 14px; stroke-width: 2.5; }
.team-tile.is-active .team-tile__chev { transform: rotate(180deg); }
/* Hide non-active siblings instantly when a tile expands. Matches the
   zone-btn pattern on the Process page (siblings get [hidden]) - clean
   snap, no flex-basis collapse animation. */
.team-scroller.has-active .team-tile:not(.is-active) { display: none; }
/* Trailing spacer is irrelevant when only the active tile is rendered;
   collapse it so the active card fills the scroller width edge-to-edge. */
.team-scroller.has-active::after { display: none; }
.team-tile__head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
/* The head row is the tile's <button> (expanded content must not live
   inside a button for AT); reset UA button chrome so the card visuals are
   unchanged. The whole tile stays clickable via delegation. */
.team-tile__head,
.test-tile__head {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  width: 100%;
}
.team-tile__icon {
  width: 28px; height: 28px;
  border-radius: 8px;
  background: var(--ios-accent-soft);
  color: var(--ios-accent);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.team-tile__icon svg { width: 16px; height: 16px; stroke-width: 1.75; }
.team-tile__title {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.2;
  color: var(--ios-ink);
}
.team-tile__count {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--ios-accent-strong);
  margin: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}
.team-tile__count-text { display: inline; }
.team-tile__count-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--ios-accent);
  box-shadow: 0 0 0 3px var(--ios-accent-soft);
  animation: feature-pulse 1.8s ease-in-out infinite;
  flex-shrink: 0;
}
.team-tile__preview {
  font-size: var(--type-kicker);
  color: var(--ios-muted);
  margin: 0;
  line-height: 1.35;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Expanded bullet list inside an active team tile. The tile itself becomes
   a single card containing icon + title + (count + preview) + bullets,
   matching the zone-tile pattern (no separate detail panel below that
   repeats the title).

   Animated open/close via the grid-template-rows 0fr -> 1fr trick: the
   Body shows/hides instantly to match the zone-btn pattern - no
   slide-down. When a tile is active, the divider + spacing appear with
   the body content. */
.team-tile__expanded { display: none; }
.team-tile.is-active .team-tile__expanded {
  display: block;
  margin-top: 0.625rem;
  padding-top: 0.625rem;
  border-top: 1px solid var(--ios-divider);
}
.team-tile__expanded-list {
  margin: 0;
  padding-left: 1.125rem;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--ios-ink);
  list-style: disc;
}
.team-tile__expanded-list li { margin-bottom: 0.4rem; }
.team-tile__expanded-list li:last-child { margin-bottom: 0; }
.team-tile__expanded-list li ::marker,
.team-tile__expanded-list li::marker {
  color: var(--ios-muted);
}
.team-tile__expanded-list strong {
  color: var(--ios-ink);
  font-weight: 600;
}

/* ----------------------------------------------------------------
   Test scroller (horizontal expand-in-place tiles)
   ---------------------------------------------------------------- */
.test-scroller-wrap {
  margin: 0 0 var(--space-xs);
  position: relative;
}
.test-scroller-wrap::after {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  inset-inline-end: 0;
  width: 28px;
  pointer-events: none;
  background: linear-gradient(to right, transparent, var(--ios-bg-body));
  opacity: 1;
  transition: opacity 200ms ease;
}
[dir="rtl"] .test-scroller-wrap::after {
  background: linear-gradient(to left, transparent, var(--ios-bg-body));
}
.test-scroller-wrap:has(.test-scroller.has-active)::after { opacity: 0; }
.test-scroller {
  display: flex;
  gap: 0.5rem;
  /* See .team-scroller above - same inline-start padding + scroll-padding for
     action-grid alignment and snap-aware "start" position. */
  padding: 0.25rem 0 0.5rem;
  padding-inline-start: var(--space-xs);
  scroll-padding-inline-start: var(--space-xs);
  overflow-x: auto;
  /* See .team-scroller above - proximity instead of mandatory so arrow-click
     smooth scroll animates instead of jumping. */
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.test-scroller::-webkit-scrollbar { display: none; }
.test-scroller::after {
  content: "";
  flex: 0 0 0.25rem;
}
.test-tile {
  /* Sized so the next tile is partially visible on phones (peek affordance);
     capped at 200px so tablet/desktop don't get oversized cards. */
  flex: 0 0 calc(60% - 0.25rem);
  max-width: 200px;
  scroll-snap-align: start;
  background: var(--ios-bg-card);
  border: 1px solid var(--ios-border);
  border-radius: var(--radius-tile);
  padding: 0.875rem;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  transition: background var(--transition-fast), border-color var(--transition-fast),
    transform var(--transition-fast);
}
.test-tile.is-active {
  border-color: var(--ios-accent);
  flex: 1 1 100%;
  max-width: none;
  min-width: 0;
  position: relative;
}
/* Chevron affordance in the head row: down when collapsed, rotates 180deg
   to up when active. Replaces the previous "X close" badge. Mirrors
   .team-tile__chev so both scrollers feel consistent. */
.test-tile__chev {
  margin-left: auto;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--ios-divider);
  color: var(--ios-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: transform var(--transition-normal);
}
.test-tile__chev svg { width: 14px; height: 14px; stroke-width: 2.5; }
.test-tile.is-active .test-tile__chev { transform: rotate(180deg); }
/* Hide non-active siblings instantly when a tile expands - matches the
   zone-btn pattern. Mirrors .team-scroller.has-active. */
.test-scroller.has-active .test-tile:not(.is-active) { display: none; }
.test-scroller.has-active::after { display: none; }
.test-tile__head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.test-tile__icon {
  width: 28px; height: 28px;
  border-radius: 8px;
  background: var(--ios-accent-soft);
  color: var(--ios-accent);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.test-tile__icon svg { width: 16px; height: 16px; stroke-width: 1.75; }
.test-tile__title {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.2;
  color: var(--ios-ink);
}
.test-tile__time {
  font-size: 0.875rem;
  color: var(--ios-muted);
  margin: 0;
  font-weight: 600;
  letter-spacing: 0.02em;
}
.test-tile__preview {
  font-size: var(--type-kicker);
  color: var(--ios-muted);
  margin: 0;
  line-height: 1.35;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Body shows/hides instantly to match the zone-btn pattern - no
   slide-down. Mirrors .team-tile__expanded. */
.test-tile__expanded { display: none; }
.test-tile.is-active .test-tile__expanded {
  display: block;
  margin-top: 0.625rem;
  padding-top: 0.625rem;
  border-top: 1px solid var(--ios-divider);
}
.test-tile__expanded-body {
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--ios-ink);
}
.test-tile__expanded-body strong {
  color: var(--ios-ink);
  font-weight: 600;
}
/* Hide the truncated preview text when expanded (the full body below
   contains the same content unabridged). */
.test-tile.is-active .test-tile__preview { display: none; }
.test-disclaimer {
  margin: 0 var(--space-sm) 0.75rem;
  font-size: var(--type-kicker);
  color: var(--ios-muted);
  line-height: 1.4;
}
.test-disclaimer strong {
  color: var(--ios-ink);
  font-weight: 600;
}

/* ----------------------------------------------------------------
   Scroller controls: chevron arrows + pagination dots
   POR Apr 28: improve discoverability of horizontal scrolling on
   .team-scroller and .test-scroller (Who is looking after you /
   Tests you may have on While You Wait). Both wraps are
   position: relative so arrows can absolute-position over the edges.
   Visibility wired in hub-interactions.js based on scroll position
   and the .has-active expand state.
   ---------------------------------------------------------------- */
.scroller-arrow {
  position: absolute;
  top: calc(50% - 0.25rem);
  /* Account for the scroller's 0.5rem bottom padding so the arrow centers
     on the visible tile band, not the full wrap. */
  transform: translateY(-50%);
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--ios-border);
  background: rgba(255, 255, 255, 0.92);
  color: var(--ios-ink);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font: inherit;
  padding: 0;
  box-shadow: var(--shadow-sm);
  z-index: 2;
  /* Sit slightly inset so the arrow ring isn't clipped by the scroller wrap. */
  transition: opacity var(--transition-fast), background var(--transition-fast),
    transform var(--transition-fast);
}
.scroller-arrow svg {
  width: 16px;
  height: 16px;
  stroke-width: 2.5;
}
.scroller-arrow:hover {
  background: rgba(255, 255, 255, 1);
}
.scroller-arrow:focus-visible {
  outline: var(--focus-outline);
  outline-offset: var(--focus-offset);
}
/* Invisible hit-area extension to the 44px touch-target floor (the ring
   renders 32px). */
.scroller-arrow::after {
  content: '';
  position: absolute;
  inset: -6px;
  border-radius: 50%;
}
.scroller-arrow--prev { inset-inline-start: 0; }
.scroller-arrow--next { inset-inline-end: 0; }
.scroller-arrow[hidden] { display: none; }

/* When a tile is expanded, no scrolling is possible/needed - hide arrows. */
.team-scroller-wrap:has(.team-scroller.has-active) .scroller-arrow,
.test-scroller-wrap:has(.test-scroller.has-active) .scroller-arrow {
  display: none;
}

/* Dark mode: tint the arrow background so it remains visible against the
   darker page background. Uses [data-theme="dark"] (set by preferences.js
   based on the in-app Appearance setting) rather than
   @media (prefers-color-scheme: dark) so the arrows track the page theme,
   not the OS preference. */
[data-theme="dark"] .scroller-arrow {
  background: rgba(40, 40, 40, 0.92);
  color: var(--ios-ink);
  border-color: var(--ios-border);
}
[data-theme="dark"] .scroller-arrow:hover { background: rgba(50, 50, 50, 1); }

@media (prefers-reduced-motion: reduce) {
  .scroller-arrow { transition: none; }
}

/* ----------------------------------------------------------------
   List card (icon + title + desc rows)
   ---------------------------------------------------------------- */
.list-card {
  background: var(--ios-bg-card);
  border: 1px solid var(--ios-border);
  border-radius: var(--radius-card);
  margin: 0 var(--space-xs) 0.75rem;
  padding: 0.25rem 0;
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.list-card__row {
  display: flex;
  gap: 0.875rem;
  padding: 0.875rem 1rem;
  align-items: flex-start;
  border-bottom: 1px solid var(--ios-divider);
}
.list-card__row:last-child { border-bottom: none; }
.list-card__icon {
  width: 32px; height: 32px;
  border-radius: 10px;
  background: var(--ios-accent-soft);
  color: var(--ios-accent);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  margin-top: 1px;
}
.list-card__icon svg { width: 18px; height: 18px; stroke-width: 1.75; }
.list-card__body { flex: 1; }
.list-card__title {
  margin: 0 0 0.125rem;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.25;
  color: var(--ios-ink);
}
.list-card__desc {
  margin: 0;
  font-size: 0.875rem;
  color: var(--ios-muted);
  line-height: 1.4;
}
.list-card__desc a {
  color: var(--ios-accent-strong);
  font-weight: 600;
}
.list-card__desc strong {
  color: var(--ios-ink);
  font-weight: 600;
}
.list-card__desc ul {
  margin: 0.375rem 0 0;
  padding-left: 1.125rem;
  list-style: disc;
}
.list-card__desc ul li {
  margin: 0.125rem 0;
  line-height: 1.4;
}

/* ----------------------------------------------------------------
   Do / Don't list (vertically stacked horizontal cards)
   Was a 2-col grid; switched to a single column so each card spans
   the full content width with body-sized type. The cramped 13px
   side-by-side layout failed legibility on phones and the smaller
   font fell below the practical AA readability floor.
   ---------------------------------------------------------------- */
.dodont {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  padding: 0 var(--space-xs);
  margin-bottom: 0.75rem;
}
.dodont__col {
  background: var(--ios-bg-card);
  border: 1px solid var(--ios-border);
  border-radius: var(--radius-tile);
  padding: 1rem;
}
.dodont__head {
  display: flex; align-items: center; gap: 0.5rem;
  margin-bottom: 0.625rem;
  font-size: 1.0625rem;
  font-weight: 700;
  color: var(--ios-ink);
}
.dodont__marker {
  width: 22px; height: 22px;
  border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  color: white;
}
/* Do = brand dark green; Don't keeps a semantic red (no brand-palette
   equivalent carries the "avoid" meaning). White glyphs pass AA on both. */
.dodont__col--do .dodont__marker { background: var(--brand-secondary); }
.dodont__col--dont .dodont__marker { background: #C44848; }
.dodont__list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.dodont__list li {
  display: flex;
  gap: 0.625rem;
  align-items: flex-start;
  font-size: 1rem;
  line-height: 1.45;
  padding: 0.3125rem 0;
  color: var(--ios-ink);
}
.dodont__list li::before {
  content: "";
  flex-shrink: 0;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--ios-muted);
  margin-top: 0.55rem;
}

/* ----------------------------------------------------------------
   ED screen mock - intentionally NOT themed (mocks the real
   waiting-room screens which use fixed colors).
   ---------------------------------------------------------------- */
.ed-screen-mock {
  margin: 0 var(--space-xs) 0.75rem;
}
.ed-tabs {
  display: flex;
  gap: 0.375rem;
  padding: 0.125rem;
  background: var(--ios-divider);
  border-radius: var(--radius-pill);
  margin: 0.5rem auto 0.75rem;
  width: fit-content;
}
.ed-tab {
  appearance: none;
  border: none;
  background: transparent;
  font: inherit;
  font-size: 0.75rem;
  font-weight: 600;
  /* Darker than var(--ios-muted) to clear the AAA 7:1 contrast threshold
     against the .ed-tabs background (var(--ios-divider) composites to
     ~#E1E2E3). #454446 hits ~7.5:1. The active-tab color (--ios-ink) is
     already strong enough on its lighter active-state background. */
  color: #454446;
  padding: 0.4rem 0.85rem;
  border-radius: var(--radius-pill);
  cursor: pointer;
  /* Scoped, not `all`: `all` silently catches any future layout property
     and turns a class toggle into per-frame layout work. */
  transition: background var(--transition-fast), color var(--transition-fast),
    box-shadow var(--transition-fast), transform var(--transition-fast);
}
.ed-tab.is-active {
  background: var(--ios-bg-card);
  color: var(--ios-ink);
  box-shadow: var(--shadow-sm);
}
/* Dark mode: revert to the muted token (#A8A8A8) which has enough contrast on
   the darker tab-list background. The hard-coded #525252 above is light-mode
   only. */
[data-theme="dark"] .ed-tab:not(.is-active) {
  color: var(--ios-muted);
}
.ed-screen-stack { position: relative; }
.ed-screen {
  margin: 0 0 0.5rem;
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
  border: 1px solid var(--ios-border);
  font-family: "Helvetica Neue", Arial, sans-serif;
}
.ed-screen__banner {
  background: #c8e26b;
  color: #1f2a16;
  font-weight: 700;
  text-align: center;
  font-size: 0.6875rem;
  padding: 0.4rem 0.5rem;
  letter-spacing: 0.01em;
  line-height: 1.25;
}
.ed-screen__banner em {
  font-style: normal;
  background: #fff7d1;
  color: inherit;
  padding: 0 0.2rem;
  border-radius: 3px;
}
.ed-clock {
  display: grid;
  grid-template-columns: 1fr 1.1fr 1fr;
  background: #f4f6fb;
}
.ed-clock__col {
  /* Grid items default to min-width auto; without 0 the fixed-width gauge
     forces the 3-column mock wider than a 320px phone and it clips. */
  min-width: 0;
  padding: 0.75rem 0.5rem;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  min-height: 165px;
}
@media (max-width: 349px) {
  .ed-clock__col {
    padding-inline: 0.25rem;
  }
}

/* Mock colours hold AAA (7:1) text contrast: full-strength white on the
   purple (7.38:1 - no opacity fades, they composited down to ~5.8:1),
   #5F3790 purple text on the pale zone column (7.97:1). */
.ed-clock__col--purple { background: #6b3fa0; color: #fff; }
.ed-clock__col--mid    { background: #e9eef9; color: #1a1a1a; }
.ed-clock__col--zone   { background: #f4f6fb; color: #5F3790; }
.ed-clock__time-label  { font-size: 0.6875rem; }
.ed-clock__time        { font-size: 1.5rem; font-weight: 700; line-height: 1; letter-spacing: -0.01em; }
.ed-clock__divider     { width: 70%; height: 1px; background: rgba(255, 255, 255, 0.25); margin: 0.25rem 0; }
.ed-clock__waiting-lead { font-size: 0.6875rem; line-height: 1.2; }
.ed-clock__waiting-num { font-size: 1.5rem; font-weight: 800; line-height: 1; }
.ed-clock__waiting-foot { font-size: 0.625rem; line-height: 1.2; }
.ed-clock__date { font-size: 0.875rem; font-weight: 700; line-height: 1.15; }
.ed-clock__busy-q { font-size: 0.625rem; line-height: 1.2; color: #4C4C4E; margin-top: 0.25rem; }
.ed-clock__zone-pill {
  background: #6cd66c;
  /* Dark text on bright green is ~6.7:1 contrast (vs ~1.83:1 for white-on-green
     which fails axe color-contrast). The bg color is editor-overridable from
     wait-screens.json `zoneColor`, so dark text is the safer default - keeps
     legibility on any reasonably bright zoneColor an editor might set. */
  color: #0d3a0d;
  font-weight: 800;
  font-size: 0.875rem;
  padding: 0.4rem 0.6rem;
  border-radius: 6px;
  line-height: 1.05;
  margin-bottom: 0.25rem;
  /* Editor-supplied zone names ("Green/Pink Zone") have no space to break at
     the slash; without these the pill's min-content width clips the mock on
     320px phones. */
  max-width: 100%;
  overflow-wrap: anywhere;
}

@media (max-width: 349px) {
  .ed-clock__zone-pill {
    font-size: 0.8125rem;
    padding-inline: 0.4rem;
  }
}
.ed-clock__zone-num { font-size: 2.25rem; font-weight: 800; line-height: 1; }
.ed-clock__zone-label { font-size: 0.625rem; line-height: 1.2; }

.ed-gauge {
  /* Shrinks with its column on narrow phones; labels are %-positioned so
     they scale with it. */
  width: min(110px, 100%);
  aspect-ratio: 110 / 60;
  height: auto;
  position: relative;
}
.ed-gauge svg { width: 100%; height: 100%; display: block; }
.ed-gauge__labels {
  position: absolute;
  inset: 0;
  font-size: 0.5625rem;
  font-weight: 700;
  pointer-events: none;
  color: #1a1a1a;
}
.ed-gauge__labels span {
  position: absolute;
  transform: translate(-50%, -50%);
  white-space: nowrap;
}

/* The corner labels (Low first, Extreme last) sit at 10%/92%; center-anchored
   they always overhang the gauge box, which clipped the mock on 320px phones.
   Anchor them by their inner edge instead so they stay inside at any size. */
.ed-gauge__labels span:first-child {
  transform: translate(0, -50%);
}

.ed-gauge__labels span:last-child {
  transform: translate(-100%, -50%);
}

.ed-list { background: #f4f6fb; }
.ed-list__bar {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: stretch;
  background: #6b3fa0;
  color: #fff;
}
.ed-list__zone-block {
  background: #6cd66c;
  /* See .ed-clock__zone-pill for rationale - dark text for contrast on the
     editor-supplied bright-green zone bg. */
  color: #0d3a0d;
  font-weight: 800;
  font-size: 0.6875rem;
  padding: 0.5rem 0.4rem;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  line-height: 1.05;
  min-width: 56px;
}
.ed-list__center {
  text-align: center;
  padding: 0.4rem 0.25rem;
  font-weight: 700;
  font-size: 0.75rem;
  line-height: 1.2;
}
.ed-list__center small {
  display: block;
  font-weight: 500;
  opacity: 0.85;
  font-size: 0.625rem;
  margin-top: 0.1rem;
}
.ed-list__legend {
  background: #c8e26b;
  color: #1f2a16;
  font-size: 0.625rem;
  font-weight: 700;
  padding: 0.3rem 0.5rem;
  text-align: left;
  line-height: 1.2;
}
.ed-list__rows {
  padding: 0.5rem 0.625rem 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.ed-list__row {
  font-size: 0.8125rem;
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  color: #111;
}
.ed-list__row strong { font-weight: 800; letter-spacing: 0.01em; }
.ed-list__row--you {
  background: #fff5b8;
  padding: 0.2rem 0.35rem;
  border-radius: 4px;
  box-shadow: inset 0 0 0 1px #f1d65a;
}
.ed-list__row-muted { color: #555; font-weight: 500; }
.ed-list__row-you-tag {
  margin-left: auto;
  font-weight: 700;
  color: #8b6900;
}

/* ----------------------------------------------------------------
   ios-list-card: opt-in card wrapper for plain `<ul>` / `<ol>`
   blocks. Set `"cls": "ios-list-card"` on a list block in JSON to
   render it inside a cream card with iOS-style padding, shadow,
   and themed colors. Used by Amenities (WYW), the prepare-tips
   list, and the Specialist referrals list.
   ---------------------------------------------------------------- */
ul.ios-list-card,
ol.ios-list-card {
  background: var(--ios-bg-card);
  border: 1px solid var(--ios-border);
  border-radius: var(--radius-card);
  margin: 0 var(--space-xs) 0.75rem;
  padding: 1rem 1.125rem 1rem 2.25rem;
  box-shadow: var(--shadow-sm);
  list-style: disc;
  color: var(--ios-ink);
}
ol.ios-list-card { list-style: decimal; }
ul.ios-list-card li,
ol.ios-list-card li {
  margin-bottom: 0.625rem;
  font-size: var(--type-body);
  line-height: 1.5;
  color: var(--ios-ink);
}
ul.ios-list-card li:last-child,
ol.ios-list-card li:last-child {
  margin-bottom: 0;
}
ul.ios-list-card li strong,
ol.ios-list-card li strong {
  color: var(--ios-ink);
  font-weight: 600;
}
ul.ios-list-card li a,
ol.ios-list-card li a {
  color: var(--ios-accent-strong);
  font-weight: 600;
}
ul.ios-list-card li ::marker,
ol.ios-list-card li ::marker {
  color: var(--ios-muted);
}

/* ----------------------------------------------------------------
   Reduced motion
   ---------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .feature-card__dot,
  .team-tile__count-dot {
    animation: none;
  }
  .team-tile,
  .team-tile__chev,
  .test-tile,
  .test-tile__chev,
  .ed-tab {
    transition: none;
  }
}

/* -------- Press feedback (2026-07-23 smoothness pass) --------
   Every tappable surface acknowledges touch the instant the finger lands,
   before its handler runs - the single cheapest perceived-latency win.
   Mirrors the .ios-tile / .ios-pill press pattern in ios.css. Transform
   presses sit behind the reduced-motion gate; rows and pills flash their
   background instead (see .language-modal-btn:active), which reads under
   reduced motion too. The scroller arrow composes its press with the
   translateY(-50%) that positions it - a bare scale() would teleport it. */
@media (prefers-reduced-motion: no-preference) {
  .team-tile:active,
  .test-tile:active {
    transform: scale(0.97);
  }

  .scroller-arrow:active {
    transform: translateY(-50%) scale(0.9);
  }

  .theme-choice__btn:active,
  .ed-tab:active {
    transform: scale(0.96);
  }
}
