﻿/* ═══════════════════════════════════════════════════════════════
   app.css — signed-in app shell + polish layer.
   Loads AFTER site.css/auth.css and only overrides inside .app-shell,
   so the marketing pages keep their own chrome untouched.
   ═══════════════════════════════════════════════════════════════ */

:root {
  --app-sidebar-w: 248px;
  --app-content-max: 1080px;
  /* Narrower rail for single-column pages — a list of label→amount rows
     stops being readable long before 1080px. */
  --app-content-narrow: 820px;
  --app-gutter: clamp(1rem, 3vw, 2rem);
}

/* ── shell frame ──────────────────────────────────────────────── */
.app-shell {
  display: flex;
  min-height: 100dvh;
  background: var(--color-surface);
}
.app-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.app-main main { flex: 1; }

/* ── sidebar ──────────────────────────────────────────────────── */
.app-sidebar {
  flex: none;
  width: var(--app-sidebar-w);
  position: sticky;
  top: 0;
  height: 100dvh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 1.1rem 0.85rem 0.85rem;
  background: var(--color-surface-container-lowest);
  border-right: 1px solid color-mix(in srgb, var(--color-outline-variant) 55%, transparent);
}
/* brand — now a compact, muted signature pinned to the sidebar bottom */
.side-brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.5rem;
  padding: 0.7rem 0.6rem 0.15rem;
  border-top: 1px solid color-mix(in srgb, var(--color-outline-variant) 55%, transparent);
  text-decoration: none;
  color: var(--color-on-surface-variant);
}
.side-brand-logo { display: block; flex: none; }

/* profile block — big centered avatar + name, links to /Account */
.side-profile {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.45rem;
  padding: 1rem 0.6rem 0.7rem;
  margin-bottom: 0.5rem;
  border-radius: 0.9rem;
  text-decoration: none;
  color: var(--color-on-surface);
  transition: background 120ms ease;
}
.side-profile:hover { background: var(--color-surface-container); }
.side-avatar {
  flex: none;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dim));
  color: var(--color-on-primary);
  font-family: "Manrope", sans-serif;
  font-weight: 800;
  font-size: 1.4rem;
  letter-spacing: 0.02em;
  box-shadow: 0 10px 22px color-mix(in srgb, var(--color-primary) 32%, transparent);
}
.side-profile-name {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 700;
  font-size: 0.95rem;
  line-height: 1.25;
  text-transform: capitalize;
}
.side-profile-sub { font-size: 0.72rem; font-weight: 600; color: var(--color-on-surface-variant); }
.side-badge {
  margin-top: 0.1rem;
  padding: 0.12rem 0.5rem;
  border-radius: 9999px;
  background: var(--color-secondary-container);
  color: var(--color-on-secondary-container);
  font-size: 0.6rem;
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

/* clinic selector — custom dropdown (native <select> can't style its open
   list). Lives in the footer; the menu opens upward. */
.side-clinic { position: relative; margin-bottom: 0.4rem; }
.side-clinic-trigger {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.55rem 0.6rem 0.55rem 0.7rem;
  border: 1px solid color-mix(in srgb, var(--color-outline-variant) 60%, transparent);
  border-radius: 0.7rem;
  background: var(--color-surface-container);
  font-family: "Plus Jakarta Sans", sans-serif;
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--color-on-surface);
  cursor: pointer;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}
.side-clinic-trigger:hover { border-color: var(--color-outline); }
.side-clinic-trigger > .material-symbols-outlined:first-child {
  font-size: 18px;
  color: var(--color-primary);
  flex: none;
}
.side-clinic-current {
  flex: 1;
  min-width: 0;
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.side-clinic-caret {
  font-size: 20px;
  color: var(--color-on-surface-variant);
  flex: none;
  transition: transform 150ms ease;
}
.side-clinic.open .side-clinic-caret { transform: rotate(180deg); }
.side-clinic.open .side-clinic-trigger {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-primary) 22%, transparent);
}

