/* =============================================================================
   A4 - rules Chairside adds to the kit, kept out of the ported files.

   build/kit/port-css.py overwrites _*.css wholesale every time a component is
   re-ported, so anything hand-written there is lost on the next run. This file is
   never generated, so it is where the differences live.
   ========================================================================== */

/* A sortable column header.

   HealthExpress makes the whole <th> clickable, which gives a mouse user a
   target and a keyboard user nothing: a th is not focusable and is not announced
   as an control. So the header holds a real button, and the th keeps aria-sort.
   The button then has to be stripped back to looking like a header, which is
   what these rules do -- without them it renders as a form field sitting in the
   table head. */
.s-table th .s-table-sort {
  display: inline-flex;
  align-items: center;
  gap: var(--s-gap-1);
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  cursor: pointer;
}

.s-table th .s-table-sort:hover { color: var(--accent); }

/* The direction glyph. Dim until the column is the one being sorted on, so a
   header row does not read as eight active controls. */
.s-table th .s-table-sort-glyph {
  font-size: .9em;
  line-height: 1;
  opacity: .35;
}

.s-table th[aria-sort] .s-table-sort { color: var(--accent); }
.s-table th[aria-sort] .s-table-sort-glyph { opacity: 1; }

/* A row that navigates somewhere on click says so. */
.s-table tbody tr.clickable { cursor: pointer; }

/* Loading rows: the table keeps its height while a page is fetched, so the
   footer and everything below it do not jump. */
.s-table-skeleton {
  display: block;
  block-size: 1em;
  border-radius: var(--r1);
  background: linear-gradient(90deg,
      var(--surface-2) 25%, var(--surface-3) 37%, var(--surface-2) 63%);
  background-size: 400% 100%;
  animation: s-table-shimmer 1.2s ease-in-out infinite;
}

@keyframes s-table-shimmer {
  from { background-position: 100% 50%; }
  to   { background-position: 0 50%; }
}

@media (prefers-reduced-motion: reduce) {
  .s-table-skeleton { animation: none; }
}

/* The pager sits under the table, count on one side, controls on the other. */
.s-datatable-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
  flex-wrap: wrap;
  padding: var(--s-spacer-3) 0 0;
}

/* .s-page-link and .s-page-current were invented here and matched nothing in the
   ported stylesheet, so the pager rendered as two bare browser buttons. The kit
   already ships .s-pagination-item / -link / .active / .disabled / -ellipsis;
   the table uses those now and this file adds nothing. */

/* The lookup control: a value box with its clear and search buttons inside the
   same bordered box, so the three read as one control rather than a field with
   two buttons parked beside it. */
.s-lookup { display: flex; align-items: stretch; }

.s-lookup .s-form-control {
  border-start-end-radius: 0;
  border-end-end-radius: 0;
  flex: 1;
  min-inline-size: 0;
}

.s-lookup-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--ctl-h);
  border: var(--s-border-width) solid var(--s-input-border-color);
  border-inline-start: 0;
  background: var(--surface-2);
  color: var(--ink-2);
  cursor: pointer;
}

.s-lookup-btn:hover { background: var(--surface-3); color: var(--ink); }

.s-lookup-btn:last-child {
  border-start-end-radius: var(--s-input-border-radius);
  border-end-end-radius: var(--s-input-border-radius);
}

.s-lookup-search { background: var(--accent-soft); color: var(--accent); }
.s-lookup-search:hover { background: var(--accent); color: var(--on-accent); }

/* The dialog's criteria row: the field takes the width, the button takes what it
   needs, and they sit on a shared baseline rather than the field's. */
.s-lookup-criteria {
  display: flex;
  gap: var(--gap);
  align-items: flex-end;
  margin-block-end: var(--gap);
}

.s-lookup-criteria .s-form-group { flex: 1; margin-block-end: 0; }

/* <dialog> in the top layer: the platform paints ::backdrop, so the ported
   .s-dialog-backdrop div is not used and these rules replace it. */
