@import url('fonts.css');

/*
 * app.css
 * =======
 * RejuvStem Design Standard v1.0.
 *
 * NO INLINE STYLE ANYWHERE. The CSP is `style-src 'self'`, so a `style=` on an
 * element is silently dropped by the browser and the page renders subtly wrong
 * with nothing in the console to explain it. Every rule lives here.
 *
 * THE GOLD RULE: gold fills and gold rules, but gold never spells. On a light
 * ground #B89150 fails contrast at text sizes, so text that wants to read as
 * gold uses --gold-text, which is the same hue darkened until it is legible.
 *
 * Square corners throughout. No border-radius in this file, deliberately.
 *
 * Fonts are system stacks. Google Fonts would need `font-src https://...` and a
 * network round trip on a login page; the display face is self-hosted later if
 * the difference proves to matter.
 */

:root {
  /* JIMMY DESIGN STANDARD v1.0, SECTION 1. The site's palette, taken
     verbatim from jimmybluff.com on 5 September 2026. This block is the ONE
     place a color is defined; docs/JIMMY-DESIGN-STANDARD.md names each. */
  --navy:           #283A6C;
  --navy-deep:      #1B2A52;
  --blue:           #157EBF;
  --blue-deep:      #0F639A;
  --blue-mid:       #3793BB;
  --sky:            #5EC2F6;
  --sky-light:      #CFE8F8;
  --sky-on-dark:    var(--sky);
  --tint:           #CEE5F0;
  --tint-deep:      #A9CBE0;
  --tint-light:     #EDF9FF;
  --off:            #F4F6FC;
  --white:          #FFFFFF;
  --ink:            #252525;
  --ink-soft:       #3D4358;
  --ink-mute:       #6A7186;
  --hair:           rgba(40, 58, 108, .12);
  --attention:      #B23A2E;
  --attention-tint: #F9E9E6;
  --watch:          #B7791F;
  --watch-tint:     #FBF2DF;
  --done:           #2E7D5B;
  --done-tint:      #E1F0E8;

  /* Myriad Pro is the site's face, self-hosted in fonts.css. Barlow
     Condensed and Source Sans 3 are the web fallbacks the style guide uses. */
  --display:        'Myriad Pro Cond', 'Barlow Condensed', 'Arial Narrow', Arial, sans-serif;
  --sans:           'Myriad Pro', 'Source Sans 3', 'Helvetica Neue', Arial, sans-serif;
  --mono:           'IBM Plex Mono', Consolas, 'Courier New', monospace;

  /* RejuvStem'S VOCABULARY, MAPPED ONTO THE ABOVE. Three thousand lines of
     sheet were written against forest, gold, cream and sand, and every one
     of them still reads correctly when those names point at this palette:
     forest is structure (navy), gold is the accent (sky on dark, blue as
     text), cream is the ground (off-white), sand is the hairline (tint).
     The aliases stay until each sheet is rewritten in the new names, and a
     new rule never uses one of these: it uses the token above. */
  --forest:        var(--navy);
  --forest-deep:   var(--navy-deep);
  --forest-soft:   var(--blue-deep);
  --gold:          var(--sky);
  --gold-deep:     var(--blue-deep);
  --gold-text:     var(--blue);
  --gold-light:    var(--sky-light);
  --gold-on-dark:  var(--sky);
  --sand:          var(--tint);
  --sand-deep:     var(--tint-deep);
  --cream:         var(--off);
  --cream-warm:    var(--white);
  --cream-alt:     var(--tint-light);
  --sage:          var(--done);
  --fail:          var(--attention);
  --fail-tint:     var(--attention-tint);
  --serif:         var(--display);
  --paper:         var(--white);
  --rule:          var(--hair);
  --error:         var(--attention);
  --error-bg:      var(--attention-tint);
  --ok:            var(--done);
  --ink-faint:     var(--ink-mute);
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* ------------------------------------------------------------ centered ---- */
.centered {
  min-height: 100%;
  display: grid;
  place-items: center;
  padding: 2rem 1rem;
}

.card {
  width: 100%;
  max-width: 26rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-top: 3px solid var(--forest);
  padding: 2rem;
}

.card-wide { max-width: 34rem; }

/* THE BRAND BAND, full-bleed inside the card. The negative margin cancels the
   card's own 2rem padding so the band meets the border rather than floating in
   a white gutter - and the top edge lands on the card's existing 3px forest
   rule, which is now the same color continuing.

   The mark is gold on forest because that is the asset as drawn: gold type on a
   light ground fails contrast, which is why this application's rule is that
   gold fills and rules but never spells on light. The band gives it the ground
   it was made for. */
.card-brand {
  margin: -2rem -2rem 1.7rem;
  padding: 1.35rem 2rem;
  background: var(--forest);
  text-align: center;
}

.card-brand-mark {
  display: inline-block;
  width: 100%;
  max-width: 13.5rem;
  height: auto;
}

/* --------------------------------------------------------------- type ---- */
h1 {
  font-family: var(--display);
  font-weight: 500;
  font-size: 1.9rem;
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin: 0 0 0.4rem;
  color: var(--forest);
  text-wrap: balance;
}

h2 {
  font-family: var(--display);
  font-weight: 500;
  font-size: 1.35rem;
  margin: 1.8rem 0 0.5rem;
  color: var(--forest);
}

p { margin: 0 0 1rem; }
p.lede { color: var(--ink-soft); }
p:last-child { margin-bottom: 0; }

.eyebrow {
  font-family: var(--mono);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  /* gold-text, not gold: this is type on a light ground */
  color: var(--gold-text);
  margin: 0 0 0.9rem;
}

.fine {
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin-top: 1.2rem;
}

/* A LINK INSIDE BODY COPY. There was no rule for one until the sign-in card
   needed "set or reset your password": everything else on these pages is a
   button, so the first inline link rendered in browser-default blue - the one
   color this brand does not have. */
.lede a, .fine a, .flash a {
  color: var(--forest);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.lede a:hover, .fine a:hover, .flash a:hover { color: var(--forest-deep); }

/* -------------------------------------------------------------- forms ---- */
label {
  display: block;
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  margin-bottom: 0.35rem;
  color: var(--ink);
}

input[type="text"],
input[type="email"],
input[type="password"] {
  width: 100%;
  padding: 0.7rem 0.8rem;
  font-family: var(--sans);
  font-size: 1rem;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule);
  /* 8px, THE STANDARD'S INPUT RADIUS (section 3), and it belongs here rather
     than only in shape.css.

     It was `0` - RejuvStem's square-cornered default - with shape.css setting
     8px later to undo it. That works on every signed-in screen, because they
     load shape.css. THE PUBLIC PAGES DO NOT, so `input[type="text"]` at
     specificity (0,1,1) quietly beat every page sheet's `.en-input` and
     `.input` at (0,1,0), and the enrollment form, the waiver's signature field
     and the intake form all shipped with square inputs while their own
     stylesheets said 8px. Nothing looked broken, which is why it lasted.

     Fixed at the base so a page cannot inherit the wrong default again; the
     duplicate rule in shape.css is now redundant and harmless. */
  border-radius: 8px;
}

input:focus-visible,
button:focus-visible,
a:focus-visible {
  outline: 2px solid var(--forest);
  outline-offset: 2px;
}

/* Stacked fields. A single-field form never needed this - the button carries
   its own top margin - but the password forms put three in a column, and
   without it the label of the next field sits on the box above it. */
input + label { margin-top: 1.1rem; }

/* The six-digit code. Monospace and spaced, so a transposed pair is visible. */
input.code {
  font-family: var(--mono);
  font-size: 1.5rem;
  letter-spacing: 0.4em;
  text-align: center;
  padding: 0.7rem 0.4rem;
}

button, .button {
  display: inline-block;
  width: 100%;
  margin-top: 1.2rem;
  padding: 0.75rem 1rem;
  font-family: var(--sans);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--cream);
  background: var(--forest);
  border: 1px solid var(--forest);
  border-radius: 0;
  cursor: pointer;
  text-align: center;
  text-decoration: none;
}

button:hover, .button:hover { background: var(--forest-deep); }

.button-quiet {
  color: var(--forest);
  background: transparent;
  border-color: var(--rule);
}
.button-quiet:hover { background: var(--cream); }

/* A LITERAL IN RUNNING TEXT - a password, a path, a field key. There was no
   rule for `code` at all, so the one place that needed it (the development
   password on the sign-in page) rendered as ordinary prose, which is the one
   thing a literal must not do: the reader has to be able to see where it
   starts and stops. */
code {
  font-family: var(--mono);
  font-size: 0.92em;
  padding: 0.1em 0.35em;
  background: var(--cream);
  border: 1px solid var(--rule);
  color: var(--ink);
}

/* The clinical schedule in the drawer. */
.appt-list { list-style: none; margin: 0 0 0.9rem; padding: 0; }

.appt {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.15rem 0.6rem;
  padding: 0.45rem 0.6rem;
  margin-bottom: 0.35rem;
  border-left: 3px solid var(--sand-deep);
  background: var(--cream-warm);
  font-size: 0.82rem;
}

.appt-when {
  grid-column: 1;
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--ink-mute);
}

.appt-title { grid-column: 1; font-weight: 600; color: var(--ink); }
.appt-detail { grid-column: 1; color: var(--ink-soft); font-size: 0.75rem; }

.appt-drop {
  grid-column: 2;
  grid-row: 1 / span 3;
  width: auto;
  margin: 0;
  align-self: center;
  padding: 0.2rem 0.5rem;
  font-size: 0.7rem;
  color: var(--ink-soft);
  background: transparent;
  border: 1px solid var(--rule);
}

.appt-drop:hover { color: var(--fail); border-color: var(--fail); background: var(--fail-tint); }

/* THE QUICK ADD ROW. Date and time side by side, kind and title beneath -
   and on a narrow screen everything goes full width, because a date input
   squeezed into half a phone is a date input nobody can use. */
.appt-add {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.4rem;
  margin-bottom: 0.6rem;
}

.appt-add .edit-input:nth-child(3),
.appt-add .edit-input:nth-child(4) { grid-column: 1 / -1; }

/* Big enough to hit with a thumb. 16px on the input itself is not decoration:
   iOS zooms the whole page in on focus for anything smaller, and the drawer
   never comes back the same size. */
.appt-add .edit-input,
.appt-paste textarea {
  min-height: 2.6rem;
  font-size: 16px;
}

@media (max-width: 34rem) {
  .appt-add { grid-template-columns: 1fr; }
}

/* In the manager there is room for the whole row on one line. Scoped to the
   panel so the drawer's own two-column version is untouched - and behind a
   width query, because the panel is full screen on a phone and a phone has no
   more room here than the drawer did. */
@media (min-width: 44rem) {
  .pv .appt-add { grid-template-columns: 10rem 7.5rem 9rem 1fr; }
  .pv .appt-add .edit-input:nth-child(3),
  .pv .appt-add .edit-input:nth-child(4) { grid-column: auto; }
}

/* A label between the list and the editor in the schedule manager. A `div`,
   not a heading: the panel's name comes from its `aria-label`, and an <h4>
   with no <h3> above it inside a dialog is a worse outline than none. */
.appt-heading { margin: 1.4rem 0 0.5rem; }