.side-clinic-menu {
  display: none;
  position: absolute;
  bottom: calc(100% + 0.4rem);
  left: 0;
  right: 0;
  z-index: 50;
  padding: 0.3rem;
  background: var(--color-surface-container-lowest);
  border: 1px solid var(--color-outline-variant);
  border-radius: 0.85rem;
  box-shadow: 0 18px 44px color-mix(in srgb, var(--color-on-surface) 22%, transparent);
  max-height: 44vh;
  overflow-y: auto;
}
.side-clinic.open .side-clinic-menu { display: block; }
.side-clinic-option {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.5rem 0.6rem;
  border: none;
  border-radius: 0.55rem;
  background: transparent;
  font-family: "Plus Jakarta Sans", sans-serif;
  font-size: 0.86rem;
  font-weight: 600;
  text-align: left;
  color: var(--color-on-surface);
  cursor: pointer;
}
.side-clinic-option > .material-symbols-outlined:first-child {
  font-size: 18px;
  color: var(--color-on-surface-variant);
  flex: none;
}
.side-clinic-option:hover { background: var(--color-surface-container); }
.side-clinic-option.active {
  background: var(--color-primary-container);
  color: var(--color-on-primary-container);
  font-weight: 700;
}
.side-clinic-option.active > .material-symbols-outlined { color: var(--color-on-primary-container); }
.side-clinic-option-name {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.side-clinic-check { margin-left: auto; font-size: 18px; flex: none; }

.side-nav {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  flex: 1;
}
.side-eyebrow {
  margin: 0.9rem 0.6rem 0.25rem;
  font-size: 0.64rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-outline);
}
.side-link {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  width: 100%;
  padding: 0.58rem 0.7rem;
  border: none;
  border-radius: 0.7rem;
  background: transparent;
  font-family: "Plus Jakarta Sans", sans-serif;
  font-size: 0.9rem;
  font-weight: 600;
  text-align: left;
  text-decoration: none;
  color: var(--color-on-surface-variant);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.side-link .material-symbols-outlined {
  font-size: 20px;
  line-height: 1;
  flex: none;
}
.side-link:hover {
  background: var(--color-surface-container);
  color: var(--color-on-surface);
}
.side-link.active {
  background: var(--color-primary-container);
  color: var(--color-on-primary-container);
  font-weight: 700;
}
.side-link.active .material-symbols-outlined {
  font-variation-settings: 'FILL' 1;
}

/* plan chip — current plan + upgrade CTA, links to /Account/Plan */
.side-plan {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
  padding: 0.6rem 0.7rem;
  border-radius: 0.8rem;
  text-decoration: none;
  background: var(--color-primary-container);
  color: var(--color-on-primary-container);
  transition: filter 120ms ease;
}
.side-plan:hover { filter: brightness(0.97); }
/* Top plan: the chip is now a label, not an offer, so it gives up the
   accent fill that made it read as the one thing to click down here. */
.side-plan-max {
  background: var(--color-surface-container-low);
  color: var(--color-on-surface-variant);
}
.side-plan-max .side-plan-name { color: var(--color-on-surface); }
.side-plan-info { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
.side-plan-label {
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.75;
}
.side-plan-name {
  font-family: "Manrope", sans-serif;
  font-weight: 800;
  font-size: 0.95rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.side-plan-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  flex: none;
  font-size: 0.75rem;
  font-weight: 800;
}
.side-plan-cta .material-symbols-outlined { font-size: 15px; }

.side-foot {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding-top: 0.6rem;
  border-top: 1px solid color-mix(in srgb, var(--color-outline-variant) 55%, transparent);
}
.side-foot form { margin: 0; }
.side-signout:hover { color: var(--color-error); background: color-mix(in srgb, var(--color-error) 8%, transparent); }

/* Theme picker — lives on the Account page (see theme-switcher.js). Each
   swatch previews a theme's primary color; the active one is highlighted. */
.theme-picker {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.6rem;
}
.theme-swatch {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.7rem 0.85rem;
  border: 1.5px solid var(--color-outline-variant);
  border-radius: 0.8rem;
  background: var(--color-surface-container-lowest);
  font-family: "Plus Jakarta Sans", sans-serif;
  font-size: 0.9rem;
  font-weight: 700;
  text-align: left;
  color: var(--color-on-surface);
  cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease, transform 120ms ease;
}
.theme-swatch:hover { border-color: var(--color-outline); transform: translateY(-1px); }
.theme-swatch.active {
  border-color: var(--color-primary);
  background: var(--color-primary-container);
  color: var(--color-on-primary-container);
}
.theme-swatch-dot {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  flex: none;
  box-shadow: inset 0 0 0 2px color-mix(in srgb, white 55%, transparent),
              0 2px 6px color-mix(in srgb, black 22%, transparent);
}

/* ── mobile chrome ────────────────────────────────────────────── */
.app-mobilebar {
  display: none;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1rem 0.25rem;
}
.mobile-signout {
  border: none;
  background: transparent;
  cursor: pointer;
  font-family: inherit;
}
@media (max-width: 979px) {
  .app-sidebar { display: none; }
  .app-mobilebar { display: flex; }
}
@media (min-width: 980px) {
  .app-shell .app-nav { display: none; }   /* pill bar is mobile-only */
}

/* ── app footer ───────────────────────────────────────────────── */
/* Full-width band (background comes from the base footer{} rule); the
   inner rail keeps the text aligned with the page content on the left. */
.app-footer {
  width: 100%;
  margin-top: 2rem;
  padding: 0;                 /* override base footer{} padding; inner owns height */
  font-size: 0.78rem;
  color: var(--color-on-surface-variant);
}
.app-footer-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  max-width: var(--app-content-max);
  margin: 0;
  padding: 1rem var(--app-gutter) 1.5rem;
}
.app-footer nav { display: flex; gap: 1rem; }
.app-footer a { color: inherit; }

/* ═══ polish layer — alignment + consistency inside the shell ═══ */

/* site.css styles the marketing page footer with a BARE `footer {}` —
   background, 2.5rem padding, 5rem top margin. That selector matches any
   <footer> element, including one used semantically inside a card or a
   tile, where it renders as a pale slab of dead space rather than a
   footer rail. The app shell's own footer is `.app-footer`, a sibling of
   <main> rather than a descendant, so it keeps the base rule and only
   in-content footers are reset here.

   :where() so the selector weighs exactly (0,0,1) — the same as the bare
   `footer {}` it is overriding, which this sheet outranks by load order,
   and less than any class rule a component writes for its own footer. A
   plain `.app-shell main footer` would win against `.check-foot` and
   flatten its padding right back to zero. */
:where(.app-shell main) footer {
  margin-top: 0;
  padding: 0;
  background: none;
}

/* One content width for every section (was 880/1000 mixed), left-aligned
   to the sidebar edge instead of floating centered in the viewport. */
.app-shell .app-header-inner,
.app-shell .pay-head,
.app-shell .pay-wrap,
.app-shell .pay-sim-bar,
.app-shell .cal-wrap,
.app-shell .settings-wrap,
.app-shell main > .account-grid {
  max-width: var(--app-content-max);
  margin-left: 0;
  margin-right: auto;
  padding-left: var(--app-gutter);
  padding-right: var(--app-gutter);
}
.app-shell .pay-head { margin-top: 1.4rem; align-items: center; flex-wrap: wrap; row-gap: 0.6rem; }
.app-shell .pay-wrap { margin-top: 1.1rem; }
/*  /Pay and /Pay/Reports open on the mode picker now that the Overview /
    Reports pills are gone, and .pay-sim-bar's own 0.9rem was measured to
    sit UNDER a control, not against the page header. :first-child rather
    than a blanket rule so /Calendar/Day — which still has a .pay-head
    above its picker — keeps its spacing. */
.app-shell main > .pay-sim-bar:first-child { margin-top: 1.4rem; }

/* Grids nested inside a wrapper fill it (the wrapper owns the width/gutter)
   and stay left-aligned rather than re-centering at their own max-width. */
.app-shell .pay-wrap > .account-grid {
  max-width: none;
  margin-left: 0;
  margin-right: 0;
  padding-left: 0;
  padding-right: 0;
}

/* /Calendar/Day is one clinic on one day: a hero tile and a single card,
   never two columns. On the shared rail its rows ran a label and an amount
   to opposite ends of a 1015px line with nothing between them. Narrower
   rail, same left edge — so it still lines up with the header above it. */
.app-shell .day-page .pay-head,
.app-shell .day-page .pay-wrap,
.app-shell .day-page .pay-sim-bar {
  max-width: var(--app-content-narrow);
}

/* Page titles: identical scale everywhere + room for a subtitle. */
.app-shell .pay-head h1 { font-size: 1.45rem; line-height: 1.2; }
.app-shell .page-sub {
  margin: 0.15rem 0 0;
  font-size: 0.85rem;
  color: var(--color-on-surface-variant);
}

/* Dashed rows: center-align both sides, keep amounts on one line. */
.app-shell .account-card .row { align-items: center; }
.app-shell .account-card .row > span:last-child:not(.label) { flex: none; white-space: nowrap; }
/* …except a cluster of controls. The rule above exists to keep a money
   amount on one line, which is right for a figure and wrong for buttons:
   it pinned the armed delete row at 489px tall and overflowing the card.
   Needs to live here, at this specificity, because app.css loads after
   auth.css and would otherwise win. */
.app-shell .account-card .row > span.report-actions:last-child:not(.label) {
  flex: 0 1 auto;
  white-space: normal;
}
.app-shell .account-card .row .label { min-width: 0; }
.app-shell .account-card .row .label a { color: var(--color-primary); font-weight: 600; text-decoration: none; }
.app-shell .account-card .row .label a:hover { text-decoration: underline; }

/* Buttons: consistent icon sizing/alignment at every size. */
.app-shell .btn { line-height: 1.2; }
.app-shell .btn .material-symbols-outlined { font-size: 18px; line-height: 1; }
.app-shell .btn-secondary { padding: 0.6rem 1.1rem; font-size: 0.88rem; }

/* Icon glyphs never wobble the baseline inside text lines. */
.app-shell .payday-pill .material-symbols-outlined,
.app-shell .cal-footnote .material-symbols-outlined { line-height: 1; }

/* Cards: uniform corner + padding rhythm. */
.app-shell .account-card { padding: 1.35rem 1.35rem 1.5rem; }
.app-shell .account-card h2 { font-size: 1.05rem; margin-bottom: 0.65rem; }

/* Alerts sit flush with the grid, same width as cards. */
.app-shell .alert-info,
.app-shell .alert-error { margin: 0 0 1rem; }

/* Keyboard focus is always visible (theme-aware). */
.app-shell a:focus-visible,
.app-shell button:focus-visible,
.app-shell input:focus-visible,
.app-shell select:focus-visible,
.app-shell summary:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: 0.4rem;
}

/* ── app header band ──────────────────────────────────────────────
   Sticky title + breadcrumb strip that frames every signed-in page.
   Sits flush-left on the same content rail as the body below it. */
.app-header {
  position: sticky;
  top: 0;
  z-index: 30;
  background: color-mix(in srgb, var(--color-surface) 86%, transparent);
  -webkit-backdrop-filter: saturate(1.6) blur(12px);
  backdrop-filter: saturate(1.6) blur(12px);
  border-bottom: 1px solid color-mix(in srgb, var(--color-outline-variant) 55%, transparent);
}
.app-header-inner {
  padding-top: 1rem;
  padding-bottom: 0.85rem;
}
.app-crumbs {
  display: flex;
  align-items: center;
  gap: 0.28rem;
  flex-wrap: wrap;
  margin-bottom: 0.3rem;
  font-family: "Plus Jakarta Sans", sans-serif;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--color-on-surface-variant);
}
.app-crumbs a { color: var(--color-on-surface-variant); text-decoration: none; transition: color 120ms ease; }
.app-crumbs a:hover { color: var(--color-primary); }
.app-crumb-sep {
  font-size: 15px;
  line-height: 1;
  color: var(--color-outline);
}
.app-crumb-current { color: var(--color-on-surface); }

/* clinic switcher living inside the breadcrumb (opens downward) */
.crumb-clinic { position: relative; display: inline-flex; }
.crumb-clinic-trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.1rem 0.35rem;
  border: none;
  border-radius: 0.45rem;
  background: transparent;
  font-family: inherit;
  font-size: inherit;
  font-weight: 700;
  color: var(--color-on-surface);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.crumb-clinic-trigger:hover { background: var(--color-surface-container); color: var(--color-primary); }
.crumb-clinic-trigger > .material-symbols-outlined:first-child { font-size: 15px; color: var(--color-primary); }
.crumb-clinic-caret { font-size: 16px; color: var(--color-on-surface-variant); transition: transform 150ms ease; }
.crumb-clinic.open .crumb-clinic-caret { transform: rotate(180deg); }
.crumb-clinic.open .crumb-clinic-trigger { background: var(--color-surface-container); }

.crumb-clinic-menu {
  display: none;
  position: absolute;
  top: calc(100% + 0.35rem);
  left: 0;
  z-index: 60;
  min-width: 190px;
  margin: 0;
  padding: 0.3rem;
  background: var(--color-surface-container-lowest);
  border: 1px solid var(--color-outline-variant);
  border-radius: 0.75rem;
  box-shadow: 0 16px 40px color-mix(in srgb, var(--color-on-surface) 20%, transparent);
  max-height: 50vh;
  overflow-y: auto;
}
.crumb-clinic.open .crumb-clinic-menu { display: block; }
.crumb-clinic-option {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.45rem 0.6rem;
  border: none;
  border-radius: 0.5rem;
  background: transparent;
  font-family: "Plus Jakarta Sans", sans-serif;
  font-size: 0.85rem;
  font-weight: 600;
  text-align: left;
  color: var(--color-on-surface);
  cursor: pointer;
}
.crumb-clinic-option > .material-symbols-outlined:first-child { font-size: 17px; color: var(--color-on-surface-variant); flex: none; }
.crumb-clinic-option:hover { background: var(--color-surface-container); }
.crumb-clinic-option.active {
  background: var(--color-primary-container);
  color: var(--color-on-primary-container);
  font-weight: 700;
}
.crumb-clinic-option.active > .material-symbols-outlined { color: var(--color-on-primary-container); }
.crumb-clinic-option-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.crumb-clinic-check { margin-left: auto; font-size: 17px; flex: none; }
.app-title {
  margin: 0;
  font-family: "Manrope", sans-serif;
  font-weight: 800;
  font-size: clamp(1.45rem, 2.4vw, 1.9rem);
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--color-on-surface);
}
.app-subtitle {
  margin: 0.28rem 0 0;
  font-size: 0.9rem;
  color: var(--color-on-surface-variant);
}

