/* ==========================================================================
   RehabDox Doctor Office Portal - authentication screens
   Tokens and layout taken from PORTAL_MOCKUP_APPROVED.html (screen 01).
   Self contained on purpose: the portal must never load staff CSS.
   ========================================================================== */

:root {
  color-scheme: light dark;

  --brand:      #1878c4;
  --green:      #2f9e57;
  --amber:      #b0761c;
  --red:        #c0392b;

  --bg:        #f4f7fb;
  --surface:   #ffffff;
  --surface-2: #eef3f9;
  --line:      #dbe4ee;
  --line-soft: #e9eff6;
  --ink:       #0f1b2a;
  --ink-2:     #35455a;
  --muted:     #64768c;

  --shadow: 0 1px 2px rgba(15, 27, 42, .06), 0 8px 24px -12px rgba(15, 27, 42, .18);
  --radius: 10px;

  --sans: ui-sans-serif, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "Cascadia Mono", "Segoe UI Mono", Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:        #0c1521;
    --surface:   #121d2b;
    --surface-2: #172434;
    --line:      #263548;
    --line-soft: #1d2b3c;
    --ink:       #e8eef6;
    --ink-2:     #bcc9d8;
    --muted:     #8698ad;
    --brand:     #4ea3e8;
    --green:     #4cb877;
    --amber:     #d69b3c;
    --red:       #e8776a;
    --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 10px 28px -14px rgba(0, 0, 0, .7);
  }
}

:root[data-theme="dark"] {
  --bg:        #0c1521;
  --surface:   #121d2b;
  --surface-2: #172434;
  --line:      #263548;
  --line-soft: #1d2b3c;
  --ink:       #e8eef6;
  --ink-2:     #bcc9d8;
  --muted:     #8698ad;
  --brand:     #4ea3e8;
  --green:     #4cb877;
  --amber:     #d69b3c;
  --red:       #e8776a;
  --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 10px 28px -14px rgba(0, 0, 0, .7);
}

:root[data-theme="light"] {
  --bg:        #f4f7fb;
  --surface:   #ffffff;
  --surface-2: #eef3f9;
  --line:      #dbe4ee;
  --line-soft: #e9eff6;
  --ink:       #0f1b2a;
  --ink-2:     #35455a;
  --muted:     #64768c;
  --brand:     #1878c4;
  --green:     #2f9e57;
  --amber:     #b0761c;
  --red:       #c0392b;
  --shadow: 0 1px 2px rgba(15, 27, 42, .06), 0 8px 24px -12px rgba(15, 27, 42, .18);
}

* { box-sizing: border-box; }

body.portal-body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--brand); }
:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 4px; }

[hidden] { display: none !important; }

/* ---------- brand mark ---------- */

/*
   One asset, /images/rehabdox_logo.png, shared with the staff app so a
   rebrand lands in one place. It carries its own wordmark, so there is no
   separate text wordmark to keep in step with it.

   Sized by height with width auto, never the other way round: the file is a
   wide lockup and fixing the width would crop or squash it.
*/
.mark { display: inline-flex; align-items: center; }
.appbar-logo { display: block; height: 26px; width: auto; }

/* ---------- auth shell ---------- */

.portal-auth {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 24px;
}

.auth-card {
  width: 100%;
  max-width: 940px;
  display: grid;
  grid-template-columns: 1.05fr .95fr;
  min-height: 460px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: var(--shadow);
}