/* Pasting a whole day. */
.appt-paste textarea { width: 100%; font-family: var(--mono); line-height: 1.6; }

.appt-preview { margin: 0.6rem 0; }

.appt-prow {
  display: grid;
  grid-template-columns: 4.5rem 1fr 7rem;
  gap: 0.5rem;
  align-items: center;
  padding: 0.3rem 0;
  border-bottom: 1px solid var(--rule);
  font-size: 0.8rem;
}

.appt-prow .edit-input { min-height: 2rem; font-size: 0.78rem; padding: 0.2rem 0.3rem; }

/* THE PREVIEW SHARES `.appt-when` AND `.appt-title` WITH THE LIST ABOVE, and
   those carry `grid-column: 1` for the stacked list layout. Unset here, the
   title landed in the 4.5rem time column and wrapped one word per line. Shared
   class names are cheap right up until two grids disagree about them. */
.appt-prow .appt-when { grid-column: 1; }
.appt-prow .appt-title { grid-column: 2; }

@media (max-width: 34rem) {
  .appt-prow { grid-template-columns: 5rem 1fr; }
  .appt-prow .edit-input { grid-column: 1 / -1; }
}

/* THE SAME COLORS AS THE CALENDAR, so a row means the same thing in both
   places. Color never carries it alone - the kind is written out on the
   calendar and chosen from a named list here. */
.appt.kind-pickup    { border-left-color: var(--gold); }
.appt.kind-consult   { border-left-color: var(--forest); }
.appt.kind-treatment { border-left-color: var(--fail); }
.appt.kind-hospital  { border-left-color: var(--watch); }
.appt.kind-rest      { border-left-color: var(--sage); }

/* Correcting a patient's details in the drawer. */
.edit-row { margin-bottom: 0.7rem; }

.edit-label {
  display: block;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
  margin-bottom: 0.25rem;
}

.edit-input {
  width: 100%;
  padding: 0.5rem 0.6rem;
  font-family: var(--sans);
  font-size: 0.9rem;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 8px;  /* 8px: section 3. Was 0, and beat shape.css on specificity. */
}

/* THE WARNING CARRIES WEIGHT ON PURPOSE. It is the whole reason a local-only
   edit is safe to offer: somebody who does not read it will correct an address
   here and believe mail now goes to it. */
.edit-warn {
  border-left: 3px solid var(--watch);
  background: var(--watch-tint);
  padding: 0.6rem 0.75rem;
  margin-top: 0.9rem;
  color: var(--ink-soft);
}

/* The keyboard route to the same thing, in the drawer. */
.stage-row {
  display: flex;
  gap: 0.6rem;
  align-items: center;
}

.stage-row .stage-pick { flex: 1 1 auto; }

.stage-row button { width: auto; margin-top: 0; flex: 0 0 auto; }

/* -------------------------------------------------------- moving a card --- */
/* Press and hold a card and it lifts; the ghost follows the pointer and the
   column under it lights up. See move.js for why it is a hold rather than a
   plain drag - on a phone the cards are the column, and a plain drag has to
   stay available for scrolling. */

/* The card left behind. Kept in place rather than removed so the column does
   not reflow under the finger mid-gesture, which makes the drop land somewhere
   the person did not aim at. */
.card.is-lifted {
  opacity: 0.35;
  filter: grayscale(1);
}

/* What actually follows the pointer. `pointer-events: none` is load-bearing:
   elementFromPoint has to read the column underneath, not this. */
.card-ghost {
  position: fixed;
  z-index: 60;
  margin: 0;
  pointer-events: none;
  box-shadow: 0 10px 30px rgba(40, 58, 108, .3);
  transform: rotate(-1.5deg);
  opacity: 0.95;
}

/* Where it would land. A tinted body and a solid edge, because a border alone
   is easy to miss under a finger that is covering half the column. */
.col.is-target .col-body {
  background: var(--done-tint);
  outline: 2px solid var(--forest);
  outline-offset: -2px;
}

.col.is-saving .col-body { opacity: 0.6; }

/* No text selection while carrying, and no long-press menu on iOS - both turn
   a move into a mess halfway through. */
body.is-moving {
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

@media (prefers-reduced-motion: reduce) {
  .card-ghost { transform: none; }
}

/* -------------------------------------------------------- the calendar --- */
.cal-head {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: flex-end;
  justify-content: space-between;
  margin-bottom: 1.4rem;
}

/* THE MONTH, WHICH IS THE HEADING NOW. It was a `.lede` under an `<h1>` that
   said "Treatment Calendar" - and that title moved into the band at the top of
   the page, where every page's title is. So the only heading left on this
   screen is the one that answers the question somebody clicking an arrow is
   asking, and it is set at a heading's size rather than a caption's.

   TIGHT TO THE ZONE LINE UNDER IT. The two are one block: which period, and
   whose clock the times in it are on. */
.cal-when {
  font-family: var(--display);
  font-size: 1.5rem;
  font-weight: 500;
  line-height: 1.15;
  color: var(--navy);
  margin: 0 0 0.15rem;
}

/* THE VIEW CONTROLS, WHICH WERE NEVER STYLED AT ALL.
   -------------------------------------------------------------------------
   They were written as `class="tab"`, and `.tab` is defined in
   `board-layout.css`, which only the board loads. So on the calendar they were
   browser-default links: blue, underlined, purple once visited, in a page that
   has no other blue in it. It rendered, it worked, and it looked like a 1998
   index page under a display heading.

   `.cal-views` AND `.cal-move` ARE GONE. They were the old two groups; the
   markup now says `.cal-seg` for every group, because there are four of them
   and naming each after its job meant a new class for each new one.

   A SEGMENTED CONTROL RATHER THAN LOOSE BUTTONS, because Month, Week and Day
   are one question with three answers - and the filled one IS the answer, so
   which view you are in is readable without comparing the three.

   NAVY FILL, NOT SKY. The board's tabs fill with sky and they can: they sit on
   navy. This strip sits on the page, where sky as type is refused throughout
   this application - `test_sky_never_spells_on_a_light_ground` would fail, and
   it is right to. */
.cal-controls {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
  align-items: center;
}

.cal-seg {
  display: flex;
  border: 1px solid var(--tint-deep);
  background: var(--white);
  /* Rounded, because everything else on a Jimmy screen is - and clipped, so
     the filled tab's corners follow the group rather than squaring it off. */
  border-radius: 8px;
  overflow: hidden;
}

.cal-tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.1rem;
  padding: 0 0.85rem;
  border-left: 1px solid var(--tint-deep);
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--navy);
  text-decoration: none;
  white-space: nowrap;
  background: none;
  cursor: pointer;
}

/* The group draws the outer border; the children draw the dividers. Without
   this the first child doubles the left edge and the strip sits a pixel out of
   line with everything under it. */
.cal-tab:first-child { border-left: 0; }

.cal-tab:hover { background: var(--tint-light); }

/* Inset, because an outset ring on a segmented control is drawn over its
   neighbor and reads as the wrong item being focused. */
.cal-tab:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }

.cal-tab.on,
.cal-tab.on:hover { background: var(--navy); color: var(--white); }

/* One glyph rather than a word, so the box sets the width and the tracking
   that spaces capitals is turned off. */
.cal-arrow { padding: 0 0.75rem; font-size: 15px; letter-spacing: 0; }

/* THE ATTRIBUTE HAS TO BEAT THE DISPLAY RULE. `display: inline-flex` above is
   an author rule and the user agent's `[hidden] { display: none }` is not, so
   `go.hidden = true` in calendar.js would set the attribute and change nothing
   on screen. */
.cal-tab[hidden] { display: none; }

/* THE ONE ACTION IN THE STRIP, so it is filled - the same navy the current tab
   wears, because on this strip "filled" already means "this is the one".

   IT IS NOT A `.button`. Left to the page's own button styles it arrived as a
   full-width navy pill three times the height of the strip beside it, which is
   what the first pass shipped. */
.cal-tab.cal-go,
.cal-tab.cal-go:hover { background: var(--navy); color: var(--white); }

/* Jumping to a date. The input carries no border of its own - the group draws
   it, the same as every other item in the strip - and inherits the strip's
   type so a native date field does not arrive in the browser's own font. */
.cal-jump { align-items: stretch; }

.cal-date {
  border: 0;
  background: transparent;
  padding: 0 0.6rem;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--ink);
  min-height: 2.1rem;
}

.cal-date:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }

/* Sample data is a different KIND of thing from the view switcher - it changes
   what the calendar is showing, not how. It keeps the amber every sample
   affordance in this application uses, and stands on its own. */
.cal-sample { color: var(--watch); }
.cal-sample:hover { background: var(--watch-tint); color: var(--watch); }

/* THE SAME ANSWER THE BORDER COLOR GIVES, IN A SECOND CHANNEL. Color alone
   means nothing to somebody who cannot separate these hues, which is why the
   label is always written out - a shape is the cheaper half of that promise,
   read before the words on a grid of forty-two cells. `currentColor` so it
   takes the row's own ink rather than needing a rule per kind. */
.cal-icon {
  width: 11px;
  height: 11px;
  vertical-align: -1px;
  margin-right: 3px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* The sprite itself is markup, not a picture. */
.cal-sprite { display: none; }

.cal-bad {
  display: block;
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--ink-soft);
}

.cal-foot { margin-top: 1.2rem; }

/* The grid is seven columns whatever the view - a week is a month with one
   row, which keeps one set of markup and one set of rules rather than two that
   drift apart. */
.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
}

.cal-dayname {
  background: var(--cream-alt);
  padding: 0.45rem 0.6rem;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

.cal-cell {
  background: var(--paper);
  min-height: 7rem;
  padding: 0.4rem;
}

.cal-grid-week .cal-cell { min-height: 16rem; }

/* The neighboring month's days. Dimmed rather than hidden: a trip arriving on
   the 31st of the month before is still a trip somebody is about to work. */
.cal-out { background: var(--cream-warm); }
.cal-out .cal-num { color: var(--ink-mute); }

.cal-today { box-shadow: inset 0 0 0 2px var(--forest); }

.cal-num {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--ink-soft);
  text-decoration: none;
  margin-bottom: 0.3rem;
}

.cal-num:hover { color: var(--forest); text-decoration: underline; }

.cal-item {
  display: block;
  margin-bottom: 0.25rem;
  padding: 0.25rem 0.35rem;
  font-size: 0.72rem;
  line-height: 1.35;
  border-left: 3px solid var(--sand-deep);
  background: var(--cream-warm);
}

/* WHICH LEG OF THE TRIP, BY COLOR AND POSITION BOTH. Color alone would mean
   nothing to somebody who cannot separate these hues, so the label is always
   written out beside it. */
.cal-item.kind-arrival  { border-left-color: var(--forest); }
.cal-item.kind-checkin  { border-left-color: var(--gold); }
.cal-item.kind-checkout { border-left-color: var(--sand-deep); }
.cal-item.kind-departure{ border-left-color: var(--sage); }

/* The clinical kinds, matching the drawer exactly. */
.cal-item.kind-pickup    { border-left-color: var(--gold); }
.cal-item.kind-consult   { border-left-color: var(--forest); }
.cal-item.kind-treatment { border-left-color: var(--fail); }
.cal-item.kind-hospital  { border-left-color: var(--watch); }
.cal-item.kind-rest      { border-left-color: var(--sage); }