/* Clinic (and similar) summary values wrap instead of running off the
   card — overrides the nowrap money-amount rule above for text values. */
.app-shell .account-card .row > span.clinic-summary,
.app-shell .account-card .row > span.clinic-summary:last-child {
  flex: 0 1 auto;
  min-width: 0;
  white-space: normal;
  overflow-wrap: anywhere;
  text-align: right;
}

/* ── signed-in devices (Account) ──────────────────────────────── */
.app-shell .account-card .row.device-row { align-items: center; }
.device-name {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-weight: 600;
  color: var(--color-on-surface);
}
.device-name .material-symbols-outlined { font-size: 18px; color: var(--color-primary); flex: none; }
.device-actions { display: inline-flex; align-items: center; gap: 0.6rem; }
.device-actions form { margin: 0; }
.device-actions .btn-secondary { padding: 0.38rem 0.75rem; font-size: 0.78rem; }
.device-status {
  padding: 0.18rem 0.55rem;
  border-radius: 9999px;
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
}
.device-status.active { background: var(--color-primary-container); color: var(--color-on-primary-container); }
.device-status.expired { background: var(--color-secondary-container); color: var(--color-on-secondary-container); }
.device-status.revoked { background: var(--color-surface-container-high); color: var(--color-on-surface-variant); }

/* ── pay: per-day breakdown of the accruing period ────────────── */
.pay-days { display: flex; flex-direction: column; gap: 0.35rem; margin-top: 0.5rem; }
/* The list used to be a narrow right-hand column; it now sits under the
   full-width period tiles, where a single stack would run a date and an
   amount to opposite ends of a 1000px line. Two columns instead — and
   the fortnight it holds fits on one screen. */
@media (min-width: 900px) {
  .pay-days {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 1.5rem;
  }
}
.pay-day {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem 0.6rem;
  border-radius: 0.75rem;
  text-decoration: none;
  color: var(--color-on-surface);
  transition: background 120ms ease;
}
.pay-day:hover { background: var(--color-surface-container); }
.pay-day-cal {
  flex: none;
  width: 44px;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0.28rem 0;
  border-radius: 0.6rem;
  background: var(--color-primary-container);
  color: var(--color-on-primary-container);
  line-height: 1.05;
}
.pay-day-dow { font-size: 0.58rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; opacity: 0.85; }
.pay-day-num { font-family: "Manrope", sans-serif; font-weight: 800; font-size: 1.05rem; }
.pay-day-info { display: flex; flex-direction: column; min-width: 0; flex: 1; line-height: 1.25; }
.pay-day-date { font-weight: 700; font-size: 0.9rem; }
.pay-day-meta { font-size: 0.74rem; color: var(--color-on-surface-variant); }
.pay-day .money { flex: none; font-weight: 700; font-variant-numeric: tabular-nums; }
.pay-day-go { flex: none; font-size: 18px; color: var(--color-outline); }

/* ── cancel / retention page ──────────────────────────────────── */
.app-shell .cancel-wrap { max-width: 680px; }
.cancel-card { padding: 1.75rem 1.6rem 1.5rem; }
.cancel-eyebrow {
  display: block;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-primary);
}
.cancel-title {
  margin: 0.4rem 0 0.6rem;
  font-family: "Manrope", sans-serif;
  font-weight: 800;
  font-size: clamp(1.4rem, 3vw, 1.8rem);
  letter-spacing: -0.02em;
}
.cancel-lead { margin: 0 0 1.4rem; color: var(--color-on-surface-variant); line-height: 1.55; }
.cancel-lose h3,
.cancel-alts h3 {
  margin: 0 0 0.7rem;
  font-family: "Manrope", sans-serif;
  font-weight: 800;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-on-surface-variant);
}
.cancel-lose { padding: 1.1rem 1.15rem; border-radius: 1rem; background: var(--color-surface-container-low); margin-bottom: 1.4rem; }
.cancel-lose ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.55rem; }
.cancel-lose li { display: flex; align-items: center; gap: 0.6rem; font-size: 0.92rem; }
.cancel-lose li .material-symbols-outlined { font-size: 19px; color: var(--color-primary); flex: none; }
.cancel-lose .muted-note { margin-top: 0.9rem; }

.cancel-alts { margin-bottom: 1.5rem; }
.cancel-alt {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.85rem 0.95rem;
  border: 1px solid var(--color-outline-variant);
  border-radius: 0.9rem;
  text-decoration: none;
  color: var(--color-on-surface);
  transition: border-color 130ms ease, transform 130ms ease, box-shadow 130ms ease;
}
.cancel-alt + .cancel-alt { margin-top: 0.6rem; }
.cancel-alt:hover {
  border-color: var(--color-primary);
  transform: translateY(-1px);
  box-shadow: 0 10px 24px color-mix(in srgb, var(--color-on-surface) 8%, transparent);
}
.cancel-alt > .material-symbols-outlined:first-child { font-size: 24px; color: var(--color-primary); flex: none; }
.cancel-alt-text { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.cancel-alt-text strong { font-weight: 700; font-size: 0.95rem; }
.cancel-alt-text .muted-note { font-size: 0.82rem; }
.cancel-alt-go { margin-left: auto; color: var(--color-outline); flex: none; }

.cancel-actions { display: flex; flex-direction: column; align-items: center; gap: 0.35rem; }
.cancel-confirm-form { margin: 0; }
.cancel-confirm {
  border: none;
  background: transparent;
  padding: 0.5rem 0.75rem;
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--color-on-surface-variant);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.cancel-confirm:hover { color: var(--color-error); }

/* ── gradient money tile ──────────────────────────────────────────
   Was the dashboard hero; the dashboard now uses the money route below
   and /Calendar/Day is the only caller left (see .day-hero in
   auth.css, which extends these). Kept here rather than moved so the
   day tile and the route's final card stay visually identical. */
.dash-primary {
  position: relative;
  overflow: hidden;
  border-radius: 1.25rem;
  padding: 1.5rem 1.6rem;
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dim));
  color: var(--color-on-primary);
  box-shadow: 0 18px 44px color-mix(in srgb, var(--color-primary) 30%, transparent);
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.dash-primary::after {
  /* soft radial sheen — texture without another color */
  content: "";
  position: absolute;
  top: -60%;
  right: -20%;
  width: 70%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--color-on-primary) 18%, transparent), transparent 70%);
  pointer-events: none;
}
.dash-primary-label {
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.85;
}
.dash-primary-value {
  font-family: "Manrope", sans-serif;
  font-weight: 800;
  font-size: clamp(2rem, 4.5vw, 2.6rem);
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
}
.dash-primary-hint { font-size: 0.85rem; opacity: 0.9; }

/* ── the money route ──────────────────────────────────────────────
   Three stages, ordered by how far each dollar still has to travel:
   today → the open period → the closed period with a payday. The cards
   gain weight left to right (outline → tinted → full gradient) so the
   crescendo reads as "closer to the bank", and the connectors between
   them carry the hand-off in words. That pairing is what replaced the
   old "Accruing now" label, which named a mechanism and explained
   nothing. */
.flow {
  display: grid;
  grid-template-columns: 1fr auto 1fr auto 1fr;
  align-items: stretch;
  gap: 0.5rem;
  /* Was 0.85rem when a legend line sat underneath and carried the rest of
     the gap. The route now runs straight into the cards below it, so the
     air it needs lives here. */
  margin-bottom: 1.25rem;
}
.flow-card {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 1.15rem 1.2rem 1.1rem;
  border-radius: 1.15rem;
  text-decoration: none;
  color: var(--color-on-surface);
  background: var(--color-surface-container-lowest);
  border: 1px solid color-mix(in srgb, var(--color-outline-variant) 70%, transparent);
  transition: transform 150ms ease, box-shadow 150ms ease, border-color 150ms ease;
  /* Staggered reveal, left to right — the route draws itself once.
     TRANSFORM ONLY, never opacity: a paused or never-started animation
     must not be able to hide a money figure. Worst case the card is
     10px low for a moment; it is never blank. */
  animation: flow-in 420ms cubic-bezier(0.22, 1, 0.36, 1) backwards;
}
/* nth-CHILD, not nth-of-type — the connectors are siblings, and counting
   by element type would hand the same delay to two cards. */