.s-dialog::backdrop { background: color-mix(in srgb, var(--ink) 55%, transparent); }

/* A closed <dialog> must stay hidden.

   The browser hides it through a UA rule, dialog:not([open]) { display: none },
   which any author-level display wins against. HealthExpress's .s-dialog was
   written for a div and sets display:flex to make a full-screen backdrop
   container -- applied to a real <dialog> that defeats the UA rule, and a closed
   dialog renders inline in the middle of the page with the browser's default
   black border. Restoring it is the whole fix, and it is worth knowing as a class
   of problem: CSS written for a div does not always survive being pointed at the
   native element that replaces it. */
dialog.s-dialog:not([open]) { display: none; }

/* The dialog is the frame; the panel inside it carries the size class, which is
   how the ported stylesheet expects it. */
.s-dialog[open] {
  border: var(--s-border-width) solid var(--line);
  border-radius: var(--r3);
  background: var(--surface);
  color: var(--ink);
  padding: 0;
  max-inline-size: 96vw;
  max-block-size: 86vh;
  overflow: hidden;
}

.s-dialog .s-dialog-panel { display: flex; flex-direction: column; max-block-size: 86vh; }
.s-dialog .s-dialog-body { overflow: auto; padding: var(--pad); }

/* A single field should not stretch to a full-width card; a lookup at 1400px is
   a target you have to travel to. */
.kit-form-narrow { max-width: 460px; }

/* A result grid must not resize as the results change: a dialog 385px wide when
   empty and 604px with eight rows moves the row you were about to click. Sized on
   the dialog, because <dialog> is width:fit-content and a minimum on the panel has
   no containing block to push against. */
.s-dialog.s-dialog-xl[open] { inline-size: min(94vw, 820px); }
.s-dialog.s-dialog-lg[open] { inline-size: min(92vw, 640px); }
.s-dialog.s-dialog-sm[open] { inline-size: min(92vw, 420px); }
.s-dialog .s-dialog-panel { inline-size: 100%; }

/* Loading a new page dims the current one rather than replacing it. The rows keep
   their height, so nothing under the pointer moves, and they stop responding so a
   second click cannot land on a row that is about to be replaced. */
.s-table tbody.s-table-busy {
  opacity: .45;
  pointer-events: none;
  transition: opacity var(--dur) var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  .s-table tbody.s-table-busy { transition: none; }
}

/* The select's editor is a <button>, so it can be reached by keyboard and is
   announced as a control — but a button centres its text, and .s-combobox-editor
   was written for a div and never resets it. Left as-is, every chosen value sits
   in the middle of the field while every other field in the form starts at the
   left edge. Third instance of the same class of problem: ported CSS assumes the
   element it was written for. */
.s-combobox-editor { text-align: start; }
.s-combobox-editor .s-combobox-display,
.s-combobox-editor .s-combobox-placeholder { text-align: start; }

/* Route tabs on a record workspace. The kit's tab styles assume buttons in a
   tablist; these are links, because a tab here is a place with an address. */
.ws-tabs { display: flex; gap: 2px; margin-bottom: var(--gap); border-bottom: 1px solid var(--line); }
.ws-tabs .s-tab-link { text-decoration: none; }

.finder-actions { display: flex; gap: var(--gap); align-items: center; margin-top: var(--gap); }

/* Registration is a single column of decisions, not a full-width form. A field
   stretched to 1400px is a target you have to travel to. */
.reg-narrow { max-width: 900px; }
.reg-note { max-width: 62ch; margin-bottom: var(--gap); }

/* What NPHIES would still need from a patient record: short sentences, one per gap. */
.nphies-gaps { margin: 4px 0 0; padding-inline-start: 18px; max-width: 80ch; }
.nphies-gaps li + li { margin-top: 2px; }

/* The branch switcher lives in a 52px header bar, so its control has to fit that
   rather than a form row. */
.branch .s-combobox-editor { min-block-size: 30px; block-size: 30px; padding-block: 0; }
.branch .s-combobox { min-inline-size: 150px; }