/*
   Fixed dark in both themes. Deliberate, not a missed dark mode.

   Content is centred vertically rather than pushed to the top. The mockup had a
   spacer here holding a footer block to the bottom; the footer was cut, so the
   spacer was left propping up nothing. Centring balances this panel against the
   sign in form opposite, which is centred too.
*/
.auth-pitch {
  background: linear-gradient(160deg, #0a2540 0%, #0d3157 62%, #10416f 100%);
  color: #dce8f5;
  padding: 40px 44px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 26px;
}
.auth-pitch h2 {
  margin: 0;
  font-size: 30px;
  line-height: 1.16;
  letter-spacing: -.022em;
  font-weight: 640;
  color: #fff;
  text-wrap: balance;
  max-width: 15ch;
}
.auth-pitch p { margin: 0; max-width: 40ch; color: #a9c2db; font-size: 14.5px; }

.auth-panel {
  padding: 40px 44px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 18px;
}
/*
   align-self keeps the logo hard left against the form fields below it. The
   panel is a centred flex column, so without this the lockup would sit
   centred over left aligned labels.
*/
.auth-logo {
  display: block;
  height: 32px;
  width: auto;
  align-self: flex-start;
  margin-bottom: 6px;
}

.auth-panel h1 { margin: 0; font-size: 24px; font-weight: 650; letter-spacing: -.018em; }
.auth-panel .sub { margin: -10px 0 0; font-size: 13.5px; color: var(--muted); }

.step { display: flex; flex-direction: column; gap: 18px; }
.step form { display: flex; flex-direction: column; gap: 18px; margin: 0; }

/* ---------- fields ---------- */

.field { display: grid; gap: 6px; }
.field label { font-size: 12.5px; font-weight: 570; color: var(--ink-2); }
.field input {
  font: inherit;
  padding: 11px 13px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  width: 100%;
}
.field input::placeholder { color: var(--muted); }
.field input:disabled,
.field input[readonly] {
  background: var(--surface-2);
  color: var(--ink-2);
  cursor: default;
}

.btn {
  font: inherit;
  font-weight: 600;
  font-size: 14.5px;
  cursor: pointer;
  border: 1px solid transparent;
  border-radius: 8px;
  padding: 11px 16px;
  background: var(--brand);
  color: #fff;
  width: 100%;
}
.btn:disabled { opacity: .6; cursor: default; }

.btn-link {
  font: inherit;
  font-size: 13px;
  font-weight: 550;
  background: none;
  border: 0;
  padding: 0;
  color: var(--brand);
  cursor: pointer;
}
.btn-link:disabled { color: var(--muted); cursor: default; }
.btn-link.quiet { color: var(--muted); }

.helper { margin: 0; font-size: 12.5px; color: var(--muted); }
.helper.center { text-align: center; }

/* ---------- alerts ---------- */

.alert {
  margin: 0;
  font-size: 13.5px;
  padding: 10px 13px;
  border-radius: 8px;
  border: 1px solid;
}
.alert.error {
  color: var(--red);
  border-color: color-mix(in srgb, var(--red) 40%, transparent);
  background: color-mix(in srgb, var(--red) 9%, transparent);
}
.alert.success {
  color: var(--green);
  border-color: color-mix(in srgb, var(--green) 40%, transparent);
  background: color-mix(in srgb, var(--green) 9%, transparent);
}
.alert.info {
  color: var(--ink-2);
  border-color: var(--line);
  background: var(--surface-2);
}

/* ---------- OTP ---------- */

.otp-head { display: grid; gap: 3px; text-align: center; }
.otp-head h1 { font-size: 21px; }
.otp-head p { margin: 0; font-size: 13.5px; color: var(--muted); }
.otp-head .addr { color: var(--ink); font-weight: 620; font-family: var(--mono); font-size: 13px; }

.otp-inputs { display: flex; gap: 8px; justify-content: center; }
.otp-digit {
  font: inherit;
  font-size: 20px;
  font-weight: 620;
  text-align: center;
  width: 46px;
  padding: 10px 0;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.check { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--ink-2); }
.check input { width: 16px; height: 16px; margin: 0; accent-color: var(--brand); }

/* ---------- password rules ---------- */

.rules { margin: 0; padding: 0; list-style: none; display: grid; gap: 4px; }
.rules li {
  font-size: 12.5px;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 7px;
}
.rules li::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--line);
  flex: none;
}
.rules li.met { color: var(--green); }
.rules li.met::before { background: var(--green); }

.meter { display: grid; gap: 5px; }
.meter-track {
  height: 4px;
  border-radius: 99px;
  background: var(--line-soft);
  overflow: hidden;
}
.meter-fill {
  height: 100%;
  width: 0;
  border-radius: 99px;
  background: var(--amber);
  transition: width .18s ease;
}
.meter-fill.weak   { background: var(--red); }
.meter-fill.fair   { background: var(--amber); }
.meter-fill.strong { background: var(--green); }
.meter-label { font-size: 12px; color: var(--muted); }