.flow > :nth-child(1) { animation-delay: 0ms; }
.flow > :nth-child(3) { animation-delay: 70ms; }
.flow > :nth-child(5) { animation-delay: 140ms; }
@keyframes flow-in {
  from { transform: translateY(10px); }
  to   { transform: none; }
}
.flow-card:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--color-primary) 45%, transparent);
  box-shadow: 0 14px 32px color-mix(in srgb, var(--color-on-surface) 10%, transparent);
  /* The card is an <a>, so site.css's a:hover recolours it — and out-
     specifies the class that set the colour, so the money figure (which
     has no colour of its own and simply inherits) changed on hover. The
     lift and the shadow are the affordance; the amount holds still. */
  color: var(--color-on-surface);
}

.flow-stage {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--color-on-surface-variant);
}
.flow-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--color-primary);
  flex: none;
}
.flow-value {
  margin-top: 0.35rem;
  font-family: "Manrope", sans-serif;
  font-weight: 800;
  font-size: clamp(1.6rem, 3.1vw, 2.15rem);
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
}
.flow-value-none { color: var(--color-on-surface-variant); }
.flow-cap {
  margin-top: 0.15rem;
  font-size: 0.8rem;
  color: var(--color-on-surface-variant);
}
/* The day's shape, directly under the caption — it describes the figure
   above it, so it belongs to the figure, not to the footer. */
.flow-facts {
  margin-top: 0.35rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.55rem;
  font-size: 0.78rem;
  color: var(--color-on-surface-variant);
}
/* A footer rail, pinned to the bottom of every card and separated by a
   hairline. The cards stretch to the tallest of the three, so without a
   rule the shortest one just showed a hole; with one, the same air reads
   as a footer and all three bottom lines sit on the same baseline. It
   carries ONE line — what happens next, or where this card goes. */
.flow-meta {
  margin-top: auto;
  padding-top: 0.7rem;
  border-top: 1px solid color-mix(in srgb, var(--color-outline-variant) 60%, transparent);
  /* A rail holding a pill is ~4px taller than one holding plain text, which
     is enough to knock the three hairlines out of line with each other.
     Floor them all at the pill's height so the rules read as one. */
  min-height: 2.25rem;
  box-sizing: border-box;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.55rem;
  font-size: 0.78rem;
  color: var(--color-on-surface-variant);
}
/* Hairline separators between meta facts — cheaper than bullets and they
   disappear cleanly when the row wraps. */
.flow-facts > span + span:not(.flow-chip)::before,
.flow-meta > span + span:not(.flow-chip)::before {
  content: "";
  display: inline-block;
  width: 1px;
  height: 0.7em;
  margin-right: 0.55rem;
  vertical-align: -0.05em;
  background: currentColor;
  opacity: 0.35;
}
/* A pill already separates itself — a rule right after one reads as debris. */
.flow-facts > .flow-chip + span::before,
.flow-meta > .flow-chip + span::before { content: none; }
.flow-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.16rem 0.5rem;
  border-radius: 999px;
  background: var(--color-surface-container);
  font-weight: 700;
  font-size: 0.74rem;
  color: var(--color-on-surface-variant);
}
.flow-chip .material-symbols-outlined { font-size: 14px; line-height: 1; }
/* The one date on this screen that is a commitment rather than an
   estimate — it gets full ink where the facts around it stay muted. */
.flow-chip-strong { color: var(--color-on-surface); font-weight: 800; }
/* A recorded outcome outranks a scheduled date: once the cheque has
   landed (or hasn't), that is the fact, and the payday it was due on is
   history. Takes full ink for the same reason .flow-chip-strong does.
   On .flow-mail's gradient the chip's own inversion rule already
   applies — no colour is doing the work here, the icon and the word are. */
.flow-chip-settled { color: var(--color-on-surface); font-weight: 800; }

/* The settlement recorder sits directly under the flow strip, between it
   and the day-bars card, so it needs the gap both of those own. */
.dash-settle { margin-bottom: 1.25rem; }
.dash-settle > h2 { margin-bottom: 0.15rem; }
.dash-settle .settle { margin-top: 0.75rem; }
.flow-go {
  position: absolute;
  top: 1.05rem;
  right: 1.05rem;
  color: var(--color-outline);
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity 150ms ease, transform 150ms ease;
}
.flow-go .material-symbols-outlined { font-size: 18px; line-height: 1; display: block; }
.flow-card:hover .flow-go,
.flow-card:focus-visible .flow-go { opacity: 1; transform: none; }

/* Stage 1 — today. Lightest weight: this money hasn't gone anywhere yet. */
.flow-today.is-quiet .flow-value { color: var(--color-on-surface-variant); }
.flow-today.is-quiet .flow-dot { background: var(--color-outline); }

/* Stage 2 — the open period. Tinted: committed, not yet closed. */
.flow-period {
  background: var(--color-surface-container-low);
  border-color: color-mix(in srgb, var(--color-primary) 22%, transparent);
}
/* Elapsed time, not money — deliberately a different quantity from the
   figure above it, so it answers a question the total can't. */
.flow-track {
  margin-top: 0.7rem;
  height: 5px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--color-on-surface) 10%, transparent);
  overflow: hidden;
}
.flow-track-fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--color-primary);
}

/* Stage 3 — closed and waiting on a payday. Full weight: this is real. */
.flow-mail {
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dim));
  border-color: transparent;
  color: var(--color-on-primary);
  box-shadow: 0 16px 38px color-mix(in srgb, var(--color-primary) 28%, transparent);
}
.flow-mail::after {
  /* soft radial sheen — texture without another color */
  content: "";
  position: absolute;
  top: -70%;
  right: -25%;
  width: 80%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--color-on-primary) 18%, transparent), transparent 70%);
  pointer-events: none;
}
.flow-mail > * { position: relative; z-index: 1; }
/* Colour only — the arrow keeps the shared show-on-hover opacity, which a
   rule in here would out-specify and pin permanently visible. */
.flow-mail .flow-stage,
/* 0.94, not the 0.88 the old hero used: measured against every theme's
   primary, sage and terracotta drop small text under 4.5:1 by 0.88. */
.flow-mail .flow-cap,
.flow-mail .flow-facts,
.flow-mail .flow-meta { color: var(--color-on-primary); opacity: 0.94; }
/* The footer rule has to be drawn out of the card's own ink here — the
   outline token is a light-surface grey and vanishes on the gradient. */
.flow-mail .flow-meta { border-top-color: color-mix(in srgb, var(--color-on-primary) 28%, transparent); }
/* `.flow-mail > *` above ties with .flow-go on specificity and wins on
   order, which dropped the arrow out of the corner and into the bottom of
   the column. Restated here, at two classes, so it stays pinned top-right
   like every other card's. */
.flow-mail .flow-go {
  position: absolute;
  color: var(--color-on-primary);
}
.flow-mail .flow-dot { background: var(--color-on-primary); }
.flow-mail .flow-chip {
  background: color-mix(in srgb, var(--color-on-primary) 18%, transparent);
  color: var(--color-on-primary);
}
.flow-mail:hover {
  border-color: transparent;
  box-shadow: 0 20px 46px color-mix(in srgb, var(--color-primary) 36%, transparent);
  /* Same a:hover story as the light cards, in this card's own ink — and it
     has to be restated after .flow-card:hover, which ties on specificity. */
  color: var(--color-on-primary);
}

/* The hand-off between stages, in words. */
.flow-link {
  align-self: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1rem;
  padding: 0 0.1rem;
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-align: center;
  color: var(--color-outline);
  white-space: nowrap;
}
.flow-link .material-symbols-outlined { font-size: 20px; line-height: 1; }

/* Stacked: the route turns vertical and the connectors point down. */
@media (max-width: 900px) {
  .flow { grid-template-columns: 1fr; gap: 0.4rem; }
  .flow-link { flex-direction: row; gap: 0.4rem; padding: 0.1rem 0; }
  .flow-link .material-symbols-outlined { transform: rotate(90deg); }
  .flow-value { font-size: 1.8rem; }
}

/* ── period bar strip ─────────────────────────────────────────────
   One series, so no legend — the card heading names it. Every calendar
   day keeps its slot, so days off read as gaps instead of vanishing.
   Today is marked by an outline and a bolder tick as well as colour,
   never colour alone. */
.bars {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  min-height: 118px;
  padding-top: 0.35rem;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
}
.bar {
  flex: 1 1 0;
  min-width: 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  text-decoration: none;
  border-radius: 0.35rem;
  padding-bottom: 0.15rem;
}
.bar-col {
  width: 100%;
  height: 92px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  /* baseline the bars sit on — visible even where nothing was earned */
  box-shadow: inset 0 -1px 0 0 color-mix(in srgb, var(--color-on-surface) 16%, transparent);
}
/* Deliberately NOT animated. A grow-from-zero keyframe leaves every bar
   flat whenever the animation is paused or never starts, and a chart of
   money that renders empty is worse than one that simply appears. */