/* Form rhythm.

   .s-form-group carries margin-block-end for groups stacked in normal flow. Inside
   .s-form-grid that margin lands on top of the grid's own row-gap, so rows sat 32px
   apart while a label sat 6px from its value -- better than five to one, which reads
   as labels floating above values they do not belong to. The grid owns the spacing;
   the group stops adding its own. */
.s-form-grid .s-form-group { margin-block-end: 0; }

.s-form-grid {
  row-gap: 18px;
  column-gap: 28px;
}

/* A little more air under the label, so the pair reads as one thing without the
   row above crowding it. */
.s-form-grid .s-form-label { margin-block-end: 5px; }

/* A section is a group of rows; the space between sections has to beat the space
   between rows or the grouping does no work. */
.s-form-section + .s-form-section { margin-block-start: 28px; }

/* Branch switcher: a button that says where you are, and a dialog for changing it. */
.branch-current {
  display: inline-flex; align-items: center; gap: 8px;
  block-size: 30px; padding-inline: 10px;
  border: var(--s-border-width) solid var(--line);
  border-radius: var(--r1);
  background: var(--surface); color: var(--ink);
  font: inherit; font-size: var(--ui-sm); cursor: pointer;
}
.branch-current:hover { border-color: var(--accent); color: var(--accent); }
.branch-code {
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  padding: 1px 5px; border-radius: var(--r1);
  background: var(--accent-soft); color: var(--accent);
}
.branch-name { font-weight: 600; white-space: nowrap; }

.branch-search { margin-block-end: var(--gap); }

/* Two columns, so fifty branches are scanned rather than scrolled. One column on a
   narrow screen, because two 200px columns is worse than one readable one. */
.branch-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: 8px; list-style: none; padding: 0; margin: 0;
  max-block-size: 52vh; overflow-y: auto;
}

.branch-option {
  display: flex; align-items: center; gap: 10px; inline-size: 100%;
  padding: 9px 11px; text-align: start;
  border: var(--s-border-width) solid var(--line);
  border-radius: var(--r2);
  background: var(--surface); color: var(--ink);
  font: inherit; cursor: pointer;
}
.branch-option:hover { border-color: var(--accent); background: var(--accent-soft); }
.branch-option.current { border-color: var(--accent); }

.branch-option-code {
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  padding: 2px 6px; border-radius: var(--r1);
  background: var(--surface-2); color: var(--ink-2); flex: none;
}
.branch-option:hover .branch-option-code,
.branch-option.current .branch-option-code { background: var(--accent); color: var(--on-accent); }

.branch-option-body { display: flex; flex-direction: column; min-inline-size: 0; }
.branch-option-name { font-weight: 600; }
.branch-option-city { font-size: var(--ui-sm); color: var(--ink-3); }
.branch-option-here {
  margin-inline-start: auto; font-size: 10.5px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--accent);
}

/* Appointment board control bar: day navigation, date, specialty and who is shown,
   all on one row. They are the same decision made in sequence. */