.cal-time {
  font-family: var(--mono);
  font-size: 0.68rem;
  color: var(--ink-mute);
  margin-right: 0.3rem;
}

.cal-who { font-weight: 600; color: var(--ink); }
.cal-what { display: block; color: var(--ink-soft); }
.cal-detail { display: block; color: var(--ink-mute); font-size: 0.68rem; }

.cal-day .cal-list { list-style: none; margin: 0; padding: 0; }

.cal-day .cal-item {
  font-size: 0.9rem;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--rule);
  border-left-width: 4px;
}

.cal-none { color: var(--ink-mute); padding: 2rem 0; }

/* The trips it could not place. Above the calendar, in the warning color,
   because a patient missing from a calendar somebody trusts is the failure
   this screen most needs to avoid. */
.cal-unread {
  border-left: 3px solid var(--watch);
  background: var(--watch-tint);
  padding: 0.9rem 1rem;
  margin-bottom: 1.4rem;
}

.cal-unread h2 { margin: 0 0 0.3rem; font-size: 1rem; }
.cal-bad { display: block; font-family: var(--mono); font-size: 0.75rem; color: var(--ink-soft); }
.cal-foot { margin-top: 1.2rem; }

@media (max-width: 60rem) {
  .cal-grid { font-size: 0.9em; }
  .cal-cell { min-height: 5.5rem; }
}

/* ------------------------------------------------------------- stale ------ */
/* Shown when the ten-second poll finds the board has moved and the person is
   busy - a drawer open, or typing. Bottom left, out of the way of the drawer
   on the right and the masthead above. It is a notice, not a dialog: nothing
   is blocked and nothing takes focus. */
.stale {
  position: fixed;
  left: 1.25rem;
  bottom: 1.25rem;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.6rem 0.7rem 0.6rem 1rem;
  background: var(--forest);
  color: var(--cream);
  border: 1px solid var(--forest-deep);
  box-shadow: 0 6px 24px rgba(40, 58, 108, .28);
  font-size: 0.85rem;
}

/* HIDDEN MEANS HIDDEN. `display: flex` above outranks the browser's own
   `[hidden] { display: none }`, so the notice was on screen from the first
   paint on every board, before any poll had run - inherited from RejuvStem,
   found on this fork's first screenshot. board.js and move.js both toggle the
   attribute; this is the rule that makes the attribute mean something. */
.stale[hidden] { display: none; }

.stale-go {
  width: auto;
  margin: 0;
  padding: 0.35rem 0.8rem;
  font-size: 0.8rem;
  color: var(--forest);
  background: var(--cream);
  border-color: var(--cream);
}

.stale-go:hover { background: var(--white); }

@media (max-width: 44rem) {
  .stale { left: 0.75rem; right: 0.75rem; bottom: 0.75rem; }
}

/* ---------------------------------------------------------------- qr ------ */
/* The enrollment code. White ground and a real quiet zone are not decoration -
   a scanner needs both to find the code, and the quiet zone is drawn into the
   SVG itself so that no container style can take it away. */
.qr-wrap {
  display: flex;
  justify-content: center;
  margin: 1.2rem 0;
}

.qr {
  width: 100%;
  max-width: 15rem;
  height: auto;
  background: var(--white);
  color: var(--ink);
  /* Crisp edges. Smoothing a 45-module code up to 240px turns every boundary
     into a gray ramp, which is exactly what a scanner has to threshold back
     out again. */
  image-rendering: pixelated;
  shape-rendering: crispEdges;
}

/* The typed-key fallback, folded away. It is the second-best route for almost
   everybody, so it should not be the first thing on the page - but it is the
   only route on a desktop authenticator with no camera. */
.by-hand > summary {
  cursor: pointer;
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin-bottom: 0.6rem;
}

/* --------------------------------------------------------------- sso ------ */
/* The Google button. Outlined rather than solid so the page still has exactly
   one primary action - "Sign in" - and this reads as the alternative route it
   is, not as a competing call to action. */
.button-sso {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  color: var(--ink);
  background: var(--paper);
  border-color: var(--rule);
  margin-top: 0;
}

.button-sso:hover { background: var(--cream); }

.sso-mark { flex: 0 0 auto; }

/* A rule with a word sitting in it. The line is drawn by the pseudo-elements
   either side rather than by a border on the paragraph, so the gap around the
   word is the word's own width and stays right at any font size. */
.or {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 1.2rem 0;
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

.or::before, .or::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--rule);
}

/* -------------------------------------------------- staff notes ---------- */
/* Notes on PATIENT pages that only staff may read. See
   templates/public/_staff.html for why the gate is in the macro.

   Deliberately unlike the page around it - mono, a dashed rule, no gold, no
   serif. A note that wears the page's own clothes is one a person skims past
   as content; this one has to read as scaffolding at a glance, because the
   whole risk it guards against is somebody not noticing which audience is
   looking. It is defined here rather than per page so every internal note on
   every patient page looks the same. */
.staff-note { padding: 32px 56px 0; }

.staff-note-inner {
  border: 1px dashed var(--sand-deep);
  background: var(--cream-warm);
  padding: 20px 22px;
}

.staff-note-tag {
  margin: 0 0 10px;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--ink-mute);
}

.staff-note-head {
  margin: 0 0 8px;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink);
}

.staff-note-body {
  font-family: var(--sans);
  font-size: 13px;
  line-height: 1.75;
  color: var(--ink-soft);
}

.staff-note-body :last-child { margin-bottom: 0; }

@media (max-width: 640px) { .staff-note { padding: 24px 24px 0; } }

/* NEVER ON PAPER. A concierge printing a page to hand over should not hand
   over the production notes with it. */
@media print { .staff-note { display: none; } }

/* -------------------------------------------------------------- flash ---- */
.flash {
  padding: 0.7rem 0.9rem;
  margin-bottom: 1.2rem;
  font-size: 0.9rem;
  border-left: 3px solid var(--forest);
  background: var(--cream);
}

.flash-error {
  border-left-color: var(--error);
  background: var(--error-bg);
  color: var(--error);
}

/* ------------------------------------------------------------ secrets ---- */
.secret {
  font-family: var(--mono);
  font-size: 0.95rem;
  letter-spacing: 0.06em;
  word-break: break-all;
  padding: 0.75rem;
  background: var(--cream);
  border: 1px solid var(--rule);
}

.codes {
  list-style: none;
  padding: 0.9rem;
  margin: 0 0 1rem;
  background: var(--cream);
  border: 1px solid var(--rule);
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.4rem 1rem;
}

.codes li {
  font-family: var(--mono);
  font-size: 0.95rem;
  letter-spacing: 0.04em;
}

.warn {
  border-left: 3px solid var(--gold);
  background: var(--cream);
  padding: 0.75rem 0.9rem;
  font-size: 0.88rem;
  margin-bottom: 1.2rem;
}

/* --------------------------------------------------------------- shell --- */
.masthead {
  background: var(--forest);
  color: var(--cream);
  /* a gold rule: a fill, which is what gold is for */
  border-bottom: 2px solid var(--gold);
}

.masthead-inner {
  max-width: 72rem;
  margin: 0 auto;
  padding: 0.9rem 1.5rem;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
}

/* WHICH PAGE THIS IS. `.wordmark` and `.nav` were here and are gone with the
   markup that carried them: a brand the rail already shows, and a two-link nav
   beside a sidebar with the full one.

   THE SIZE IS A HEADING'S, because it is one - `<h1>`, and the pages under this
   band dropped their own in the same pass. It sits on navy with the sky rule
   under it, so it is white type on the darkest surface the application has and
   the only thing in the band. */
.page-title {
  font-family: var(--display);
  font-size: 1.5rem;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.01em;
  color: var(--white);
  margin: 0;
  margin-right: auto;
}

.whoami {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: var(--sand);
}

.logout {
  width: auto;
  margin: 0;
  padding: 0.35rem 0.7rem;
  font-size: 0.78rem;
  color: var(--sand);
  background: transparent;
  border: 1px solid var(--forest-soft);
}
.logout:hover { background: var(--forest-deep); color: var(--cream); }

main.page {
  max-width: 72rem;
  margin: 0 auto;
  padding: 2rem 1.5rem 4rem;
}

.empty {
  background: var(--paper);
  border: 1px solid var(--rule);
  padding: 3rem 2rem;
  text-align: center;
  color: var(--ink-soft);
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}


/* ------------------------------------------------------------- panels ---- */
.panel {
  background: var(--paper);
  border: 1px solid var(--rule);
  padding: 1.5rem;
  margin-bottom: 1.5rem;
}

.panel h2 { margin-top: 0; }

/* ------------------------------------------------------------- tables ---- */
.table-scroll { overflow-x: auto; }

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
  min-width: 46rem;
}

th {
  text-align: left;
  font-size: 0.68rem;
  font-family: var(--mono);
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  padding: 0.6rem 0.8rem;
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
}

td {
  padding: 0.8rem;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}

tr:last-child td { border-bottom: none; }

tr.row-off { opacity: 0.55; }

td.num { font-family: var(--mono); font-size: 0.82rem; white-space: nowrap; }

.name { display: block; font-weight: 600; }

.sub {
  display: block;
  font-size: 0.78rem;
  color: var(--ink-soft);
}

/* A CELL IS NOT A SPAN. `.sub` is a utility for quiet text inside a line, and
   `display: block` is what makes it sit on its own; on a <td> the same
   declaration takes the cell out of the table's column model altogether. The
   symptom is not subtle once you know it - the cell stops lining up with the
   column above it and the browser parks the leftover width beside it - but from
   the outside it reads as "the table has a huge gap in it", which is a layout
   problem nobody thinks to solve by looking at a text color.

   Two tables were wearing it: the facts list on the admin page and the Detail
   column of the intake log. Fixed here rather than by renaming the class in
   both templates, so the third one nobody has written yet is fixed too. */
td.sub, th.sub { display: table-cell; }

/* -------------------------------------------------------------- pills ---- */
.pill {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.15rem 0.4rem;
  margin-top: 0.3rem;
  color: var(--ink-soft);
  background: var(--cream);
  border: 1px solid var(--rule);
}

.pill-ok   { color: var(--ok);        border-color: var(--ok); }
/* gold-text, never gold: this is type on a light ground */
.pill-warn { color: var(--gold-text); border-color: var(--gold); }
.pill-off  { color: var(--error);     border-color: var(--error); }

/* -------------------------------------------------------------- forms ---- */
.row-form {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: flex-end;
}

.field { flex: 1 1 12rem; }
.field-narrow { flex: 0 0 auto; }

.field button { margin-top: 0; width: auto; }

/* A checkbox in a row of text fields. `flex: 0 0 auto` so it takes the width of
   its own words rather than a twelfth of the row, and the label carries the box
   so the words are part of the hit target - a 13px checkbox on its own is a
   target somebody misses on a laptop trackpad and every time on a phone. */
.field-check { flex: 0 0 auto; padding-bottom: 0.75rem; }
.field-check label {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0;
  font-size: 0.9rem;
  cursor: pointer;
}
.field-check input { width: auto; margin: 0; }