.bar-fill {
  width: 100%;
  min-height: 2px;
  border-radius: 4px 4px 0 0;
  background: var(--color-primary);
  transition: background-color 130ms ease;
}
.bar-tick {
  font-size: 0.66rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--color-on-surface-variant);
  opacity: 0.75;
}
/* Today's tick carries a dot. EVERY tick reserves the room for one, or
   that one bar is taller than its neighbours — and since .bars aligns to
   flex-end, a taller bar lifts its column and today's fill floats off the
   shared baseline. The dot is only painted on today. */
.bar-tick::after {
  content: "";
  display: block;
  width: 3px;
  height: 3px;
  margin: 2px auto 0;
  border-radius: 50%;
  background: transparent;
}
.bar:hover .bar-fill { background: var(--color-primary-dim); }
.bar:hover .bar-tick { opacity: 1; color: var(--color-on-surface); }

/* Days with nothing logged: baseline only, no mark to misread as small. */
.bar:not(.has-money) .bar-fill { background: transparent; }
/* Not yet arrived — dimmer tick, so the empty tail isn't read as days missed. */
.bar.is-future .bar-tick { opacity: 0.4; }

.bar.is-today .bar-col {
  border-radius: 0.4rem 0.4rem 0 0;
  background: color-mix(in srgb, var(--color-primary) 10%, transparent);
  box-shadow: inset 0 -2px 0 0 var(--color-primary);
}
.bar.is-today .bar-tick {
  opacity: 1;
  font-weight: 800;
  color: var(--color-primary);
}
.bar.is-today .bar-tick::after { background: var(--color-primary); }

/* ── the strip's hover card ───────────────────────────────────────
   Inverse ink, not another pale panel: it floats over a light card and
   has to read instantly as "on top of" rather than "part of". The
   on-surface / surface pair inverts with the theme, so this stays a
   legible overlay in every one of them.

   The wrapper exists purely to position it — .bars itself scrolls, and a
   scroll container clips both axes no matter what overflow-y says. */
.bars-wrap { position: relative; }

.bar-tip {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 20;
  /* Two panes wide rather than one pane tall: the plot band is ~118px,
     and a stacked card would have to leave the section to clear a bar. */
  display: flex;
  align-items: stretch;
  gap: 0.85rem;
  width: max-content;
  max-width: min(22rem, 100%);
  /* Kept trim on purpose: it floats over a ~118px plot, and every row of
     padding here is a row of the chart it hides. */
  padding: 0.6rem 0.8rem 0.65rem;
  border-radius: 0.9rem;
  background: var(--color-on-surface);
  color: var(--color-surface-container-lowest);
  box-shadow: 0 18px 40px color-mix(in srgb, var(--color-on-surface) 32%, transparent);
  /* Never intercepts the pointer: catching its own hover would flicker
     the card off and on as the box passes under the cursor. */
  pointer-events: none;
  opacity: 0;
  /* Rises INTO place from just under the ticks, matching the direction it
     now sits in relative to the chart. */
  transform: translateY(-4px);
  transition: opacity 130ms ease, transform 130ms ease;
}
.bar-tip.is-on { opacity: 1; transform: none; }
/* Points up at the day number it belongs to. Sits on --caret, which the
   script keeps aimed at that tick even after the box has been nudged in
   from an edge. */
.bar-tip::after {
  content: "";
  position: absolute;
  bottom: 100%;
  left: var(--caret, 50%);
  margin-left: -6px;
  border: 6px solid transparent;
  border-bottom-color: var(--color-on-surface);
}
/* The local `.bar-tip [hidden]` patch that used to live here is gone —
   site.css settles [hidden] globally now. */
.bar-tip-main {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.bar-tip-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
}
.bar-tip-day {
  font-size: 0.67rem;
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  opacity: 0.72;
}
.bar-tip-today {
  padding: 0.1rem 0.4rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--color-surface-container-lowest) 22%, transparent);
  font-size: 0.56rem;
  font-weight: 800;
  letter-spacing: 0.1em;
}
.bar-tip-earned {
  margin-top: 0.2rem;
  font-family: "Manrope", sans-serif;
  font-weight: 800;
  font-size: 1.25rem;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.bar-tip-note {
  font-size: 0.72rem;
  opacity: 0.7;
}
/* Right pane: the day's facts, past a hairline. Label left, figure right,
   the same shape as the dashed rows on every card in the app. */
.bar-tip-stats {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.28rem;
  padding-left: 0.85rem;
  border-left: 1px solid color-mix(in srgb, var(--color-surface-container-lowest) 20%, transparent);
}
.bar-tip-stat {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.1rem;
}
.bar-tip-stat-label {
  font-size: 0.58rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.62;
}
.bar-tip-stat-value {
  font-size: 0.82rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
/* The day's weight in the period, as a line rather than a fourth figure. */
.bar-tip-share {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: auto;
  padding-top: 0.4rem;
  font-size: 0.64rem;
  white-space: nowrap;
  opacity: 0.78;
}
.bar-tip-share-track {
  width: 2.6rem;
  flex: none;
  height: 3px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--color-surface-container-lowest) 22%, transparent);
  overflow: hidden;
}
.bar-tip-share-fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: currentColor;
}

/* Period totals — the two figures as label-over-value blocks and nothing
   else. The old single flex row also carried the pay-rule summary, which
   met the money coming the other way in the middle of the card. */
.bars-foot {
  margin-top: 0.9rem;
  padding-top: 0.85rem;
  border-top: 1px solid color-mix(in srgb, var(--color-outline-variant) 55%, transparent);
  color: var(--color-on-surface-variant);
}
.bars-figs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem 2.4rem;
}
.bars-fig {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  position: relative;
}
/* Hairline between the pair, same device as .flow-meta — it disappears on
   its own when the row wraps to two lines. */
.bars-fig + .bars-fig::before {
  content: "";
  position: absolute;
  left: -1.2rem;
  top: 0.15rem;
  bottom: 0.15rem;
  width: 1px;
  background: color-mix(in srgb, var(--color-outline-variant) 65%, transparent);
}
.bars-fig-label {
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--color-on-surface-variant);
}
.bars-fig-value {
  font-family: "Manrope", sans-serif;
  font-weight: 800;
  font-size: 1.4rem;
  letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
  color: var(--color-on-surface);
}
/* Take-home carries the bar colour, so the figure and the strip above it
   are visibly the same quantity. */
.bars-fig.is-earned .bars-fig-value { color: var(--color-primary); }
.bars-fig-note {
  margin-top: 0.1rem;
  font-size: 0.72rem;
  color: var(--color-on-surface-variant);
  font-variant-numeric: tabular-nums;
}

/* Card headings: title left, a quiet unit/count note right. */
.dash-card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
}
.dash-card-head h2 { margin-bottom: 0; }
.dash-card-title { display: flex; flex-direction: column; gap: 0.12rem; min-width: 0; }
/* The window the card is about, stated once under its title so the totals
   in the footer can stay bare. */
.dash-card-sub {
  margin: 0;
  font-size: 0.78rem;
  color: var(--color-on-surface-variant);
  font-variant-numeric: tabular-nums;
}
.dash-card-note {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--color-on-surface-variant);
  white-space: nowrap;
}
.app-shell .dash-grid .dash-card-head { margin-bottom: 0.65rem; }
/* The strip wants the full grid width; the tiles beside it don't. */
.dash-grid > .dash-span { grid-column: 1 / -1; }

@media (prefers-reduced-motion: reduce) {
  .app-shell *, .app-shell *::before, .app-shell *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}

/* ═══ the ask card — dashboard assistant ═══════════════════════════════
   Reads as a fourth stage of the money route rather than as a widget
   bolted below it: same radius, same border weight, same uppercase
   micro-label with a primary dot. What separates it is the ground — a
   faint primary wash instead of the flat surface the money cards use, so
   it is legible as "a different kind of thing" without a second accent
   colour entering the page. */
.ask {
  position: relative;
  /* Was hidden, to keep the corner gradient inside the radius. The clinic
     menu opens upward out of the card, and a clipped popup is worse than a
     gradient that needs its own containment — which the radial's own extent
     already gives it. */
  overflow: visible;
  margin-bottom: 1.25rem;
  padding: 1.25rem 1.3rem 1.3rem;
  border-radius: 1.15rem;
  border: 1px solid color-mix(in srgb, var(--color-primary) 22%, transparent);
  background:
    radial-gradient(120% 140% at 0% 0%,
      color-mix(in srgb, var(--color-primary) 8%, transparent) 0%,
      transparent 58%),
    var(--color-surface-container-lowest);
}
/* Same transform-only reveal as the route above, one beat later so the
   page resolves top to bottom. Never opacity — a card that animates its
   own visibility can be left invisible by a paused animation. */
.ask { animation: flow-in 420ms cubic-bezier(0.22, 1, 0.36, 1) 200ms backwards; }

.ask-head { margin-bottom: 0.9rem; }
.ask-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--color-on-surface-variant);
}
.ask-title {
  margin: 0.5rem 0 0;
  font-family: "Manrope", sans-serif;
  font-weight: 800;
  font-size: 1.28rem;
  letter-spacing: -0.02em;
  color: var(--color-on-surface);
}
.ask-sub {
  margin: 0.3rem 0 0;
  max-width: 60ch;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--color-on-surface-variant);
}