.board-bar {
  display: flex; align-items: flex-start; gap: 18px; flex-wrap: wrap;
}
.board-bar .s-form-group { margin-block-end: 0; }
.board-bar-date { inline-size: 190px; }
.board-bar-specialty { inline-size: 200px; }
.board-bar-end { margin-inline-start: auto; }
/* Day, week, month, timeline (S3): one segmented control, labelled like the fields beside it. */
.board-views {
  display: inline-flex;
  block-size: var(--ctl-h);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.board-view {
  font: inherit;
  padding-inline: 12px;
  background: var(--surface);
  color: var(--ink-2);
  border: 0;
  border-inline-start: 1px solid var(--line);
  cursor: pointer;
}
.board-view:first-child { border-inline-start: 0; }
.board-view[aria-pressed="true"] { background: var(--accent-soft); color: var(--ink); font-weight: 600; }
.board-view:focus-visible { outline: var(--focus-ring); outline-offset: -2px; }
.board-bar-week { inline-size: 240px; }

.board-daynav-group { display: flex; flex-direction: column; }
.board-daynav-spacer { display: block; }
.board-daynav { display: inline-flex; gap: 6px; }
.board-daynav-btn { padding-inline: 9px; }

/* A chip names the resource and tags its specialty: covering two specialties, a
   name alone does not say which board column belongs to which. */
.board-chip-name { font-weight: 600; }
.board-chip-spec {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .02em;
  padding: 1px 5px; border-radius: var(--r1);
  background: var(--surface-2); color: var(--ink-3);
}
/* Presence, not a value: Blazor renders data-on="@(bool)" as a bare attribute
   when true and omits it when false, so [data-on="True"] matches nothing. */
.board-chip[data-on] .board-chip-spec { background: var(--accent-soft); color: var(--accent); }

/* The dialog, for when there are more resources than chips can carry. */
.board-pick-bar { display: flex; align-items: flex-end; gap: var(--gap); margin-block-end: var(--gap); }
.board-pick-bar .s-form-group { flex: 1; margin-block-end: 0; }

.board-pick-group + .board-pick-group { margin-block-start: 18px; }
.board-pick-group-head {
  display: flex; align-items: center; gap: 10px; margin-block-end: 8px;
  padding-block-end: 5px; border-block-end: 1px solid var(--line-2);
}

.board-pick-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr));
  gap: 6px; list-style: none; padding: 0; margin: 0;
}
.board-pick-item {
  display: flex; align-items: center; gap: 9px; padding: 7px 10px;
  border: 1px solid var(--line); border-radius: var(--r1);
  cursor: pointer; font-size: var(--ui);
}
.board-pick-item:hover { border-color: var(--accent); }
.board-pick-item[data-on] { border-color: var(--accent); background: var(--accent-soft); }
.board-pick-item input { accent-color: var(--accent); }
.board-pick-name { font-weight: 600; }
.board-pick-slot { margin-inline-start: auto; font-size: var(--ui-sm); color: var(--ink-3); }

/* The waiting queue. Compact rows, because it sits above the board and the board is
   what the receptionist is actually looking at. */
.queue { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }

.queue-row {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 12px;
  border: 1px solid var(--line); border-radius: var(--r1);
}

/* Half an hour is where a wait stops being normal and starts being a complaint.

   Presence, not a value: Blazor renders data-long="@(x > 30)" as a bare attribute
   when true and omits it when false, so [data-long="True"] never matches anything. */
.queue-row[data-long] { border-color: var(--warn); background: var(--warn-soft); }

.queue-wait {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-weight: 600; min-inline-size: 46px;
}
.queue-who { display: flex; flex-direction: column; min-inline-size: 0; flex: 1; }
.queue-name { font-weight: 600; }
.queue-svc { font-size: var(--ui-sm); color: var(--ink-3); }

/* The day navigator. Arrows either side of the date, because that is what they
   move; Today follows, disabled rather than hidden when there is nothing to do. */
.daynav-group { display: flex; flex-direction: column; gap: 2px; }
.daynav-spacer { visibility: hidden; }
.daynav { display: flex; align-items: stretch; gap: 6px; }
.daynav-btn { padding-inline: 8px; }
.daynav-date { inline-size: 9.5rem; }
.daynav-hijri { font-size: var(--ui-sm); color: var(--ink-3); padding-inline-start: 2px; }

/* The front desk. Grid on the left, the waiting list beside it: the list is short,
   glanced at constantly, and must not be a tab the desk forgets to open. */
.desk { display: grid; grid-template-columns: minmax(0, 1fr) 22rem; gap: 16px; align-items: start; }
.desk-bar { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; }
.desk-bar-end { margin-inline-start: auto; display: flex; gap: 8px; align-items: flex-end; }

@media (max-width: 1100px) {
  .desk { grid-template-columns: minmax(0, 1fr); }
}