/* ---------- state screens ---------- */

.state { display: grid; gap: 14px; }
.state h1 { margin: 0; font-size: 22px; font-weight: 650; letter-spacing: -.018em; }
.state p { margin: 0; font-size: 14px; color: var(--ink-2); }

.spinner {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid var(--line);
  border-top-color: var(--brand);
  animation: portal-spin .7s linear infinite;
}
@keyframes portal-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .spinner { animation-duration: 2.4s; }
  .meter-fill { transition: none; }
}

/* ==========================================================================
   Signed in pages: home and patient chart.
   Taken from screens 02 and 03 of the approved mockup.
   ========================================================================== */

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- loading skeletons ----------

   A portal that has not finished loading must never draw something that reads
   as an answer. A tile showing 0 and a table with headers and no rows tells a
   referring office they have no patients, which is the worst thing this product
   can say incorrectly. These placeholders say "not yet" instead.
*/

/*
   A skeleton MUST contain no text. Ever.

   It sizes itself from width and height, not from characters inside it, so put
   nothing between the tags. An earlier version held "00" hidden with
   color: transparent, and .tile.hot b (0,2,1) out-specified .skeleton (0,1,0),
   so the placeholder rendered as a readable "00 signed notes" on the one tile
   an office actually came to read.

   The fix is not a more specific selector. Any future colour rule on a stat
   value would spring the same trap. An element with no characters in it cannot
   leak characters, whatever the cascade decides about its colour.
*/
.skeleton {
  display: inline-block;
  width: 2.6em;
  height: 1em;
  vertical-align: middle;
  border-radius: 6px;
  background: var(--line-soft);
  background-image: linear-gradient(90deg,
    var(--line-soft) 0%, var(--surface-2) 40%, var(--line-soft) 80%);
  background-size: 300% 100%;
  animation: portal-shimmer 1.4s ease-in-out infinite;
}
.skeleton.line { height: .8em; width: 12ch; }
.skeleton.wide { width: 60%; }

/*
   Note for anyone automating this page: a looping animation never settles, so
   Page.captureScreenshot waits for a stable frame that never comes and times
   out. The same applies to the note viewer on the chart. Neither is a defect.
   Screenshot after loading finishes, or disable animations in the driver.
*/
@keyframes portal-shimmer {
  0%   { background-position: 100% 0; }
  100% { background-position: -100% 0; }
}

.skeleton-rows { display: grid; gap: 1px; padding: 4px 0; }
.skeleton-rows > div {
  display: flex;
  gap: 12px;
  align-items: center;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line-soft);
}
.skeleton-rows > div:last-child { border-bottom: 0; }
.skeleton-rows .a { flex: 2; }
.skeleton-rows .b { flex: 1; }
.skeleton-rows .c { flex: 1.4; }

@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; }
}

/* ---------- app bar ---------- */

.appbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 20px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
.appbar .mark { text-decoration: none; color: var(--ink); }
.appbar .office {
  font-size: 12.5px;
  color: var(--muted);
  padding-left: 16px;
  border-left: 1px solid var(--line);
}
.appbar .office b { color: var(--ink); font-weight: 620; }
.appbar-spacer { flex: 1; }

.avatar { display: flex; align-items: center; gap: 9px; font-size: 13px; color: var(--ink-2); }
.avatar i {
  width: 28px; height: 28px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--surface-2); border: 1px solid var(--line);
  font-style: normal; font-size: 11.5px; font-weight: 650; color: var(--brand);
}

/* ---------- canvas ---------- */

.canvas {
  padding: 24px 20px 40px;
  background: var(--bg);
  display: grid;
  gap: 20px;
  align-content: start;
  min-height: calc(100vh - 53px);
}

.greet { display: grid; gap: 3px; }
.greet h3 { margin: 0; font-size: 20px; font-weight: 650; letter-spacing: -.016em; }
.greet p { margin: 0; font-size: 13.5px; color: var(--muted); min-height: 21px; }

/* ---------- tiles ---------- */