select {
  width: 100%;
  padding: 0.7rem 0.8rem;
  font-family: var(--sans);
  font-size: 1rem;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 0;
}

.inline-form { display: inline-flex; gap: 0.3rem; align-items: center; }
.inline-form select { width: auto; padding: 0.3rem 0.4rem; font-size: 0.82rem; }

td.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

button.mini {
  width: auto;
  margin: 0;
  padding: 0.3rem 0.6rem;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--forest);
  background: transparent;
  border: 1px solid var(--rule);
}

button.mini:hover { background: var(--cream); }

button.mini-danger { color: var(--error); border-color: var(--error); }
button.mini-danger:hover { background: var(--error-bg); }

/* ---------------------------------------------------------------- log ---- */
.log { list-style: none; padding: 0; margin: 0; }

.log li {
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--rule);
  font-size: 0.85rem;
}

.log li:last-child { border-bottom: none; }

.log .when {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--ink-soft);
  margin-right: 0.6rem;
}

.flash-ok { border-left-color: var(--ok); }


/* ====================================================================== *
 * DEVELOPMENT CHROME                                                     *
 *                                                                        *
 * Two signals: a red favicon in the tab strip and a red banner at the top *
 * of the page. Both come from configuration rather than from the request, *
 * so a production box cannot be talked into wearing them. The page ground *
 * itself stays the same as live - the banner carries the warning, and     *
 * tinting every surface behind it only made the app harder to read.       *
 * ====================================================================== */

.devbar {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1rem;
  padding: 0.45rem 1.5rem;
  background: #C0281F;
  color: #FBEEEC;
  font-family: var(--mono);
  font-size: 0.72rem;
  line-height: 1.5;
  letter-spacing: 0.04em;
  border-bottom: 2px solid #8E3320;
}

.devbar-tag {
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.devbar-text { opacity: 0.92; }

.devbar-host {
  margin-left: auto;
  opacity: 0.85;
  white-space: nowrap;
}

/* The banner is a block above the centered sign-in card, so the page needs to
   be a column that can give the remaining height to the card. Without this
   `.centered`'s min-height:100% plus the banner overflows the viewport and the
   card sits slightly off-center with a scrollbar for no reason. */
body { display: flex; flex-direction: column; min-height: 100vh; }
.centered { flex: 1 1 auto; }
main.page { width: 100%; }

/* ====================================================================== *
 * THE BOARD                                                              *
 *                                                                        *
 * A list, not columns. Fourteen columns on a laptop gives each one about  *
 * eighty pixels, which fits a number and nothing a person can read. The   *
 * stage is a label on the card instead, and the list is sorted by the     *
 * rule in stages.py: attention first, then longest waiting.               *
 *                                                                        *
 * The left stripe carries the kind. It is the only thing on the card      *
 * doing color-as-meaning, so it gets a shape too (width) rather than     *
 * relying on hue alone.                                                   *
 * ====================================================================== */

.board-head { margin-bottom: 1.2rem; }

.filters { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 1.5rem; }

.chip {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.4rem 0.8rem;
  color: var(--ink-soft);
  background: var(--paper);
  border: 1px solid var(--rule);
  text-decoration: none;
}
.chip:hover { border-color: var(--forest); color: var(--forest); }
.chip-on { color: var(--cream); background: var(--forest); border-color: var(--forest); }

/* ---------------------------------------------------------------- cards --- */
.cards { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.6rem; }

.card-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto auto;
  gap: 1.2rem;
  align-items: start;
  padding: 1rem 1.2rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-left: 4px solid var(--rule);
}

.card-item.kind-attention { border-left-color: var(--error); }
.card-item.kind-action    { border-left-color: var(--forest); }
.card-item.kind-waiting   { border-left-color: var(--gold); }
.card-item.kind-done      { border-left-color: var(--sand); }

.card-item.is-overdue { background: var(--error-bg); }

.card-open {
  width: auto;
  margin: 0;
  padding: 0;
  background: none;
  border: none;
  color: var(--forest);
  font-family: var(--display);
  font-size: 1.2rem;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
}
.card-open:hover .patient { border-bottom: 1px solid var(--gold); }

.stage-line { margin: 0.2rem 0 0; display: flex; gap: 0.5rem; align-items: baseline; }

.stage-num {
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  color: var(--gold-text);
}

.stage-label { font-size: 0.92rem; font-weight: 600; }
.stage-desc { margin: 0.15rem 0 0; font-size: 0.82rem; color: var(--ink-soft); }

/* ---------------------------------------------------------------- clock --- */
.card-clock { text-align: right; white-space: nowrap; }

.days {
  font-family: var(--mono);
  font-size: 1.6rem;
  font-weight: 500;
  line-height: 1;
  color: var(--forest);
  font-variant-numeric: tabular-nums;
}
.is-overdue .days { color: var(--error); }

.days-unit {
  display: block;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* ---------------------------------------------------------------- forms --- */
.card-forms { display: flex; gap: 0.3rem; }

.form-flag {
  display: grid;
  place-items: center;
  width: 1.7rem;
  height: 1.7rem;
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 500;
  border: 1px solid var(--rule);
}

/* A fill for received, an outline for outstanding: the difference is shape as
   well as color, so it survives a monochrome screen and color blindness. */
.form-in  { color: var(--forest); background: var(--done-tint); border-color: var(--sage); }
.form-out { color: var(--ink-faint, var(--ink-soft)); background: transparent; }

/* ----------------------------------------------------------------- meta --- */
.card-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.2rem;
  text-align: right;
  white-space: nowrap;
}

.who { font-size: 0.8rem; font-weight: 600; }
.who-none { color: var(--ink-soft); font-weight: 400; font-style: italic; }

@media (max-width: 44rem) {
  .card-item { grid-template-columns: 1fr auto; }
  .card-forms { grid-column: 1; }
  .card-meta { grid-column: 2; }
}

/* --------------------------------------------------------------- drawer --- */
/* A flyout rather than an expanding card: expanding in place costs the vertical
   space that lets somebody see the queue, and the queue is what the board is
   for. */
.drawer {
  position: fixed;
  top: 0; right: 0; bottom: 0;
  width: min(28rem, 100%);
  background: var(--paper);
  border-left: 3px solid var(--forest);
  overflow-y: auto;
  padding: 1.5rem;
  z-index: 20;
}

.scrim {
  position: fixed;
  inset: 0;
  background: rgba(40, 58, 108, 0.28);
  z-index: 10;
}

.drawer-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  border-bottom: 2px solid var(--gold);
  padding-bottom: 0.6rem;
  margin-bottom: 1rem;
}

.drawer-head h2 { margin: 0; }

.drawer-close {
  width: auto;
  margin: 0;
  padding: 0.3rem 0.7rem;
  font-size: 0.75rem;
  color: var(--forest);
  background: transparent;
  border: 1px solid var(--rule);
}

.drawer-stage { display: flex; gap: 0.5rem; align-items: baseline; margin-bottom: 0.2rem; }

.drawer-clock {
  font-family: var(--mono);
  font-size: 0.82rem;
  color: var(--ink-soft);
  margin-bottom: 1.2rem;
}
.drawer-clock.is-overdue { color: var(--error); font-weight: 600; }

.drawer-section { margin-bottom: 1.5rem; }
/* THE ONE EYEBROW IN THE APPLICATION WITHOUT THE SKY RULE, until now. Every
   other screen marks the step from a label to its content with a short sky
   rule - the client sheets, Start Here, the Pages manager, the board's own
   column headers. The drawer is the panel somebody keeps open all day beside
   the board, so being the odd one out reads as a different product rather than
   as a quiet choice. Condensed and blue to match those, rather than mono. */
.drawer-section h3 {
  font-family: var(--display);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--blue);
  margin: 0 0 0.55rem;
}

.drawer-section h3::after {
  content: "";
  display: block;
  width: 22px;
  height: 3px;
  background: var(--sky);
  margin-top: 6px;
}

/* A section lifted onto its own ground. History earns it: it is the answer to
   "what has actually happened to this patient", and as a plain list at the foot
   of the drawer it read as the least important thing rather than the record. */
.drawer-card {
  background: var(--cream-warm);
  border: 1px solid var(--sand);
  border-left: 2px solid var(--gold);
  padding: 0.9rem 1rem 1rem;
}

.drawer-card h3 { color: var(--gold-text); }

.drawer-card .drawer-list li { border-bottom-color: var(--sand); }

.drawer-list { list-style: none; padding: 0; margin: 0; }
/* The horizontal padding is for the filled rows, and the matching negative
   margin is so it costs the others nothing: a `.form-in` fill needs room
   before its label or the text sits hard against the edge of the green, while
   every row's text stays on the same line it was on. */
.drawer-list li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.65rem 0.6rem;
  margin: 0 -0.6rem;
  border-bottom: 1px solid var(--rule);
  font-size: 0.85rem;
}

/* A row here is two facts on one line - what it is, and where it stands - and
   at 0.45rem they packed tightly enough that the eye ran them together. The
   filled `.form-in` rows made it worse: a fill needs more room around its text
   than a bare line does. */
.drawer-list li:last-child { border-bottom: none; }

/* A send that failed or was blocked. Quieter than a delivered one, because the
   list is read to find what went out and these are the rows that did not. */
.drawer-list li.contact-off .form-name { color: var(--ink-mute); }

/* SEPARATION BETWEEN FORMS. Three answered rows ran together into one block of
   green: the fill is what says "received", and with the rows touching, three
   receipts read as one panel rather than three facts. A gap breaks it back into
   rows, so the border between them is space rather than a hairline that the
   fill swallows anyway. */