/* Pending services: what the clinic finished and the desk has not dealt with. */
.pending { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.pending-row {
  display: flex; align-items: baseline; gap: 10px;
  padding: 8px 12px; border: 1px solid var(--line); border-radius: var(--r1);
}
.pending-desc { flex: 1; min-inline-size: 0; }
.pending-qty { font-family: var(--font-mono); font-variant-numeric: tabular-nums; color: var(--ink-3); }

/* The desk's grid carries names and service descriptions, both of which are long
   and neither of which should become a three-line paragraph in a 90px column. The
   widths above give each column its share; this stops the short ones wrapping. */
.desk td, .desk th { vertical-align: middle; }

/* Choosing which visit to bill. One row each, because the distinguishing facts are
   the date and the clinic and both have to be readable at a glance. */
.visit-pick { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }

.visit-pick-item {
  inline-size: 100%;
  display: flex; align-items: center; gap: 14px;
  padding: 10px 12px;
  border: 1px solid var(--line); border-radius: var(--r1);
  background: var(--surface); color: inherit;
  font: inherit; text-align: start; cursor: pointer;
}

.visit-pick-item:hover { border-color: var(--accent); }
.visit-pick-item[data-on] { border-color: var(--accent); background: var(--accent-soft); }

.visit-pick-when {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  color: var(--ink-2); min-inline-size: 7.5rem;
}
.visit-pick-who { display: flex; flex-direction: column; min-inline-size: 0; }

/* The palette. Wide enough to read, dense enough that a full-mouth chart does not
   need scrolling between every tooth. */
.palette { display: flex; flex-direction: column; gap: 10px; }
.palette-group { display: flex; flex-direction: column; gap: 4px; }
.palette-name { font-size: var(--ui-sm); color: var(--ink-3); font-weight: 600; }
.palette-marks { display: flex; flex-wrap: wrap; gap: 4px; }

.palette-mark {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 9px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: inherit; font: inherit; font-size: var(--ui-sm);
  cursor: pointer;
}

.palette-mark:hover { border-color: var(--accent); }
.palette-mark[data-on] { border-color: var(--accent); background: var(--accent-soft); }

.palette-dot { inline-size: 8px; block-size: 8px; border-radius: 50%; background: var(--ink-3); }
.palette-dot[data-cat="patho"] { background: var(--neg); }
.palette-dot[data-cat="resto"] { background: var(--accent); }
.palette-dot[data-cat="endo"] { background: var(--warn); }
.palette-dot[data-cat="prosth"] { background: var(--ink-3); }
.palette-dot[data-cat="base"] { background: var(--line); }

.chart-bar { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; }
.chart-bar-end { margin-inline-start: auto; display: flex; gap: 8px; align-items: flex-end; }

/* The consultation note. Two columns for the short answers, full width for the
   narrative, because a complaint is a phrase and a history is a paragraph. */
.note-grid { display: grid; grid-template-columns: 2fr 1fr; gap: 12px; }

@media (max-width: 700px) { .note-grid { grid-template-columns: 1fr; } }

.exam-region { display: flex; flex-direction: column; gap: 4px; margin-block: 8px; }
.exam-region-name { font-size: var(--ui-sm); color: var(--ink-3); font-weight: 600; }

.note-read { display: flex; flex-direction: column; gap: 10px; margin: 0; }
.note-read dt { font-size: var(--ui-sm); color: var(--ink-3); margin-block-end: 2px; }
.note-read dd { margin: 0; white-space: pre-wrap; }
.note-by { font-size: var(--ui-sm); margin-block-start: 12px; }

/* What the patient was told, in both languages at once. The English is what the
   record is read in and the Arabic is what the patient was handed, and a clinician
   checking one against the other must not have to open two screens. */
.advice-read { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }

.advice-read li {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  padding-inline-start: 12px; border-inline-start: 2px solid var(--line);
}

.advice-read .advice-ar { color: var(--ink-3); font-size: var(--ui-sm); }

/* The sheet the patient carries out. Bigger than anything else the application
   prints, because it is read without the clinic there to explain it, and often by
   somebody who has just had an injection and is not at their sharpest. */
.advice-sheet { list-style: none; margin: 0 0 12px; padding: 0; display: flex; flex-direction: column; gap: 10px; }

/* Held to a reading measure so the Arabic and the English under it stay one pair.
   Across the full width of a card they drift to opposite edges and read as two
   separate columns, which is exactly what a translation must not look like. */
.advice-sheet li {
  display: flex; flex-direction: column; gap: 2px;
  max-width: 52ch;
  padding-inline-start: 14px; border-inline-start: 3px solid var(--accent);
}

.advice-sheet-ar { font-size: 1.15rem; line-height: 1.7; }
.advice-sheet-en { color: var(--ink-3); }
.advice-sheet-free { white-space: pre-wrap; margin: 0 0 12px; }
.advice-sheet-foot { margin-block-start: 18px; color: var(--ink-3); }

/* The standing history. Flags first because they are what changes today's
   treatment; the prose is context underneath. */
.hx-flags { display: flex; flex-wrap: wrap; gap: 4px; }
.hx-stale { color: var(--warn); }

/* Proposals from the chart. One row each, the kind first so the eye can group
   diagnoses from charges without reading every line. */
.prop-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }

.prop-row {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 12px; border: 1px solid var(--line); border-radius: var(--r1);
}

.prop-pick { display: flex; align-items: center; gap: 8px; cursor: pointer; }

.prop-kind {
  font-size: var(--ui-sm); font-weight: 600;
  padding: 1px 8px; border-radius: 999px;
  background: var(--line); color: var(--ink-2);
  min-inline-size: 68px; text-align: center;
}

.prop-kind[data-kind="Diagnosis"] { background: var(--neg); color: var(--on-accent); }
.prop-kind[data-kind="ServiceOrder"] { background: var(--accent); color: var(--on-accent); }
.prop-kind[data-kind="PlanItem"] { background: var(--warn); color: var(--on-accent); }

.prop-what { display: flex; flex-direction: column; flex: 1; min-inline-size: 0; }
.prop-name { font-weight: 600; }
/* The secondary line under something: why a deadline is what it is, what a
   department needs to know, which code has no price. Always a trailing
   explanation, so always its own line — inline it ran straight into the text
   above it ("beforehand.For the department:") on the hand-over sheet. */
.prop-why { display: block; font-size: var(--ui-sm); color: var(--ink-3); }
.prop-code { font-size: var(--ui-sm); color: var(--ink-3); }

/* The treatment plan, in the visit. Grouped by phase because that is the order the
   work happens in, and a patient reading it wants to know what comes first. */
.plan-head { display: flex; align-items: center; gap: 10px; margin-block-end: 10px; }
.plan-title { font-weight: 600; }
.plan-total { font-variant-numeric: tabular-nums; font-weight: 600; }

.plan-phase { margin-block: 10px; }
.plan-phase-name { font-size: var(--ui-sm); color: var(--ink-3); font-weight: 600; }

.plan-items { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }

.plan-item {
  display: flex; align-items: center; gap: 12px;
  padding: 7px 12px; border: 1px solid var(--line); border-radius: var(--r1);
}

/* Work already done reads as settled rather than outstanding. */
.plan-item[data-status="Completed"] { opacity: 0.6; }
.plan-item[data-status="Declined"] { opacity: 0.5; text-decoration: line-through; }

.plan-what { display: flex; flex-direction: column; flex: 1; min-inline-size: 0; }
.plan-fee { font-variant-numeric: tabular-nums; color: var(--ink-2); }

.plan-decide { margin-block-start: 14px; padding-block-start: 12px; border-block-start: 1px solid var(--line); }
.plan-pick { display: flex; align-items: center; gap: 8px; padding-block: 3px; cursor: pointer; }

/* Free start times. A grid rather than a drop-down: a dentist choosing between
   eleven slots wants to see the shape of the day, not scroll a list. */
.slot-grid {
  list-style: none; margin: 8px 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); gap: 6px;
}