/* ── the field ──────────────────────────────────────────────────────── */
.ask-form { margin: 0; }
.ask-field {
  display: flex;
  /* Top-aligned, not centred: the field grows downward as the question gets
     longer, and a centred icon would drift down the box with it. */
  align-items: flex-start;
  gap: 0.55rem;
  padding: 0.7rem 0.7rem 0.7rem 0.9rem;
  /* A rounded rectangle, not a pill. A pill is right for one line; two lines
     of text inside one leaves crescents of dead space at both ends. */
  border-radius: 1.25rem;
  background: var(--color-surface-container);
  border: 1px solid color-mix(in srgb, var(--color-outline-variant) 70%, transparent);
  transition: border-color 150ms ease, box-shadow 150ms ease;
}
/* :focus-within, not :focus — the ring belongs to the whole pill, which is
   what reads as the control. Focusing the bare input would ring a
   borderless box inside a bordered one. */
.ask-field:focus-within {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-primary) 18%, transparent);
}
.ask-field-icon {
  font-size: 20px;
  color: var(--color-primary);
  flex: none;
  /* Optically on the first line of text rather than on the box's top edge. */
  margin-top: 0.15rem;
}
/*  The field is the pill, not the textarea inside it.

    site.css styles every input and textarea with its own border, radius and
    focus ring, which drew a second rounded box inside this one — a box within
    a box, both lit on focus. Everything visual is stripped here and the ring
    lives on .ask-field:focus-within instead, so the whole control reads as one
    control. !important because the base rules are element selectors carrying a
    .input class alongside them. */
.ask-input,
.ask-input:focus,
textarea.ask-input {
  flex: 1 1 auto;
  min-width: 0;
  border: 0 !important;
  outline: none !important;
  box-shadow: none !important;
  background: none !important;
  border-radius: 0;
  font: inherit;
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--color-on-surface);
  padding: 0.15rem 0;
  /* Two lines to start. The script grows it as the question does, up to a
     ceiling, then it scrolls — the same shape as every chat composer, and the
     reason it never pushes the send button off the card. */
  min-height: 3rem;
  max-height: 11rem;
  resize: none;
  overflow-y: auto;
}
.ask-input::placeholder { color: var(--color-on-surface-variant); opacity: 0.85; }
.ask-send {
  flex: none;
  /* Pinned to the bottom of a growing field, where a send button belongs —
     next to the end of what you just typed. */
  align-self: flex-end;
  width: 2.15rem;
  height: 2.15rem;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  background: var(--color-primary);
  color: var(--color-on-primary);
  transition: transform 130ms ease, filter 130ms ease;
}
.ask-send:hover { transform: scale(1.06); }
.ask-send:active { transform: scale(0.96); }
.ask-send .material-symbols-outlined { font-size: 20px; }
.ask.is-busy .ask-send { filter: grayscale(1); pointer-events: none; }
.ask.is-busy .ask-input { opacity: 0.6; }

/* ── starter questions ──────────────────────────────────────────────── */
/*  The daily allowance, under the composer where a character counter would
    sit. Quiet by default and coloured only as it runs out — a limit you are
    nowhere near is background information. */
/*  Under the field: which clinic on the left, the allowance on the right.
    Both are answers to "what will this question do", so they share a rail
    rather than stacking into two thin lines. */
.ask-underbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  margin-top: 0.45rem;
  min-height: 1.85rem;
  /* The picker's menu opens upward out of this rail. */
  position: relative;
}

/*  The composer's clinic picker.

    Styled to match the header crumb rather than left as a native <select>:
    the OS draws its own dropdown, complete with a system highlight that
    belongs to no theme, and the page ends up with two clinic pickers that
    look nothing alike. A little larger than the quota beside it, because it
    is a control and that is a readout. */
.ask-clinic {
  position: relative;
  /* Nudged in to line up with the field's text rather than the pill's outer
     edge — the icon inside the composer starts here too. */
  margin-left: 0.9rem;
}

/*  The value lives in a real form control the script reads; only its own
    dropdown is replaced. Not display:none — a hidden-but-present select keeps
    working if the menu script ever fails to bind. */
.ask-clinic-value {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.ask-clinic-menu { position: relative; }

.ask-clinic-trigger {
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.3rem 0.5rem;
  border-radius: 999px;
  cursor: pointer;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--color-on-surface-variant);
  transition: background 130ms ease, color 130ms ease;
}
.ask-clinic-trigger::-webkit-details-marker { display: none; }
.ask-clinic-trigger:hover,
.ask-clinic-menu[open] .ask-clinic-trigger {
  background: var(--color-surface-container);
  color: var(--color-on-surface);
}
.ask-clinic-trigger .material-symbols-outlined { font-size: 16px; }
.ask-clinic-caret { transition: transform 130ms ease; }
.ask-clinic-menu[open] .ask-clinic-caret { transform: rotate(180deg); }

/*  Opens UPWARD. This sits at the bottom of the page — on the Ask screen it is
    the last thing above the fold — and a menu dropping below would open
    off-screen or push the footer. */
.ask-clinic-pop {
  position: absolute;
  left: 0;
  bottom: calc(100% + 0.3rem);
  z-index: 40;
  min-width: 13rem;
  padding: 0.3rem;
  border-radius: 0.85rem;
  background: var(--color-surface-container-lowest);
  border: 1px solid var(--color-outline-variant);
  box-shadow: 0 -10px 30px color-mix(in srgb, var(--color-on-surface) 16%, transparent);
}

.ask-clinic-option {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.5rem 0.55rem;
  border: 0;
  border-radius: 0.6rem;
  background: none;
  color: var(--color-on-surface);
  font: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}
.ask-clinic-option:hover { background: var(--color-surface-container); }
.ask-clinic-option.active {
  background: var(--color-primary-container);
  color: var(--color-on-primary-container);
}
.ask-clinic-option .material-symbols-outlined { font-size: 17px; }
.ask-clinic-option-name { flex: 1 1 auto; }

/*  The tick is rendered on every row so the script can move it without
    rebuilding the menu; hidden on the rows that aren't selected, or they all
    read as chosen. */
.ask-clinic-check { display: none; }
.ask-clinic-option.active .ask-clinic-check { display: inline-flex; }

.ask-quota {
  margin: 0;
  font-size: 0.72rem;
  color: var(--color-on-surface-variant);
  text-align: right;
  margin-left: auto;
}
.ask-quota.is-low { color: var(--color-error, #b3261e); font-weight: 600; }

.ask-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.75rem;
}
.ask-chip {
  border: 1px solid color-mix(in srgb, var(--color-outline-variant) 70%, transparent);
  background: var(--color-surface-container-lowest);
  color: var(--color-on-surface-variant);
  border-radius: 999px;
  padding: 0.35rem 0.75rem;
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 130ms ease, color 130ms ease, background 130ms ease;
}
.ask-chip:hover {
  border-color: color-mix(in srgb, var(--color-primary) 45%, transparent);
  background: var(--color-primary-container);
  color: var(--color-on-primary-container);
}

/* ── the answer ─────────────────────────────────────────────────────── */
.ask-answer { margin-top: 0.95rem; }
.ask-thinking {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.85rem;
  color: var(--color-on-surface-variant);
}
.ask-dots { display: inline-flex; gap: 3px; }
.ask-dots i {
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--color-primary);
  animation: ask-pulse 1.05s ease-in-out infinite;
}
.ask-dots i:nth-child(2) { animation-delay: 0.15s; }
.ask-dots i:nth-child(3) { animation-delay: 0.3s; }
@keyframes ask-pulse {
  0%, 60%, 100% { opacity: 0.3; }
  30%           { opacity: 1; }
}

.ask-body {
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--color-on-surface);
}
.ask-body p { margin: 0 0 0.55rem; }
.ask-body p:last-child { margin-bottom: 0; }
.ask-body strong { font-weight: 700; }
.ask-body.is-error { color: var(--color-error, #b3261e); }
.ask-inline-cta { display: inline-flex; margin-top: 0.7rem; }

.ask-list { margin: 0.2rem 0 0.55rem; padding-left: 1.1rem; }
.ask-list li { margin-bottom: 0.2rem; }

/* Tables scroll inside their own box. Six pay periods on a phone is wider
   than the card, and letting that push the dashboard sideways would break
   every row above it, not just this one. */
.ask-table-wrap {
  overflow-x: auto;
  margin: 0.55rem 0;
  border-radius: 0.7rem;
  border: 1px solid color-mix(in srgb, var(--color-outline-variant) 60%, transparent);
}
.ask-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
  white-space: nowrap;
}
.ask-table th,
.ask-table td {
  padding: 0.5rem 0.75rem;
  text-align: left;
  border-bottom: 1px solid color-mix(in srgb, var(--color-outline-variant) 45%, transparent);
}
.ask-table tbody tr:last-child td { border-bottom: 0; }
.ask-table th {
  background: var(--color-surface-container);
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--color-on-surface-variant);
}
/* Amounts right-aligned on tabular figures, so a column of money reads as a
   column — the same treatment every other money table in the app gets. */