.drawer-list.forms-list {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.drawer-list.forms-list li { border-bottom: 0; }

.form-right { display: flex; align-items: center; gap: 0.5rem; flex: none; }

/* Sits on the fill of an answered row. It carried gold-light text for the
   forest ground it used to sit on, which is nearly invisible on the light one
   that replaced it. */
.form-view {
  width: auto;
  margin-top: 0;
  padding: 0.2rem 0.55rem;
  border: 1px solid var(--gold);
  background: transparent;
  color: var(--gold-text);
  font-family: var(--sans);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
}

.form-view:hover { background: var(--gold); color: var(--forest); }

/* ------------------------------------------------ the answers panel --- */
.pv-loading, .pv-empty {
  margin: 0;
  font-family: var(--sans);
  font-size: 0.85rem;
  color: var(--ink-mute);
}

.answer-list {
  display: flex;
  flex-direction: column;
  margin-bottom: 1.3rem;
  border: 1px solid var(--sand);
}

.answer-row {
  display: grid;
  grid-template-columns: 12rem minmax(0, 1fr);
  gap: 1rem;
  padding: 0.6rem 0.8rem;
  border-bottom: 1px solid var(--sand);
}

.answer-row:last-child { border-bottom: 0; }
.answer-row:nth-child(even) { background: var(--cream); }

.answer-key {
  font-family: var(--sans);
  font-size: 0.78rem;
  color: var(--ink-mute);
}

.answer-value {
  font-size: 0.88rem;
  color: var(--ink);
  word-break: break-word;
}

@media (max-width: 560px) {
  .answer-row { grid-template-columns: 1fr; gap: 0.15rem; }
}
.drawer-list .fine { margin: 0; white-space: nowrap; }
.drawer-list .note-body { white-space: pre-wrap; }

.drawer-list li.form-in  .form-name { font-weight: 600; }
.drawer-list li.form-out .form-name { color: var(--ink-soft); }

/* `.fine` CARRIES ITS OWN COLOR. On the forest fill this row used to have,
   it put --ink-soft on dark green and the date vanished into it; on the light
   fill that replaced it the opposite rule applies, so it comes back to a dark
   value.
   --gold-text measures 4.62:1 on `--done-tint` and clears AA. --ink-mute is
   the obvious choice for a muted line and reaches only 3.86:1, so it is
   deliberately not used. */
.drawer-list li.form-in .fine { color: var(--gold-text); }

/* Quiet: it is a way to see more, not a thing to do. */
.note-more {
  width: auto;
  margin: 0.5rem 0 0;
  padding: 0.25rem 0.6rem;
  border: 1px solid var(--sand);
  background: transparent;
  color: var(--gold-text);
  font-family: var(--sans);
  font-size: 0.72rem;
  cursor: pointer;
}

.note-more:hover { border-color: var(--gold); background: var(--cream); }

.note-form { display: flex; gap: 0.4rem; margin-bottom: 0.8rem; }
.note-form textarea {
  flex: 1;
  padding: 0.5rem;
  font-family: var(--sans);
  font-size: 0.88rem;
  border: 1px solid var(--rule);
  border-radius: 8px;  /* 8px: section 3. Was 0, and beat shape.css on specificity. */
  resize: vertical;
}
.note-form button { margin: 0; align-self: flex-end; }

body.drawer-open { overflow: hidden; }

/* ---------------------------------------------------------- stage groups --- */
/* Every stage renders, including the empty ones. A stage that appears only when
   it holds somebody is a stage nobody remembers exists, and the shape of the
   pipeline stops being readable at a glance - which is half of what a board is
   for. "0 patients" is information. */

.stage-group { margin-bottom: 1.6rem; }

.stage-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.2rem 1rem;
  align-items: baseline;
  padding-bottom: 0.4rem;
  border-bottom: 2px solid var(--forest);
  margin-bottom: 0.6rem;
}

.stage-key {
  grid-row: 1;
  font-family: var(--mono);
  font-size: 0.66rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-text);
}

.stage-head h2 {
  grid-row: 2;
  grid-column: 1;
  margin: 0;
  font-size: 1.2rem;
}

.stage-blurb {
  grid-row: 3;
  grid-column: 1;
  margin: 0;
  font-size: 0.82rem;
  color: var(--ink-soft);
}

.stage-count {
  grid-row: 2;
  grid-column: 2;
  font-family: var(--mono);
  font-size: 0.76rem;
  color: var(--ink-soft);
  white-space: nowrap;
}

/* An empty stage is quieter but never invisible. */
.stage-empty .stage-head { border-bottom-color: var(--rule); }
.stage-empty .stage-head h2 { color: var(--ink-soft); font-weight: 400; }

.stage-none {
  margin: 0;
  padding: 0.5rem 0 0.7rem;
  font-family: var(--mono);
  font-size: 0.76rem;
  letter-spacing: 0.06em;
  color: var(--ink-faint, var(--ink-soft));
}

/* Off the fourteen. Sales owned, or a stage we could not place. */
.stage-parked .stage-head { border-bottom-color: var(--gold); }

/* ====================================================================== *
 * THE BOARD, AS COLUMNS                                                  *
 *                                                                        *
 * Fourteen stages side by side on a horizontal rail, mirroring the board  *
 * this replaces. An earlier version stacked them vertically on the        *
 * reasoning that fourteen columns on a laptop gives each one eighty       *
 * pixels; the answer is not fewer columns, it is a rail that scrolls and  *
 * columns wide enough to read. The shape of the pipeline is the thing a   *
 * concierge reads first, and stacking destroyed it.                       *
 * ====================================================================== */

.board-masthead { border-bottom: 2px solid var(--gold); }

.masthead-sub {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sand);
}

.masthead-ver {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  color: var(--forest-soft);
  margin-right: auto;
}

.masthead-right {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
}

.masthead-pipeline,
.masthead-updated {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.06em;
  color: var(--sand);
}

.topbtn {
  font-family: var(--mono);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.3rem 0.7rem;
  color: var(--cream);
  border: 1px solid var(--forest-soft);
  text-decoration: none;
}
.topbtn:hover { background: var(--forest-deep); }

/* ------------------------------------------------------------- subnav --- */
.subnav {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  flex-wrap: wrap;
  max-width: 100%;
  padding: 0.5rem 1.5rem;
  background: var(--forest-deep);
}

.subnav-key {
  font-family: var(--mono);
  font-size: 0.6rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-on-dark);
}
.subnav-key-manage { margin-left: 0.8rem; }

.subnav a {
  font-size: 0.76rem;
  color: var(--sand);
  text-decoration: none;
  padding: 0.2rem 0.5rem;
  border: 1px solid transparent;
}
.subnav a:hover { color: var(--cream); border-color: var(--forest-soft); }

.subnav-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.7rem;
}

/* ------------------------------------------------------------- tabs ----- */
.viewtabs {
  display: flex;
  gap: 1.4rem;
  padding: 0.7rem 1.5rem 0;
  border-bottom: 1px solid var(--rule);
}

.viewtabs a {
  font-family: var(--mono);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  text-decoration: none;
  padding-bottom: 0.5rem;
  border-bottom: 2px solid transparent;
}
.viewtabs a.on { color: var(--forest); border-bottom-color: var(--forest); }

/* ------------------------------------------------------------ notice ---- */
.notice {
  margin: 0;
  padding: 0.6rem 1.5rem;
  background: var(--cream);
  border-bottom: 1px solid var(--rule);
  border-left: 3px solid var(--gold);
  font-size: 0.82rem;
  color: var(--ink-soft);
}

/* -------------------------------------------------------------- rail ---- */
.rail {
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  overflow-x: auto;
  padding: 1rem 1.5rem 2rem;
}

.col {
  flex: 0 0 15rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  min-height: 22rem;
  display: flex;
  flex-direction: column;
}

.col-empty { background: transparent; }

.col-head {
  padding: 0.8rem 0.9rem 0.7rem;
  border-bottom: 1px solid var(--rule);
}

.col-key {
  font-family: var(--mono);
  font-size: 0.6rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-text);
}

.col-head h2 {
  margin: 0.15rem 0 0.2rem;
  font-size: 1rem;
  line-height: 1.2;
}
.col-empty .col-head h2 { color: var(--ink-soft); font-weight: 400; }

.col-blurb {
  margin: 0 0 0.5rem;
  font-size: 0.72rem;
  line-height: 1.45;
  color: var(--ink-soft);
}

.col-count {
  margin: 0;
  font-family: var(--mono);
  font-size: 0.66rem;
  color: var(--ink-soft);
}

.col-body { padding: 0.6rem; display: grid; gap: 0.5rem; }

.col-none {
  margin: 0;
  padding: 0.4rem 0.3rem;
  font-size: 0.78rem;
  font-style: italic;
  color: var(--ink-faint, var(--ink-soft));
}

.col-parked { border-color: var(--gold); }

/* ----------------------------------------------------------- the card --- */
.pcard {
  display: grid;
  gap: 0.35rem;
  width: 100%;
  margin: 0;
  padding: 0.6rem 0.7rem;
  text-align: left;
  background: var(--cream);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--rule);
  cursor: pointer;
  font-family: var(--sans);
}

.pcard:hover { border-color: var(--forest); }

.pcard.kind-attention { border-left-color: var(--error); }
.pcard.kind-action    { border-left-color: var(--forest); }
.pcard.kind-waiting   { border-left-color: var(--gold); }
.pcard.kind-done      { border-left-color: var(--sand); }
.pcard.is-overdue     { background: var(--error-bg); }

.pcard-top { display: flex; align-items: baseline; gap: 0.4rem; }

.pcard-name {
  flex: 1;
  font-weight: 600;
  font-size: 0.88rem;
  color: var(--forest);
}

.pcard-age {
  font-family: var(--mono);
  font-size: 0.7rem;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
}
.is-overdue .pcard-age { color: var(--error); font-weight: 600; }

.pcard-chev { color: var(--ink-faint, var(--ink-soft)); font-size: 0.9rem; }

.pcard-sub { display: flex; align-items: center; gap: 0.4rem; }

.substate {
  font-family: var(--mono);
  font-size: 0.6rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  padding: 0.1rem 0.32rem;
  color: var(--cream);
  background: var(--forest);
}
.kind-attention .substate { background: var(--error); }
.kind-waiting .substate   { background: var(--gold-text); }
.kind-done .substate      { background: var(--ok); }

.substate-text { font-size: 0.72rem; color: var(--ink-soft); }

.pcard-forms { display: flex; align-items: center; gap: 0.22rem; }

.pcard-forms .form-flag {
  width: 1.15rem;
  height: 1.15rem;
  font-size: 0.58rem;
}

.pcard-who {
  margin-left: auto;
  font-size: 0.68rem;
  color: var(--ink-soft);
}

/* ------------------------------------------------------- performance ----- */
/* Rendered on every page and collapsed by default. A monitor you have to switch
   on is a monitor nobody has running when the slow thing happens. */

.perf {
  position: fixed;
  right: 0;
  bottom: 0;
  z-index: 30;
  max-width: min(30rem, 100%);
  font-family: var(--mono);
  font-size: 0.68rem;
  background: var(--white);
  border: 1px solid var(--hair);
  border-right: none;
  border-bottom: none;
  color: var(--ink-soft);
}

.perf summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.8rem;
  cursor: pointer;
  list-style: none;
  white-space: nowrap;
}
.perf summary::-webkit-details-marker { display: none; }
.perf[open] summary { border-bottom: 1px solid var(--hair); }

.perf-dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--ink-mute);
  flex: none;
}
.perf-good { background: var(--forest); }
.perf-fair { background: var(--watch); }
.perf-poor { background: var(--fail); }

.perf-sum { letter-spacing: 0.04em; }
.perf-browser { color: var(--ink-mute); }

.perf-body { padding: 0.6rem 0.8rem 0.8rem; }

.perf-grid {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.2rem 0.9rem;
  margin: 0;
}
.perf-grid dt { color: var(--ink-mute); }
.perf-grid dd { margin: 0; text-align: right; }
.perf-grid b { color: var(--ink); font-weight: 500; }

.perf-note {
  margin: 0.6rem 0 0;
  padding-top: 0.5rem;
  border-top: 1px solid var(--hair);
  font-family: var(--sans);
  font-size: 0.72rem;
  line-height: 1.5;
  color: var(--ink-mute);
  white-space: normal;
}

/* ====================================================================== *
 * THIN BAR AND PROFILE MENU                                              *
 *                                                                        *
 * Role on the left of the cluster, person on the right. No cart, and no  *
 * notification bell: a bell with nothing behind it teaches people to     *
 * ignore bells, and the one thing this application has to say - a card   *
 * needing attention - it says on the card, where the work is.            *
 * ====================================================================== */

.topbar {
  background: var(--cream-warm);
  border-bottom: 1px solid var(--hair);
}

.topbar-inner {
  max-width: 100%;
  padding: 0.3rem 1.1rem;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.7rem;
}