.slot {
  inline-size: 100%; padding: 7px 4px;
  border: 1px solid var(--line); border-radius: var(--r1);
  background: var(--surface); color: inherit;
  font: inherit; font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  cursor: pointer;
}

.slot:hover { border-color: var(--accent); }
.slot[data-on] { border-color: var(--accent); background: var(--accent-soft); font-weight: 600; }

/* A "?" beside a setting (SHelp). The popover is the browser's own, so it sits
   in the top layer, centred, above any dialog, and closes on Escape or a click
   outside. */
.s-help { display: inline-flex; vertical-align: middle; }
.s-help-q {
  inline-size: 1.25rem; block-size: 1.25rem; border-radius: 50%;
  border: 1px solid var(--accent); background: transparent; color: var(--accent);
  font: 600 0.75rem/1 var(--font-ui); cursor: pointer; padding: 0;
  display: inline-grid; place-items: center;
}
.s-help-q:hover, .s-help-q:focus-visible { background: var(--accent); color: var(--on-accent); }
.s-help-q:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.s-help-pop {
  inline-size: min(26rem, 92vw); padding: var(--s-gap-4); margin: auto;
  border: 1px solid var(--line); border-radius: 10px;
  background: var(--surface-2, var(--bg)); color: var(--ink); box-shadow: var(--shadow-3);
  font-size: var(--s-font-size-sm); line-height: 1.55; text-align: start;
}
.s-help-pop::backdrop { background: color-mix(in srgb, var(--ink) 14%, transparent); }
.s-help-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-gap-3); margin-block-end: var(--s-gap-2); }
.s-help-title { font-weight: 600; font-size: var(--s-font-size-base); }
.s-help-x { border: 0; background: none; color: var(--ink-3); font-size: 1.25rem; line-height: 1; cursor: pointer; padding: 0; }
.s-help-text { margin: 0 0 var(--s-gap-2); }
.s-help-k {
  margin-block: var(--s-gap-3) var(--s-gap-1); font-size: var(--s-font-size-xs);
  text-transform: uppercase; letter-spacing: .07em; color: var(--ink-3); font-weight: 600;
}
.s-help-calc {
  margin: 0; padding: var(--s-gap-2) var(--s-gap-3); border-radius: 6px;
  background: var(--bg); font: 0.8rem/1.5 var(--font-mono); white-space: pre-wrap;
}

/* A group of radio options, all visible (SChoice). */
.s-choice { border: 0; margin: 0 0 var(--s-gap-3); padding: 0; min-inline-size: 0; }
.s-choice-legend { font-weight: 600; font-size: var(--s-font-size-sm); margin-block-end: var(--s-gap-2); padding: 0; display: flex; gap: var(--s-gap-2); align-items: center; }
.s-choice-option { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-gap-2); padding-block: 2px; }
.s-choice-option .s-form-check-input { margin: 0; }
.s-choice-default {
  font-size: var(--s-font-size-xs); font-weight: 600; color: var(--pos);
  background: var(--pos-soft); border-radius: 999px; padding: 1px 8px;
}

/* -----------------------------------------------------------------------------
   Form alignment. Fields of one row were uneven, a button sat below the input it
   belongs to, and sections touched. Four causes, each fixed once here.
   ---------------------------------------------------------------------------- */

/* 1. One height for every one-line control: the text input's. The combobox kept
   the kit's own 2.5rem + 2px, six pixels taller than the input beside it. The
   small variant keeps its own (its selector is more specific). */
:root {
  --s-control-block-size: calc(var(--s-input-font-size) * var(--s-input-line-height) + 2 * var(--s-input-padding-y) + 2 * var(--s-border-width, 1px));
}
.s-combobox-editor { min-block-size: var(--s-control-block-size); }

/* 2. The field wrapper spaces fields stacked down a page. A combobox inside one
   added a second 16px of its own, so in a row aligned by the bottom edge every
   dropdown stood 16px above the inputs beside it. The wrapper owns the spacing. */
.s-form-group > .s-combobox { margin-block-end: 0; }