.ask-table .is-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.ask-trail {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.6rem;
  font-size: 0.74rem;
  color: var(--color-on-surface-variant);
}
.ask-trail .material-symbols-outlined { font-size: 15px; }

/* ── locked ─────────────────────────────────────────────────────────── */
.ask.is-locked {
  border-style: dashed;
  border-color: color-mix(in srgb, var(--color-outline-variant) 85%, transparent);
  background: var(--color-surface-container-lowest);
}
.ask-upsell {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  flex-wrap: wrap;
}
.ask-examples {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  font-size: 0.82rem;
  font-style: italic;
  color: var(--color-on-surface-variant);
}

@media (max-width: 720px) {
  .ask { padding: 1.05rem 1rem 1.15rem; }
  .ask-title { font-size: 1.15rem; }
  /* One per line, full width — four wrapped pills on a phone read as a
     paragraph of buttons rather than as a list of choices. */
  .ask-chips { flex-direction: column; align-items: stretch; }
  .ask-chip { text-align: left; }
}

/* Label that exists for assistive tech only. The ask field is a placeholder-
   led control by design — a visible label above a single pill would read as a
   form — but a placeholder is not a label, so the real one lives here. */
.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;
}

/* ═══ /Dashboard/Assistant — the Ask page ══════════════════════════════
   History rail on the left, transcript and composer on the right. The
   rail is narrow on purpose: it lists things already answered, and a
   dentist reopening one is looking for a remembered phrase, not browsing.
   Inside .pay-wrap, so the page gutter and content width come from the
   polish layer above rather than being restated here. */
.askpage {
  display: grid;
  grid-template-columns: 15rem minmax(0, 1fr);
  gap: 1.1rem;
  align-items: start;
  margin-top: 1.1rem;
  /* Animating the track itself keeps the conversation's left edge moving with
     the rail rather than snapping once it's gone. */
  transition: grid-template-columns 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

/*  Collapsed: no rail at all.

    The default. The conversation's widest output is a table, and 15rem of
    permanent chrome taxes exactly that for a list people consult rarely. What
    replaced the rail is not a narrower rail — it is two buttons in the toolbar
    above the conversation, which is where they were always going to be
    reached for. */
.askpage.is-rail-collapsed { grid-template-columns: minmax(0, 1fr); }
.askpage.is-rail-collapsed > .askpage-rail { display: none; }

/*  The collapsed history card: its own header, nothing else.

    Deliberately the SAME markup and styling as the open card's header, so the
    two states read as one component rather than as a pill that summons a
    panel. Expanding adds the list underneath; it does not swap one control
    for a different-looking one.

    Auto width and above the conversation, so collapsing actually returns the
    space — a header holding a 15rem column open would defeat the point. */
.askpage-stub {
  align-self: start;
  margin-bottom: 0.7rem;
  padding: 0.5rem 0.6rem;
  border-radius: 1.15rem;
  background: var(--color-surface-container-lowest);
  border: 1px solid color-mix(in srgb, var(--color-outline-variant) 70%, transparent);
}
.askpage-stub .askpage-rail-head { margin-bottom: 0; gap: 0.75rem; }

/*  The label is the expand control too — clicking the word "History" should
    do what the chevron does, since that is what anyone will try first. */
.askpage-stub-label {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: 0;
  background: none;
  padding: 0;
  cursor: pointer;
  font: inherit;
}

.askpage-bar-count {
  min-width: 1.1rem;
  padding: 0.05rem 0.3rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--color-primary) 16%, transparent);
  color: var(--color-primary);
  font-size: 0.66rem;
  font-weight: 800;
  line-height: 1.4;
  text-align: center;
}

/*  Exactly one of the two is ever on screen: the stub while collapsed, the
    full card once open. Both show the same header, so it reads as one panel
    opening rather than one control being replaced by another. */
.askpage:not(.is-rail-collapsed) .askpage-stub { display: none; }

/*  Controls inside the open rail's header. */
.askpage-rail-actions {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}
.askpage-rail-icon {
  display: inline-grid;
  place-items: center;
  width: 1.6rem;
  height: 1.6rem;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--color-on-surface-variant);
  text-decoration: none;
  cursor: pointer;
  transition: background 130ms ease, color 130ms ease;
}
.askpage-rail-icon:hover {
  background: var(--color-surface-container);
  color: var(--color-on-surface);
}
.askpage-rail-icon .material-symbols-outlined { font-size: 17px; display: block; }

/*  New stays the primary action wherever it appears. */
.askpage-rail-icon.is-primary {
  background: var(--color-primary);
  color: var(--color-on-primary);
}
.askpage-rail-icon.is-primary:hover {
  color: var(--color-on-primary);
  filter: brightness(1.06);
}



.askpage-rail:has(.askpage-thread-menu[open]) { overflow: visible; }
.askpage-rail {
  position: sticky;
  top: 1.1rem;
  /* Same box as the conversation beside it, scrolling separately — a long
     history must not stretch the page past the pinned composer. */
  max-height: calc(100dvh - 10.5rem);
  overflow-y: auto;
  /* A scroll container clips both axes, so an open menu would be cut off at
     the rail's edge. While one is open the rail stops scrolling and lets it
     out; the list is short enough that losing the scroll for a moment costs
     nothing. */
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--color-outline-variant) 90%, transparent) transparent;
  padding: 0.9rem;
  border-radius: 1.15rem;
  background: var(--color-surface-container-lowest);
  border: 1px solid color-mix(in srgb, var(--color-outline-variant) 70%, transparent);
}
.askpage-rail-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.7rem;
}
.askpage-new {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  font-size: 0.76rem;
  font-weight: 700;
  text-decoration: none;
  color: var(--color-primary);
}
.askpage-new .material-symbols-outlined { font-size: 16px; }
.askpage-rail-empty {
  margin: 0;
  font-size: 0.8rem;
  line-height: 1.45;
  color: var(--color-on-surface-variant);
}

.askpage-threads { list-style: none; margin: 0; padding: 0; }
.askpage-thread {
  display: flex;
  align-items: center;
  gap: 0.2rem;
  border-radius: 0.6rem;
  transition: background 130ms ease;
  /* An open menu has to sit above the rows below it. */
  position: relative;
}
.askpage-thread:has(.askpage-thread-menu[open]) { z-index: 30; }
.askpage-thread:hover { background: var(--color-surface-container); }
.askpage-thread.is-open { background: var(--color-primary-container); }
.askpage-thread > a {
  flex: 1 1 auto;
  min-width: 0;
  display: block;
  padding: 0.45rem 0.5rem;
  text-decoration: none;
  color: var(--color-on-surface);
}
.askpage-thread.is-open > a { color: var(--color-on-primary-container); }
.askpage-thread-title {
  display: block;
  font-size: 0.82rem;
  font-weight: 600;
  /* One line. A saved question is a label to recognise, not to re-read —
     and a rail this narrow would give three lines to most of them. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.askpage-thread-when {
  display: block;
  font-size: 0.7rem;
  color: var(--color-on-surface-variant);
}
.askpage-thread.is-open .askpage-thread-when { color: inherit; opacity: 0.75; }
/* ── per-thread menu ────────────────────────────────────────────────
   <details> rather than a scripted popover: it opens, closes on a second
   click, and works with scripting off — which matters because the two
   things inside it are the only ways to lose a conversation. */
.askpage-thread-menu { position: relative; flex: none; }
.askpage-thread-menu > summary {
  list-style: none;
  cursor: pointer;
  padding: 0.3rem;
  border-radius: 0.4rem;
  color: var(--color-on-surface-variant);
  /* Revealed on hover/focus, never removed from the tab order — a control
     that only exists on hover is unreachable by keyboard. */
  opacity: 0;
  transition: opacity 130ms ease, background 130ms ease;
}
.askpage-thread-menu > summary::-webkit-details-marker { display: none; }
.askpage-thread:hover .askpage-thread-menu > summary,
.askpage-thread-menu > summary:focus-visible,
.askpage-thread-menu[open] > summary { opacity: 1; }
.askpage-thread-menu > summary:hover { background: var(--color-surface-container-high); }
.askpage-thread-menu .material-symbols-outlined { font-size: 17px; display: block; }

.askpage-menu-pop {
  position: absolute;
  right: 0;
  top: calc(100% + 0.2rem);
  z-index: 20;
  /* Was 13rem to fit a text field. Two labelled rows need far less, and a
     menu wider than its contents reads as something failing to fill. */
  min-width: 9.5rem;
  padding: 0.35rem;
  border-radius: 0.75rem;
  background: var(--color-surface-container-lowest);
  border: 1px solid var(--color-outline-variant);
  box-shadow: 0 14px 34px color-mix(in srgb, var(--color-on-surface) 18%, transparent);
}
.askpage-menu-item {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  width: 100%;
  padding: 0.45rem 0.5rem;
  border: 0;
  border-radius: 0.5rem;
  background: none;
  color: var(--color-on-surface);
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}
.askpage-menu-item:hover { background: var(--color-surface-container); }
.askpage-menu-item .material-symbols-outlined { font-size: 16px; }
.askpage-menu-item.is-danger { color: var(--color-error, #b3261e); }
.askpage-menu-item.is-danger:hover {
  background: color-mix(in srgb, var(--color-error, #b3261e) 10%, transparent);
}

/* ── transcript ─────────────────────────────────────────────────────── */
/*  The conversation column is a fixed-height box, not a growing one: the
    composer is pinned to the BOTTOM of it and the transcript scrolls above,
    which is what makes this feel like a chat rather than a form with a
    growing list above it. The question box is the thing you came here to
    use, so it should be in the same place every time you arrive — not
    wherever the last answer happened to leave it. */
.askpage-main {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  min-width: 0;
  /* Viewport minus the app header, page heading and footer breathing room.
     dvh so a phone's collapsing address bar doesn't leave the composer
     under the fold. */
  /*  Measured, not guessed.

      Every fixed value tried here was wrong: the space above this column is a
      header plus a page heading whose height depends on the breadcrumb, the
      clinic name and whether anything wraps. A calc() against a constant
      overshot by ~124px and put a scrollbar on a page that fits.

      assistant.js measures the real top offset and writes --ask-h. The
      fallback covers the moment before it runs and a browser with scripting
      off — it errs small, since a column slightly too short scrolls its own
      transcript, while one too tall puts a scrollbar on the window. */
  height: var(--ask-h, calc(100dvh - 13rem));
  min-height: 20rem;
}
.askpage-log {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  /* Takes the slack; min-height:0 is what actually lets a flex child
     scroll instead of growing past its parent. */
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  /* Room for the scrollbar to sit in rather than on top of the text. A
     table's right-aligned money column runs to the edge of its box, and a
     default-width bar landing against it reads as a border that doesn't
     line up with anything. */
  padding-right: 0.85rem;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--color-outline-variant) 90%, transparent) transparent;
}
/* WebKit needs it spelled out. Track stays transparent so the bar appears
   over the page rather than carving a channel down the side of it. */
.askpage-log::-webkit-scrollbar { width: 8px; }
.askpage-log::-webkit-scrollbar-track { background: transparent; }
.askpage-log::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--color-outline-variant) 90%, transparent);
  border-radius: 999px;
  /* Inset by its own border so the thumb reads as 4px of colour with air
     either side, instead of a full-width slab. */
  border: 2px solid transparent;
  background-clip: content-box;
}
.askpage-log::-webkit-scrollbar-thumb:hover {
  background: color-mix(in srgb, var(--color-outline) 80%, transparent);
  background-clip: content-box;
}
/* Pinned to the bottom of the column. margin-top:auto rather than a fixed
   position so it stays inside the content width and never overlaps the
   sidebar or the footer. */