.tiles { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.tile {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 14px 16px; display: grid; gap: 3px;
}
.tile span {
  font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); font-weight: 620;
}
.tile b {
  font-size: 26px; font-weight: 660; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.tile.hot b { color: var(--brand); }
.tile small { font-size: 12px; color: var(--muted); }

/* ---------- cards and tables ---------- */

.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden;
}
.card-head {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 16px; border-bottom: 1px solid var(--line-soft);
}
.card-head h4 { margin: 0; font-size: 14.5px; font-weight: 630; }
.card-head .sp { flex: 1; }

.card-message { margin: 0; padding: 16px; font-size: 13.5px; }
.card-message.dim { color: var(--muted); }
.alert.card-message { border-radius: 0; border-width: 0 0 1px 0; }

.table-wrap { overflow-x: auto; }

table { width: 100%; border-collapse: collapse; }
th {
  text-align: left; font-size: 10.5px; letter-spacing: .085em; text-transform: uppercase;
  color: var(--muted); font-weight: 640; padding: 9px 16px;
  border-bottom: 1px solid var(--line-soft); background: var(--surface-2);
  white-space: nowrap;
}
td { padding: 11px 16px; border-bottom: 1px solid var(--line-soft); font-size: 13.5px; vertical-align: middle; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr { cursor: pointer; }
tbody tr:hover { background: var(--surface-2); }
tbody tr:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
td.name { font-weight: 600; color: var(--ink); }
td.num { font-family: var(--mono); font-size: 12.5px; color: var(--ink-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
td.dim, .dim { color: var(--muted); }
.stack { display: grid; gap: 1px; }
.stack small { font-size: 12px; color: var(--muted); }

/* ---------- pills ---------- */

.pill {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 600; padding: 2px 9px; border-radius: 99px;
  border: 1px solid; white-space: nowrap;
}
.pill.active { color: var(--green); border-color: color-mix(in srgb, var(--green) 40%, transparent); background: color-mix(in srgb, var(--green) 9%, transparent); }
.pill.disch  { color: var(--muted); border-color: var(--line); background: var(--surface-2); }
.pill.new    { color: var(--brand); border-color: color-mix(in srgb, var(--brand) 40%, transparent); background: color-mix(in srgb, var(--brand) 10%, transparent); }
.pill.eval   { color: var(--amber); border-color: color-mix(in srgb, var(--amber) 42%, transparent); background: color-mix(in srgb, var(--amber) 10%, transparent); }

/* ---------- ghost buttons ---------- */

.ghost {
  font: inherit; font-size: 12.5px; font-weight: 570; cursor: pointer;
  border: 1px solid var(--line); border-radius: 7px; padding: 5px 11px;
  background: var(--surface); color: var(--ink-2); white-space: nowrap;
}
.ghost:hover:not(:disabled) { border-color: var(--brand); color: var(--brand); }
.ghost:disabled { opacity: .5; cursor: default; }
.ghost.primary { border-color: color-mix(in srgb, var(--brand) 45%, transparent); color: var(--brand); }
.rowacts { display: flex; gap: 6px; justify-content: flex-end; }

/* ---------- filters ---------- */

.filters { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.inputish {
  font: inherit; font-size: 13px; color: var(--ink);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 8px; padding: 8px 12px;
}
.inputish.grow { flex: 1; min-width: 200px; }
select.inputish { cursor: pointer; }

/* ---------- patient chart ---------- */

.backlink { font-size: 13px; color: var(--brand); text-decoration: none; font-weight: 550; }
.backlink::before { content: "\2190"; margin-right: 6px; }

.chart-head {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
.chart-head h3 { margin: 0; font-size: 19px; font-weight: 660; letter-spacing: -.016em; }
.chart-head .meta { font-family: var(--mono); font-size: 12px; color: var(--muted); }
.chips { display: flex; gap: 6px; flex-wrap: wrap; }
.chart-cols { display: grid; grid-template-columns: 320px 1fr; gap: 14px; align-items: start; }

.plan { display: grid; gap: 14px; padding: 16px; }
.plan section { display: grid; gap: 5px; }
.plan h5 {
  margin: 0; font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); font-weight: 640;
}
.plan p { margin: 0; font-size: 13.5px; color: var(--ink-2); }
.plan ul { margin: 0; padding-left: 17px; font-size: 13.5px; color: var(--ink-2); display: grid; gap: 3px; }
.plan .kv { display: flex; gap: 8px; font-size: 13.5px; }
.plan .kv b { font-variant-numeric: tabular-nums; font-weight: 620; }

.notelist { display: grid; }
.noterow {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 16px; border-bottom: 1px solid var(--line-soft);
}
.notelist .noterow:last-child { border-bottom: 0; }
.noterow .when { font-family: var(--mono); font-size: 12.5px; color: var(--muted); width: 74px; flex: none; }
.noterow .what { display: grid; gap: 2px; flex: 1; min-width: 180px; }
.noterow .what b { font-size: 13.5px; font-weight: 610; }
.noterow .what span { font-size: 12.5px; color: var(--muted); }

/* ---------- note viewer ---------- */

body.viewer-open { overflow: hidden; }

.viewer {
  position: fixed; inset: 0; z-index: 50;
  background: rgba(8, 16, 26, .55);
  display: grid; place-items: center;
  padding: 24px;
}
.viewer-panel {
  width: 100%; max-width: 880px; max-height: 88vh;
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; box-shadow: var(--shadow); overflow: hidden;
}
.viewer-head {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 16px; border-bottom: 1px solid var(--line-soft);
}
.viewer-head h4 { margin: 0; font-size: 15px; font-weight: 640; }
.viewer-head .meta { font-size: 12.5px; color: var(--muted); }
/* ── Clinical-note typography: the ONE home, portal copy ───────────────────
   Notes carry no inline font styling any more. The prompt no longer emits it,
   ClinicalHtmlSanitizer strips it on save, NotePasteCleaner strips it on paste,
   and LegacyNoteHtmlRepair strips it on read — including on the portal read
   path (PortalDataService.BuildNoteDtoAsync). So this rule is the only thing
   deciding the face and size of a note in this window.

   THREE COPIES OF THESE VALUES EXIST AND MUST STAY IN STEP. Changing one alone
   makes the same signed note look different depending on the window:
     1. styles.css                        .note-content / .note-content-view /
                                          .trumbowyg-editor  (staff app)
     2. this rule                         .viewer-body       (doctor office portal)
     3. ClinicalNoteRenderer.js           PRINT_TYPOGRAPHY_CSS (print window, a
        + GlobalBridge.js Word export     standalone document that loads no
                                          stylesheet of ours)

   No !important: nothing competes with it. If a note ever renders at the wrong
   size again, something upstream started emitting inline fonts and THAT is the
   bug, not this rule. */
.viewer-body {
  padding: 20px; overflow: auto; background: #fff; color: #111;
  font-family: Calibri, Carlito, "Segoe UI", Arial, sans-serif;
  font-size: 14px; line-height: 1.5;
}
.viewer-body * { font-family: inherit; font-size: inherit; }
.viewer-body p, .viewer-body ul, .viewer-body ol { margin: 0 0 2px 0; }
.viewer-body img { max-width: 100%; }
.viewer-body table { width: auto; }

/* ---------- responsive ---------- */

@media (max-width: 1000px) {
  .chart-cols { grid-template-columns: 1fr; }
}

@media (max-width: 760px) {
  .tiles { grid-template-columns: repeat(2, 1fr); }
  .appbar { gap: 10px; padding: 10px 14px; flex-wrap: wrap; }
  .appbar .office { padding-left: 0; border-left: 0; flex-basis: 100%; order: 3; }
  .avatar span { display: none; }
  .canvas { padding: 18px 14px 32px; }
}

@media (max-width: 480px) {
  .tiles { grid-template-columns: 1fr; }
  .viewer { padding: 0; }
  .viewer-panel { max-height: 100vh; height: 100vh; border-radius: 0; border: 0; }
}

@media (max-width: 860px) {
  .portal-auth { padding: 0; place-items: stretch; }
  .auth-card {
    grid-template-columns: 1fr;
    max-width: none;
    min-height: 100vh;
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }
  .auth-pitch { padding: 28px 24px; gap: 14px; }
  .auth-pitch h2 { font-size: 23px; }
  .auth-panel { padding: 28px 24px 40px; justify-content: flex-start; }
}

@media (max-width: 420px) {
  .otp-inputs { gap: 6px; }
  .otp-digit { width: 100%; font-size: 18px; }
}