.rolepill {
  font-family: var(--mono);
  font-size: 0.6rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 0.18rem 0.6rem;
  border: 1px solid var(--gold);
  color: var(--gold-text);
  background: transparent;
}

/* A member is not a lesser admin, so it is a different color rather than a
   faded one. */
.rolepill-member { border-color: var(--sage); color: var(--sage); }

/* ------------------------------------------------------------- avatar --- */
.avatar {
  display: grid;
  place-items: center;
  width: 1.9rem;
  height: 1.9rem;
  margin: 0;
  padding: 0;
  border-radius: 50%;
  border: none;
  background: var(--gold);
  color: var(--forest-deep);
  font-family: var(--sans);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  cursor: pointer;
  flex: none;
}

.avatar:hover { background: var(--gold-deep); color: var(--cream); }

.avatar-lg {
  width: 2.6rem;
  height: 2.6rem;
  font-size: 0.9rem;
  cursor: default;
  margin-bottom: 0.4rem;
}
.avatar-lg:hover { background: var(--gold); color: var(--forest-deep); }

/* --------------------------------------------------------------- menu --- */
.profile { position: relative; }

.profile-menu {
  position: absolute;
  top: calc(100% + 0.45rem);
  right: 0;
  z-index: 40;
  min-width: 15rem;
  background: var(--white);
  border: 1px solid var(--hair);
  box-shadow: 0 2px 14px rgba(40, 58, 108, 0.10);
}

.profile-head {
  display: flex;
  flex-direction: column;
  padding: 0.9rem 1rem 0.8rem;
}

.profile-name {
  font-family: var(--sans);
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--ink);
}

/* Smaller and regular, so the name reads first and the address is the
   confirmation rather than competing with it. */
.profile-email {
  font-family: var(--sans);
  font-size: 0.78rem;
  font-weight: 400;
  color: var(--ink-mute);
  word-break: break-all;
}

.profile-sep { height: 1px; background: var(--hair); }

.profile-item {
  display: block;
  width: 100%;
  margin: 0;
  padding: 0.62rem 1rem;
  font-family: var(--sans);
  font-size: 0.85rem;
  font-weight: 400;
  text-align: left;
  color: var(--ink);
  background: transparent;
  border: none;
  text-decoration: none;
  cursor: pointer;
}

.profile-item:hover { background: var(--cream); color: var(--forest); }
.profile-item-button { border-radius: 0; }

/* ====================================================================== *
 * ADMIN SETTINGS                                                         *
 * ====================================================================== */

.admin-page { max-width: 60rem; }

.admin-title { margin-bottom: 1.4rem; }
.admin-title span {
  font-family: var(--sans);
  font-size: 0.95rem;
  font-weight: 400;
  color: var(--ink-mute);
  margin-left: 0.4rem;
}

.admin-label {
  font-family: var(--mono);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin: 1.6rem 0 0.6rem;
}

.admin-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
  gap: 0.7rem;
}

.admin-card {
  display: block;
  padding: 0.9rem 1rem 1rem;
  background: var(--white);
  border: 1px solid var(--hair);
  border-left: 3px solid var(--forest);
  text-decoration: none;
  color: var(--ink);
}

.admin-card:hover { border-color: var(--forest); border-left-color: var(--gold); }

/* A tile that opens a placeholder is marked on its face. Looking like a
   feature and not being one costs a click and some trust. */
.admin-card-pending { border-left-color: var(--sand-deep); background: var(--cream-warm); }

.admin-card-head { display: flex; align-items: baseline; gap: 0.35rem; }

.admin-card-name {
  font-family: var(--serif);
  font-size: 1.15rem;
  font-weight: 500;
  color: var(--forest);
}

.admin-card-count {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--ink-mute);
  font-variant-numeric: tabular-nums;
}

.admin-card-desc {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

.admin-card-flag {
  display: inline-block;
  margin-top: 0.5rem;
  font-family: var(--mono);
  font-size: 0.58rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gold-text);
}

/* ====================================================================== *
 * THE NAVBAR                                                             *
 *                                                                        *
 * One green bar: brand, navigation, identity. The pages and forms that    *
 * used to sit in a second row live behind one link now - eleven links     *
 * across the top of a working screen is a menu pretending to be           *
 * navigation, and it costs the vertical space the board needs.            *
 * ====================================================================== */

.navbar {
  background: var(--forest);
  border-bottom: 2px solid var(--gold);
}

.navbar-inner {
  display: flex;
  align-items: center;
  gap: 1.2rem;
  padding: 0.45rem 1.2rem;
  flex-wrap: wrap;
}

.navbrand {
  font-family: var(--serif);
  font-size: 1.3rem;
  font-weight: 400;
  letter-spacing: 0.5px;
  color: var(--cream);
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 0.45rem;
  flex: none;
}

.navbrand-sub {
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 2.6px;
  text-transform: uppercase;
  color: var(--gold-light);
}

.navlinks {
  display: flex;
  align-items: center;
  gap: 0.15rem;
  flex-wrap: wrap;
  margin-right: auto;
}

.navlinks a {
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--sand);
  text-decoration: none;
  /* Pinned rather than inherited. The start page loads the welcome sheet, whose
     body line-height differs from ours, which made the bar 0.6px taller there
     than on every other page. Nobody would see it, but a navbar whose height
     depends on which page is under it is a thing that gets worse. */
  line-height: 1.6;
  padding: 0.42rem 0.7rem;
  white-space: nowrap;
}

.navlinks a:hover { color: var(--cream); }

/* The current page is simply the heavier, brighter word. No rule under it and
   no fill behind it: a filled box in a row of plain words reads as something
   you press, and this is a label saying where you already are. */
.navlinks a.on {
  color: var(--cream);
  font-weight: 700;
}

/* Refresh is an action, not a place. Set apart so it does not read as a
   seventh destination. */
/* Selector carries `.navlinks a` on purpose. `.navlink-action` alone is one
   class and loses to `.navlinks a`, which is a class AND a type - so a bare
   .navlink-action padding rule is silently discarded. That is what the pair of
   !important flags here used to be papering over; matching the specificity
   says the same thing without them. */
.navlinks a.navlink-action {
  margin-left: 0.5rem;
  border: 1px solid var(--forest-soft);
  /* Less 1px a side, so the outlined box finishes the same height as the
     filled one rather than standing 2px prouder than every other link. */
  padding: calc(0.42rem - 1px) calc(0.7rem - 1px);
}
.navlinks a.navlink-action:hover { background: var(--forest-deep); }

.navright { display: flex; align-items: center; gap: 0.7rem; flex: none; }

/* On the green ground the role pill needs its own treatment: the light-ground
   gold-text would disappear here. */
.navright .rolepill { border-color: var(--gold); color: var(--gold-on-dark); }
.navright .rolepill-member { border-color: var(--sage); color: var(--sand); }

@media (max-width: 60rem) {
  .navbrand-sub { display: none; }
  .navlinks a { padding: 0.3rem 0.45rem; font-size: 0.75rem; }
}

/* --------------------------------------------------------- board meta --- */
.boardmeta {
  display: flex;
  gap: 1rem;
  padding: 0.5rem 1.5rem 0;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.06em;
  color: var(--ink-mute);
}

/* ------------------------------------------------------- start screen --- */
.page.narrow { max-width: 44rem; }

.stat-row {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin: 1.2rem 0 1.8rem;
}

.stat {
  flex: 1 1 8rem;
  padding: 0.8rem 1rem;
  background: var(--white);
  border: 1px solid var(--hair);
  border-left: 3px solid var(--forest);
}

.stat-n {
  display: block;
  font-family: var(--mono);
  font-size: 1.5rem;
  font-weight: 500;
  color: var(--forest);
  font-variant-numeric: tabular-nums;
}

.stat-l {
  display: block;
  font-size: 0.72rem;
  color: var(--ink-mute);
  margin-top: 0.15rem;
}

.ticks { list-style: none; padding: 0; margin: 0 0 1.2rem; }

.ticks li {
  position: relative;
  padding: 0.3rem 0 0.3rem 1.4rem;
  font-size: 0.9rem;
  line-height: 1.55;
}

.ticks li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.85rem;
  width: 0.6rem;
  height: 1px;
  background: var(--forest);
}

/* Open items get the gold rule rather than the forest one: a different state,
   marked by a different color, not by a fainter version of the same. */
.ticks-open li::before { background: var(--gold); }

.mono { font-family: var(--mono); font-size: 0.92em; }

/* ------------------------------------------------- navbar, second pass --- */
/* Three tracks: brand, links, identity. The middle one is centered against the
   VIEWPORT rather than against the space left over, which is what a plain flex
   row gives you - and which drifts left or right as the brand or the identity
   cluster changes width. */
.navbar-inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1rem;
}

.navbrand { justify-self: start; gap: 0.55rem; }

/* The mandala is 70px square; the bar shows it at 26. Both dimensions are on
   the <img> so the row does not reflow while it loads. */
.navmark { width: 1.9rem; height: 1.9rem; display: block; flex: none; }

.navwordmark { display: flex; align-items: baseline; gap: 0.45rem; }

.navlinks { justify-self: center; margin-right: 0; }

.navright { justify-self: end; }

/* --------------------------------------------------------- navbar meta --- */
.navmeta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.25;
  font-family: var(--mono);
  font-size: 0.58rem;
  letter-spacing: 0.06em;
  white-space: nowrap;
}

.navmeta-pipe {
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--sand);
}
/* `--forest-soft` is #1B5A3E, and this sits on #0A412A. Barely more than a
   shade apart, so "Updated 00:15" was effectively invisible on the green bar.
   The same cream the nav links use, dimmed - quiet without being unreadable. */
.navmeta-when { color: rgba(255, 255, 255, 0.62); }

/* Below this the three tracks stop fitting; the links wrap to their own row and
   stay centered rather than being squeezed into an unreadable strip. */
@media (max-width: 78rem) {
  .navbar-inner { grid-template-columns: auto 1fr; }
  .navlinks { grid-column: 1 / -1; grid-row: 2; justify-self: center; }
  .navright { grid-row: 1; }
}

@media (max-width: 40rem) {
  .navmeta { display: none; }
}

/* ======================================================================= *
 *  THE PATIENT DRAWER                                                     *
 *                                                                         *
 *  Slides in over the board rather than expanding a card in place. An      *
 *  expanding card costs the vertical space that lets somebody see the      *
 *  queue, and the queue is what the board is for.                          *
 * ======================================================================= */

.fly-sub {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.4rem;
}

.fly-stage {
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: 0.08em;
  padding: 1px 5px;
  color: var(--cream);
  border: 1px solid rgba(255, 255, 255, 0.4);
}

.fly-stage-label { font-size: 0.8rem; color: var(--cream); }
.fly-clock { font-size: 0.75rem; color: var(--sand); }
.fly-clock.is-overdue { color: var(--gold-light); font-weight: 600; }

/* -------------------------------------------------------- the rows --- */
/* A two-column reading table, not a form. Label left in small caps, value
   right in the reading face, one hairline between each. */
.fly-contact { margin-bottom: 1.4rem; }

/* The edit sits under the details it edits, aligned with their values rather
   than with the labels: it belongs to the column it changes. */
.fly-contact .fly-chip { margin-top: 0.6rem; }