.askpage-composer {
  margin-top: auto;
  flex: none;
  /* Sits close to the footer on purpose — it is the last thing on the page and
     a wide gap under it reads as something failing to load. */
  padding-bottom: 0.35rem;
}

.askturn { display: flex; }
.askturn-user { justify-content: flex-end; }
.askturn-user .askturn-body {
  max-width: 80%;
  padding: 0.6rem 0.9rem;
  border-radius: 1.1rem 1.1rem 0.3rem 1.1rem;
  background: var(--color-primary-container);
  color: var(--color-on-primary-container);
  font-size: 0.92rem;
  line-height: 1.5;
}
/* The answer is not a bubble. It carries money figures and sometimes a
   table, and boxing that on the left would fight the tables for width —
   so it reads as the page's own prose while the question stays a bubble. */
.askturn-assistant .askturn-body {
  width: 100%;
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--color-on-surface);
}
.askturn-assistant .askturn-body p { margin: 0 0 0.55rem; }
.askturn-assistant .askturn-body p:last-child { margin-bottom: 0; }
.askturn-assistant .askturn-body strong { font-weight: 700; }

.askpage-empty {
  margin: auto;
  max-width: 34rem;
  text-align: center;
  color: var(--color-on-surface-variant);
}
.askpage-empty .material-symbols-outlined {
  font-size: 34px;
  color: var(--color-primary);
}
.askpage-empty h2 {
  margin: 0.5rem 0 0.3rem;
  font-family: "Manrope", sans-serif;
  font-weight: 800;
  font-size: 1.25rem;
  letter-spacing: -0.02em;
  color: var(--color-on-surface);
}
.askpage-empty p { margin: 0; font-size: 0.88rem; line-height: 1.55; }

/*  The composer reuses .ask's INNER parts — the field, the send button, the
    quota rail — but none of its card. On the dashboard .ask is a card because
    it sits among other cards; here it sits under a transcript that is already
    on the page's surface, and a bordered box around it read as a card inside a
    card. The field's own pill is the only edge this needs.

    Animation off too: it is the control the page is FOR, and it must not slide
    in after the transcript it belongs to. */
.askpage-composer {
  margin-bottom: 0;
  animation: none;
  background: none;
  border: 0;
  border-radius: 0;
  padding: 0.35rem 0 0;
}
.askpage-locked { margin-bottom: 0; }

@media (max-width: 980px) {
  /* The rail goes under the conversation, not beside it. Above the fold on
     a phone belongs to the question box; history is something you go
     looking for. */
  /* Stacked. The strip is a desktop affordance — on a phone the rail simply
     goes below the conversation, where it is already out of the way. */
  .askpage,
  .askpage.is-rail-collapsed { grid-template-columns: minmax(0, 1fr); }
  .askpage.is-rail-collapsed > .askpage-rail { display: block; }
  .askpage-rail { position: static; order: 2; max-height: none; }
  /* Height comes back off on a phone: the page scrolls as one, because a
     nested scroll region inside a scrolling page is the thing that makes
     mobile chat UIs feel broken. */
  .askpage-main { order: 1; height: auto; min-height: 0; }
  .askpage-log { overflow: visible; }
}

/* ── table export controls ──────────────────────────────────────────────
   Above the table, outside its scroll box. A wide table scrolls sideways,
   and a control placed inside would slide out of reach exactly when the
   table is big enough to be worth exporting. */
.ask-table-block { margin: 0.55rem 0; }
.ask-table-block > .ask-table-wrap { margin: 0; }
.ask-table-tools {
  display: flex;
  justify-content: flex-end;
  gap: 0.3rem;
  margin-bottom: 0.3rem;
}
.ask-table-tool {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.2rem 0.5rem;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--color-outline-variant) 70%, transparent);
  background: var(--color-surface-container-lowest);
  color: var(--color-on-surface-variant);
  font: inherit;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-decoration: none;
  cursor: pointer;
  transition: border-color 130ms ease, color 130ms ease, background 130ms ease;
}
.ask-table-tool:hover {
  border-color: color-mix(in srgb, var(--color-primary) 45%, transparent);
  background: var(--color-primary-container);
  color: var(--color-on-primary-container);
}
.ask-table-tool .material-symbols-outlined { font-size: 14px; }

/* Starter questions now live inside the empty state, so they centre with the
   invitation instead of running to the left edge under a composer. */
.askpage-empty .ask-chips {
  justify-content: center;
  margin-top: 1rem;
}
@media (max-width: 720px) {
  /* The global rule stacks chips full-width under the dashboard composer; in
     the invitation they should stay centred pills, not a column of bars. */
  .askpage-empty .ask-chips { flex-direction: row; flex-wrap: wrap; }
}

/*  The assistant crumb renders a check on EVERY option so the script can move
    the tick without rebuilding the menu — the global crumb re-renders on a post
    and can afford to emit it only on the active row. Hidden here for the rows
    that aren't selected, or all three read as chosen.

    display:none rather than visibility, so the menu's row width matches the
    global crumb's instead of reserving a column of empty ticks. */
#ask-clinic-crumb .crumb-clinic-option .crumb-clinic-check { display: none; }
#ask-clinic-crumb .crumb-clinic-option.active .crumb-clinic-check { display: inline-flex; }

/*  The Ask page owns the viewport.

    It is a chat surface: the transcript scrolls inside its own column and the
    composer is pinned under it, so a second scrollbar on the window has
    nothing to scroll to and just sits there looking broken.

    :has() rather than a body class, so no layout plumbing is needed for one
    route. Browsers without :has() keep the ordinary page scroll, which is the
    behaviour that exists today rather than a broken one.

    The footer goes with it — under a pinned composer it would be unreachable,
    and a link nobody can click is worse than one that isn't there. */
body:has(.askpage) { overflow: hidden; }
body:has(.askpage) .app-footer { display: none; }

/*  The rename field fills its dialog. .input sizes to its content by default,
    which left a title box narrower than most titles — you could not see what
    you were editing. */
#askpage .proc-modal .input,
dialog.proc-modal[id^="ask-rename-"] .input {
  width: 100%;
  box-sizing: border-box;
  font-size: 0.95rem;
}
dialog.proc-modal[id^="ask-rename-"] .proc-modal-body,
dialog.proc-modal[id^="ask-delete-"] .proc-modal-body { min-width: 22rem; }