/* 3. A row of fields with the button that acts on them: lined up by the bottom
   edge of the input, which the wrapper's stacking margin pushed 16px below the
   button. A screen's own layout for the row (a grid of fixed columns) still wins. */
.s-field-row,
.row.s-field-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 12px;
  align-items: flex-end;
}
.s-field-row > .s-form-group { margin-block-end: 0; }

/* In a flex row the fields share the width and the buttons keep their own; a
   screen's rule cannot reach the field's wrapper without ::deep, so this is
   where it is said. In a grid row the screen's columns decide. */
.s-field-row > .s-form-group { flex: 1 1 12rem; min-inline-size: 0; }

/* A field with help or an error under it is taller than its input, so lining up
   by the bottom edge would put the button beside the help text. Such a row lines
   up by the top instead, and the button steps down by one label's height. */
.s-field-row:has(> .s-form-group > :is(.s-form-text, .s-invalid-feedback)) { align-items: flex-start; }
.s-field-row > .s-form-group > .s-form-label { display: block; }
.s-field-row:has(> .s-form-group > :is(.s-form-text, .s-invalid-feedback)):has(> .s-form-group > .s-form-label) > .s-btn {
  margin-block-start: calc(1.5 * var(--s-font-size-sm) + 0.375rem);
}

/* 4. The spacing every screen uses (class "mt" and "mb", several hundred times)
   but only a few components defined for themselves, so everywhere else the gap
   between one section and the next was nothing. A component's own value wins. */
.mt { margin-block-start: 14px; }
.mb { margin-block-end: 14px; }

/* Two cards one after the other in the page itself. */
main.content > .s-card + .s-card { margin-block-start: 14px; }

/* ---------------------------------------------------------------------------
   Focus ring, keyboard paths (QA assessment 004)

   One ring for every interactive control in the kit: 2px of the accent, 2px off
   the control (tokens.css --focus-ring). base.css draws it for anything focused
   from the keyboard; these rules are the kit controls whose ported styles say
   "outline: none" with a class of their own, so the catch-all alone would lose to
   them on a later re-port. The ported files are generated, so the rules live here.
   --------------------------------------------------------------------------- */
.s-btn:focus-visible,
.s-form-control:focus-visible,
.s-form-select:focus-visible,
.s-form-check-input:focus-visible,
.s-form-switch-input:focus-visible,
.s-combobox-editor:focus-visible,
.s-combobox-search-input:focus-visible,
.s-pagination-link:focus-visible,
.s-tab-link:focus-visible,
.s-table th .s-table-sort:focus-visible,
.s-lookup-btn:focus-visible,
.s-table-row-link:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
}

/* The filter box sits flush in a scrolling panel that clips anything outside it,
   so its ring is drawn inside. */
.s-combobox-search-input:focus-visible { outline-offset: -2px; }

/* A clickable table row that is its own tab stop. The ring is drawn inside the
   row: the table scrolls sideways in a wrapper that clips anything outside. */
.s-table > tbody > tr[data-kb-activate]:focus-visible {
  outline: var(--focus-ring);
  outline-offset: -2px;
}

/* The link that makes a navigating row reachable. It keeps the cell's look: the
   row is the target for the mouse, the link is the stop for the keyboard. */
.s-table-row-link {
  color: inherit;
  text-decoration: none;
}
.s-table-row-link:hover { text-decoration: underline; text-underline-offset: 2px; }

/* The option the arrow keys are on. Same wash as the pointer's hover, plus an
   inset edge so it still reads when it is also the chosen option. */
.s-combobox-item.s-combobox-item-active {
  background-color: var(--s-primary-tint);
  box-shadow: inset 3px 0 0 var(--accent);
}
[dir="rtl"] .s-combobox-item.s-combobox-item-active {
  box-shadow: inset -3px 0 0 var(--accent);
}

/* A roving set (kit/keyboard.js): every stop but one is tabindex -1, which base.css
   leaves unringed for Blazor's heading focus. These are controls, so they ring. */
[data-roving]:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
}