.fly-row {
  display: grid;
  grid-template-columns: 7.5rem minmax(0, 1fr);
  gap: 0.6rem;
  align-items: baseline;
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--hair);
}

.fly-key {
  font-family: var(--sans);
  font-size: 0.72rem;
  color: var(--ink-mute);
  line-height: 1.4;
}

.fly-value { font-size: 0.85rem; color: var(--ink); word-break: break-word; }

/* NO RESTING UNDERLINE. The row already carries a divider, so a border on the
   value as well drew a second line a few pixels above the first and the block
   read as ruled paper. The border stays in the box as `transparent` rather than
   being dropped: hover and keyboard focus turn it gold without the row
   changing height, so the affordance survives without the clutter. */
.fly-link {
  font-size: 0.85rem;
  color: var(--forest);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  word-break: break-word;
}

.fly-link:hover,
.fly-link:focus-visible { border-bottom-color: var(--gold); }

.fly-panel { margin-bottom: 1.4rem; }

.fly-panel-title {
  margin: 0 0 0.2rem;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--gold);
  font-family: var(--sans);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-text);
}

/* ------------------------------------------------------- send block --- */
.fly-sublabel {
  margin: 0.8rem 0 0.4rem;
  font-family: var(--sans);
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

.fly-chips { display: flex; flex-wrap: wrap; gap: 0.4rem; }

/* `width: auto` because `button` is width:100% globally. A chip that fills its
   container is not a chip - it reads as the section's primary action, which is
   the opposite of what a chip is for. The mail rows already made this override
   locally; it belongs on the chip itself. */
.fly-chip {
  width: auto;
  margin-top: 0;
  padding: 0.35rem 0.7rem;
  border: 1px solid var(--sand);
  background: var(--white);
  color: var(--forest);
  font-size: 0.78rem;
  text-decoration: none;
  white-space: nowrap;
}

.fly-chip:hover { border-color: var(--gold); background: var(--cream); }

/* One row per template: what it is on the left, preview and send on the right.
   Every patient email is listed, so the row has to carry enough for somebody to
   tell at a glance whether this is the one - the stage it belongs to, what that
   stage is for, and whether it has already gone. */
.mail-intro {
  margin: 0 0 0.7rem;
  font-family: var(--sans);
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--ink-mute);
}

.mail-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.8rem;
  flex-wrap: wrap;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--sand);
}

.mail-row:last-of-type { border-bottom: 0; }

/* The rows for the stage this card is on. A left rule rather than a fill:
   the recommendation should read as emphasis, not as a warning. */
.mail-row-now {
  border-left: 2px solid var(--gold);
  padding-left: 0.7rem;
  margin-left: -0.7rem;
}

.mail-main { flex: 1 1 11rem; min-width: 0; }

.mail-head { display: flex; align-items: baseline; gap: 0.45rem; flex-wrap: wrap; }

/* Tabular so the numbers form a column the eye can run down. */
.mail-stage {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.72rem;
  color: var(--ink-mute);
}

.mail-title {
  font-family: var(--sans);
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--forest);
}

.mail-now {
  font-family: var(--sans);
  font-size: 0.58rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--forest);
  background: var(--gold-light);
  padding: 0.1rem 0.35rem;
}

.mail-desc {
  margin: 0.2rem 0 0;
  font-family: var(--sans);
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

.mail-flags {
  margin: 0.25rem 0 0;
  font-family: var(--sans);
  font-size: 0.72rem;
  line-height: 1.45;
}

/* Back in the left column, under the description it belongs to. `nowrap` is
   gone with it: the line now carries a timestamp and a relative time, which is
   longer than the column at a phone width and should wrap rather than push the
   row sideways. */
.mail-sent {
  margin: 0.25rem 0 0;
  font-family: var(--sans);
  font-size: 0.72rem;
  line-height: 1.45;
}

.mail-flags { color: var(--ink-mute); }
.mail-sent { color: var(--gold-text); font-weight: 600; }

.mail-fail {
  flex: 1 0 100%;
  margin: 0.35rem 0 0;
  font-family: var(--sans);
  font-size: 0.75rem;
  color: var(--forest);
}

/* Already sent at least once: still pressable, but it should not look like the
   next thing to do. */
.mail-acts .mini-done {
  background: var(--white);
  color: var(--forest);
  border: 1px solid var(--sand);
}

/* The right-hand column: when it last went, and the two controls, both ranged
   right so the buttons of every row line up as one column down the panel. */
.mail-side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.35rem;
  flex: none;
  text-align: right;
  /* `margin-left: auto` IS WHAT RANGES IT RIGHT, and it has to be a margin
     rather than `justify-content` on the row. The drawer is 328px and this
     column is 195px, so it wraps onto a line of its own - where a rule on the
     row does nothing, because the wrapped line has one item on it. An auto
     margin absorbs that line's free space, so it ends up right whether it
     shares a line with the description or sits under it. */
  margin-left: auto;
}

.mail-acts { display: flex; align-items: center; gap: 0.4rem; flex: none; }

/* SEND AND SEND AGAIN ARE THE SAME WIDTH. Sized to the longer of the two, so a
   row that has been sent does not shunt its Preview a centimeter left of every
   other row's. Preview matches them, so the pair is one shape at every row. */
.mail-acts .mini,
.mail-acts .fly-chip {
  min-width: 5.9rem;
  text-align: center;
}

/* Preview is a <button> now that it opens a panel rather than a tab, so it
   needs the same escape from the global button width as the Close above. */
.mail-acts .fly-chip {
  width: auto;
  margin-top: 0;
  cursor: pointer;
}

/* Disabled reads as "already done" or "not ready", not as broken. */
.mail-acts .mini:disabled {
  opacity: 0.55;
  cursor: default;
}

/* ------------------------------------------------ the email preview --- */
/* Sits above the drawer rather than replacing it, so closing the preview puts
   you back on the card you were reading with nothing to find again. */
.pv-back {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3vh 16px;
  background: rgba(40, 58, 108, 0.42);
}

.pv {
  width: min(660px, 100%);
  max-height: 94vh;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  border: 1px solid var(--sand);
}

/* WIDER, FOR THE PANELS THAT ARE WORK RATHER THAN READING. The email preview
   is a page being read and 660px is a comfortable measure for it. The schedule
   manager and the full email list are a table and a queue: a date, a time, a
   kind and a title is one line here and a stack of four at the drawer's width,
   which is most of why those editors were painful in the drawer. */
.pv-wide { width: min(820px, 100%); }

.pv-head {
  flex: none;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 1.2rem;
  border-bottom: 1px solid var(--sand);
}

.pv-who {
  font-family: var(--sans);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-text);
}

.pv-what {
  font-family: var(--serif);
  font-size: 1.35rem;
  line-height: 1.2;
  color: var(--forest);
  margin-top: 0.15rem;
}

/* `button` is width:100% with a top margin globally, which would stretch this
   across the header and shove the titles into a two-line wrap. Same override
   `.field button` and `.note-form button` already make. */
.pv-close {
  flex: none;
  width: auto;
  margin-top: 0;
  padding: 0.3rem 0.8rem;
  border: 1px solid var(--sand);
  background: var(--white);
  color: var(--forest);
  font-family: var(--sans);
  font-size: 0.75rem;
  cursor: pointer;
}

.pv-close:hover { border-color: var(--gold); background: var(--cream); }

.pv-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 1.1rem 1.2rem 1.4rem;
}

.pv-label {
  font-family: var(--sans);
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-bottom: 0.35rem;
}

.pv-subject {
  font-family: var(--serif);
  font-size: 1.1rem;
  color: var(--ink);
  margin-bottom: 1.2rem;
}

/* The frame carries the email's own cream, so the border is the only edge it
   needs. Tall enough to show the ask without scrolling inside a scroll. */
.pv-frame {
  display: block;
  width: 100%;
  height: 620px;
  border: 1px solid var(--sand);
  background: var(--cream);
}

.pv-foot {
  flex: none;
  padding: 0.75rem 1.2rem;
  border-top: 1px solid var(--sand);
  background: var(--cream);
  font-family: var(--sans);
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--ink-mute);
}

/* ---------------------------------------------------------- footer --- */
/* Pinned, so the way out to the CRM does not depend on scrolling to the end
   of a long trip. */
.fly-foot {
  flex: none;
  padding: 0.9rem 1.2rem;
  border-top: 1px solid var(--rule);
  background: var(--paper);
}

.fly-ghl {
  display: block;
  padding: 0.75rem 1rem;
  background: var(--forest);
  color: var(--cream);
  font-family: var(--sans);
  font-size: 0.8rem;
  text-align: center;
  text-decoration: none;
}

.fly-ghl:hover { background: var(--forest-deep); }
.fly-ghl[hidden] { display: none; }

/* ------------------------------------------------------- sample mode --- */
/* The same reasoning as the development bar: a state you can be in without
   noticing needs to be impossible to miss. This one is gold rather than red,
   because sample data is not an error - it is a demo, and the bar is there so
   nobody mistakes it for the real board. */
.samplebar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.7rem;
  padding: 0.5rem 1.2rem;
  background: var(--watch-tint);
  border-bottom: 1px solid var(--watch);
  font-size: 0.78rem;
  color: var(--watch);
}

.samplebar-tag {
  font-family: var(--mono);
  font-size: 0.6rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 0.15rem 0.45rem;
  background: var(--watch);
  color: var(--cream);
}

.samplebar-out { margin-left: auto; color: var(--watch); }

.tab-sample { color: var(--watch); }

.fly-muted { color: var(--ink-mute); }

/* WhatsApp CARRIED A SAGE RULE so it was findable without a logo we would have
   to ship and license. That reasoning held while every value was underlined and
   this one was a different color; with the resting underlines gone it was the
   only line left in the block and read as a mistake rather than a marker. The
   row is labeled "WhatsApp", which is what actually tells them apart - the two
   rows otherwise show the same digits. */
.fly-wa:hover,
.fly-wa:focus-visible { border-bottom-color: var(--gold); }


/* ====================================================================== *
 * BANDED SECTIONS - THE PATIENT-FACING SHEETS                            *
 *                                                                        *
 * Every page a patient is sent is one long sheet of stacked sections, and *
 * on a phone they arrived as one undifferentiated column: five blocks of  *
 * white on welcome, four of cream at the foot of the Center. Where one    *
 * ended and the next began was carried entirely by the eyebrow-and-title  *
 * rhythm, which only works if you are reading rather than scanning.       *
 *                                                                        *
 * So the sections alternate tone: white paper, warm cream, white paper.   *
 * Two tones and a sand hairline at every join, which survives a dim       *
 * screen at arm's length where the tint alone does not.                   *
 *                                                                        *
 * Here rather than in the per-page files because all four sheets load     *
 * app.css and all four had the same problem. The classes are applied in   *
 * the templates - on the Center by a Jinja counter, since its sections    *
 * are conditional and hard-coding the parity would put two creams side by *
 * side the moment a patient finished their forms.                         *
 *                                                                        *
 * THE FULL-BLEED FOREST BLOCKS (.hero, .reassure, .questions) AND THE     *
 * FOOTER ARE NOT BANDS. They already break the column, so counting them   *
 * into the alternation would only make the two tones land at random.      *
 * ====================================================================== */

/* The page sections close with zero bottom padding - they lean on the next
   block's top padding for the gap. That is invisible until a section carries a
   background, at which point the tint stops at the last line of text. One rule
   here rather than a padding fix per block, so a section added later cannot
   reintroduce it. */
.sheet .band { padding-bottom: 44px; }

.sheet .band-tint { background: var(--cream-warm); }
.sheet .band-plain { background: var(--white); }

/* THE CARDS INSIDE A TINTED BAND FLIP TO PAPER. Every sheet fills its cards -
   the numbered to-dos, the reading list, the timeline, the do-and-don't
   columns - with the same warm cream the tinted band now uses, so on those
   sections the card and its ground became one color and only the sand border
   was left holding them apart.

   Done by moving the token rather than by naming each card, because the cards
   are page-specific classes across four stylesheets and a new one would have
   been missed. Scoped to the children so the band's own fill, which reads the
   token first, keeps the tint. */
.sheet .band-tint > * { --cream-warm: var(--white); }

/* Hairline only where two bands actually meet, so the first band under the
   masthead and the first after a forest block stay clean. */
.sheet .band + .band { border-top: 1px solid var(--sand); }

@media (max-width: 760px) {
  .sheet .band { padding-bottom: 32px; }
}

@media print {
  /* The tint is the only thing distinguishing the sections on paper too, and
     a printer that drops backgrounds would collapse them all to white. */
  .sheet .band { break-inside: avoid; }
}


/* ====================================================================== *
 * THE WEBHOOK ADDRESS                                                    *
 *                                                                        *
 * On the Intake page, and it is not decoration: this line is copied by    *
 * hand into a GoHighLevel field, and a character lost on the way is a     *
 * paid patient who silently never arrives. So the URL gets its own row    *
 * rather than sitting inside a sentence - it is a value to be taken, not  *
 * prose to be read - and the button beside it is how it should be taken.  *
 * ====================================================================== */

.hookline {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
  margin: 0.8rem 0 1rem;
  padding: 0.6rem 0.75rem;
  background: var(--cream);
  border: 1px solid var(--sand);
  /* The gold edge the rest of the application uses to mean "this is the thing
     on the panel", stood on its left side. */
  border-left: 3px solid var(--gold);
}

.hookline-verb {
  font-family: var(--mono);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  color: var(--cream);
  background: var(--forest);
  padding: 0.15rem 0.4rem;
  flex: 0 0 auto;
}

/* WRAPS AT THE SLASHES RATHER THAN OVERFLOWING. A URL is one unbroken token to
   a text layout engine, so on a narrow panel it either pushes the button off
   the row or scrolls out of sight - and a URL you cannot see all of is one you
   cannot check before you paste it. */
.hookline-url {
  font-family: var(--mono);
  font-size: 0.8rem;
  color: var(--ink);
  flex: 1 1 20ch;
  min-width: 0;
  overflow-wrap: anywhere;
  /* Selectable as a unit for anybody who copies by hand out of habit. */
  user-select: all;
}

/* BOTH HALVES OF THE SIGN-IN RULE, not just one. app.css gives every button
   `width: 100%; margin-top: 1.2rem`. Resetting only the margin left the Copy
   button 1026px wide, which pushed it onto a row of its own underneath the URL
   and made the whole line three times taller than it should be - the same
   symptom manager.css describes for its own controls. */
.hookline .button-quiet { flex: 0 0 auto; width: auto; margin-top: 0; }

/* The secret's state, beside the header it belongs to. `baseline` because it
   sits inside a line of monospace and a middle-aligned pill rides high
   against it. */
.ticks .pill { margin-left: 0.5rem; vertical-align: baseline; }


/* ====================================================================== *
 * THE FACTS TABLE                                                        *
 *                                                                        *
 * Two or three columns where the first holds a short label and the last   *
 * holds a long value. `table-layout: auto` splits the free width in       *
 * proportion to content, which on the admin page gave the label column    *
 * 370px to hold the word "Version" - so every row had a third of its      *
 * width empty between a label and the value it names, and the eye had to  *
 * cross it eight times.                                                   *
 *                                                                        *
 * `width: 1%` IS THE TRICK THAT DID NOT WORK HERE, and it is worth saying  *
 * why rather than leaving somebody to try it again. It usually means       *
 * "shrink to content": the browser satisfies the 1%, finds the content     *
 * needs more, and gives it that. Against this table - `width: 100%` with   *
 * a `min-width: 46rem` under it - the auto algorithm honored the 1%       *
 * literally: the cell box collapsed to its padding, the label text spilled *
 * out past its own border, and the value column still started 400px away.  *
 * Measurably worse than the gap it was meant to close.                     *
 *                                                                         *
 * So the width is stated. It is a FLOOR, not a cap - a column with         *
 * `nowrap` grows past a specified width when its content needs more, so a  *
 * longer label added later widens the column instead of overflowing it.    *
 * ====================================================================== */

/* `table-layout: fixed` STOOD HERE AND HAS BEEN REMOVED. It was reached for
   while chasing the gap between these two columns, and it did not close it -
   because the gap was never a layout-algorithm problem. The label cell carried
   `.sub`, whose `display: block` had taken it out of the column model; see the
   note beside that rule above. Fixed layout only added a second bug, clipping
   the monospace paths in the scopes table, which auto layout sizes correctly.

   What is left is a width floor. `nowrap` means a column grows past it when a
   longer label arrives, rather than overflowing. */
.facts-table td:first-child,
.facts-table th:first-child {
  width: 11rem;
  white-space: nowrap;
  /* The gap between a label and its value is now this, and only this. */
  padding-right: 2rem;
}

/* The scope names and the call paths are both monospace and both fixed-ish, so
   they get their own floors and the sentence in the middle takes what is left -
   which is the column that actually benefits from the room. */
.scopes-table td:first-child,
.scopes-table th:first-child { width: 15rem; }

.scopes-table td:last-child,
.scopes-table th:last-child { width: 16rem; white-space: nowrap; }

.scope-name { font-size: 0.8rem; color: var(--forest); font-weight: 500; }
.scope-call { font-size: 0.75rem; }

.scopes-note { padding: 0 0 0.9rem; max-width: 68ch; }

/* The amber the search box uses for a sample row, for the same job: something
   that is not wrong but has not been confirmed. */
.pill-watch { color: var(--watch); border-color: var(--watch); }

/* ------------------------------------------------------- the drawer photo ---
   The patient's photo, beside their name. Square, per section 06; sand
   hairline; a fixed box so a slow or failed image leaves a gap of the same
   size rather than reflowing the header while the concierge is reading it. */
.drawer-photo {
  display: block;
  width: 88px;
  height: 88px;
  object-fit: cover;
  border: 1px solid var(--sand);
  background: var(--cream);
  flex: none;
}
.drawer-head-row { display: flex; align-items: flex-start; gap: 16px; }

/* ---------------------------------------------------------- the protocol ---
   What Sales sent across at intake. The details are free text and can carry
   the shape somebody typed, so newlines survive; the PDF is a link out to
   wherever Sales hosts it, styled as a button because that is what it does. */
.protocol-details {
  white-space: pre-line;
  font-size: 14px;
  line-height: 1.65;
  color: var(--ink-soft);
  background: var(--cream-warm);
  border: 1px solid var(--sand);
  padding: 0.85rem 1rem;
  margin-bottom: 0.75rem;
}

/* A REVISION IS THE ONE THING WORTH INTERRUPTING FOR. Everything else this
   section says is reference; this says the thing you remember reading is not
   the thing that is there now. Gold rule on the left rather than a filled
   panel - loud enough to catch the eye at the top of the drawer, quiet enough
   that a card carrying it does not look broken. */
.protocol-revised {
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink);
  background: var(--cream-warm);
  border-left: 3px solid var(--gold-deep);
  padding: 0.6rem 0.85rem;
  margin: 0.75rem 0 0;
}

.protocol-pdf {
  display: inline-block;
  padding: 0.6rem 1.1rem;
  background: var(--gold-deep);
  color: #FFFFFF;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  text-decoration: none;
}
.protocol-pdf:hover { background: var(--forest); }
.protocol-pdf:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }


/* ============================================================ booking ===
   WHAT THIS CARD IS DOWN FOR, at the top of the drawer where the question
   gets asked. The time is the headline because that is what somebody is
   looking for; everything else is support. */
.bk-when {
  font-family: var(--display);
  font-size: 17px;
  letter-spacing: .03em;
  color: var(--navy);
}

.bk-what {
  font-size: 13px;
  color: var(--ink);
  margin-top: 1px;
}

/* The way over to the Schedule, under the booking's facts. Blue as text on a
   light ground, never sky - the rule of this application. */
.bk-open {
  display: inline-block;
  margin-top: 4px;
  font-size: 12.5px;
  color: var(--blue);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.bk-open:hover { color: var(--navy-deep); }

/* THE POLICY WINDOW, SAID BEFORE SOMEBODY PRESSES ANYTHING. Amber rather than
   red: being inside the window is a fact about the booking, not a mistake
   somebody has made, and painting it as an error would teach people to
   dismiss it. */
.bk-warn {
  margin: 8px 0 0;
  padding: 8px 10px;
  border-left: 3px solid var(--watch);
  background: var(--off);
  border-radius: 0 8px 8px 0;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--ink);
}

.bk-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
}

.bk-btn {
  font: inherit;
  font-size: 12.5px;
  color: var(--blue);
  background: none;
  border: 1px solid var(--hair);
  border-radius: 999px;
  padding: 5px 13px;
  cursor: pointer;
}

.bk-btn:hover { border-color: var(--blue); background: var(--tint-light); }
.bk-btn:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

/* The one that starts something, rather than the ones that end it. */
.bk-btn-go {
  margin-top: 8px;
  color: var(--white);
  background: var(--navy);
  border-color: var(--navy);
}

.bk-btn-go:hover { background: var(--navy-deep); border-color: var(--navy-deep); }

/* What has already happened to this booking. Quieter than the live one on
   purpose - it is context, and a history styled like the present tense reads
   as several bookings all at once. */
.bk-past { margin-top: 10px; }

.bk-past-row {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-size: 12.5px;
  color: var(--navy);
  opacity: .7;
  padding: 3px 0;
}

.bk-past-status { flex: 0 0 auto; }

/* -------------------------------------------------------- the picker --- */
.bk-pick {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}

.bk-pick select { flex: 1 1 0; }

.bk-days { max-height: 46vh; overflow-y: auto; }

/* A DAY OF TIMES IS A STRIP, NOT A COLUMN. Half-hour starts across a working
   day is sixteen buttons; stacked they are a scroll, and side by side they
   are a shape somebody can read at a glance. */
.bk-times {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin: 0 0 12px;
}

.bk-time {
  font: inherit;
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  color: var(--navy);
  background: var(--white);
  border: 1px solid var(--hair);
  border-radius: 8px;
  padding: 5px 9px;
  cursor: pointer;
}

.bk-time:hover { border-color: var(--blue); background: var(--tint-light); }
.bk-time:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

.bk-time.on {
  color: var(--white);
  background: var(--navy);
  border-color: var(--navy);
}

.bk-extras {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 14px 0;
  padding-top: 12px;
  border-top: 1px solid var(--hair);
}
