:root {
  --green-dark: #2d6a4f;
  --green: #40916c;
  --green-light: #d8f3dc;
  /* Text sitting ON the brand bar, and nowhere else. Jenn, Sep 3, 2026:
     "I don't want words and numbers in that lime green anywhere other than on
     the bar ... I don't necessarily want it in the boxes on the page." */
  --on-brand: #d8f3dc;
  --ink: #1b2a22;
  --muted: #5c6b63;
  --bg: #f6f8f6;
  --card: #ffffff;
  --border: #e2e8e4;
  --warn-bg: #fff4e5;
  --warn-text: #8a5a00;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--ink);
}

a { color: var(--green-dark); }

.topbar {
  background: var(--green-dark);
  color: #fff;
  padding: 8px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.topbar .brand { font-weight: 700; font-size: 1.1rem; display: inline-flex;
  align-items: center; gap: 8px; }
/* A facility's own logo, scaled to the bar rather than the bar to the logo --
   a tall image must not push the navigation around. */
/* Sized for a SQUARE mark as well as a wide one -- Kawa's is 2000x2000, so a
   slot shaped for a banner rendered it as a small square adrift in the bar. */
.topbar .brand-logo { height: 52px; width: auto; max-width: 260px;
  object-fit: contain; display: block; }
.topbar a.logout { color: var(--on-brand); font-size: 0.9rem; text-decoration: none; }
/* LOG OUT IS A FORM NOW, NOT A LINK. Sep 5, 2026 -- Django 5 refuses a GET on
   logout and the link had been answering 405. The button is dressed as the
   link it replaces so nothing on the bar moves. */
.topbar form.logout-form { display: inline; margin: 0; padding: 0; }
.topbar form.logout-form button {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: var(--on-brand); font-size: 0.9rem;
}
.topbar form.logout-form button:hover { text-decoration: underline; }
.topbar .nav-links { display: flex; gap: 18px; flex: 1; margin-left: 28px; }
.topbar .nav-links a { color: var(--on-brand); text-decoration: none; font-size: 0.9rem; }
.topbar .nav-links a:hover { color: #fff; text-decoration: underline; }

/* The menu button and the log-out link that lives inside the menu belong to a
   phone only. On anything wider they are not drawn at all. */
.nav-toggle { display: none; }
.topbar .nav-links a.nav-logout { display: none; }
.topbar .nav-links form.nav-logout { display: none; }

.container {
  max-width: 1000px;
  margin: 0 auto;
  padding: 16px;
}

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px;
  margin-bottom: 16px;
}

.card h2, .card h3 {
  margin-top: 0;
}

.stat-row {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.stat-tile {
  background: var(--green-light);
  border-radius: 8px;
  padding: 10px 14px;
  min-width: 100px;
  text-align: center;
}

.stat-tile .num { font-size: 1.5rem; font-weight: 700; color: var(--green-dark); }
.stat-tile .label { font-size: 0.75rem; color: var(--muted); }

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

/* A WIDE TABLE SCROLLS INSIDE ITS CARD. IT DOES NOT RUN OFF THE PAGE.
   Sep 3, 2026. Jenn, on the bookings list with Sarah Boese's six dogs in it:
   "What I care about is the money running over the edge of the page."

   The Dogs column carries a photo, a name, badges, a breed and a room per
   dog, so a six-dog booking pushed the table wider than the card -- and the
   columns that fell off the right were Total and View. The money and the way
   into the booking were the two things you could not see.

   Every table in a card sits in one of these now, and a test fails the build
   if a new one does not. */
.table-scroll { overflow-x: auto; }

/* And a figure never breaks across two lines. "$3,353.50" split after the
   comma reads as two numbers. */
td[data-label="Amount"], td[data-label="Total"], td[data-label="Balance"],
td[data-label="Paid"] { white-space: nowrap; }
th { text-align: left; color: var(--muted); font-size: 0.75rem; text-transform: uppercase; padding: 6px 8px; border-bottom: 1px solid var(--border); }
td { padding: 8px; border-bottom: 1px solid var(--border); vertical-align: middle; }

.badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.75rem;
  background: var(--green-light);
  color: var(--green-dark);
}

.badge.archived {
  background: #eee;
  color: #666;
}

form.inline { display: flex; gap: 8px; flex-wrap: wrap; align-items: end; }
.field { display: flex; flex-direction: column; gap: 4px; font-size: 0.85rem; }

/* The HTML `hidden` attribute has to win over the rule above.
   Added Aug 30, 2026, after a form that rearranges itself did not rearrange.
   `.field { display: flex }` is an AUTHOR rule and the browser's built-in
   `[hidden] { display: none }` is a USER-AGENT rule, so the author rule wins
   and `hidden` silently does nothing on any .field div. Every hidden section
   on the Record Activity form had been visible the whole time, including the
   Where field two deploys earlier, while the JavaScript setting el.hidden ran
   perfectly and had no effect anyone could see.
   This is the CSS version of the same lesson as the browser-required dropdown:
   the code was right and the page was wrong. */
[hidden] { display: none !important; }
/* input[type=time] was missing from this list, so every time field in the app
   rendered with no padding and no border -- shorter than the fields beside it,
   which in a bottom-aligned row drops its label out of line. Jenn spotted it
   on Quick Checkin's Start time, Aug 31, 2026; a first attempt blamed the
   "optional" tag in the label and removed that instead, which changed nothing
   because the label was never the problem. Verify the page, not the theory. */
select, input[type=text], input[type=datetime-local], input[type=date], input[type=time], input[type=number], input[type=password], textarea {
  padding: 8px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 0.9rem;
}

/* A DATE FIELD HAS TO LOOK LIKE A FIELD.  Sep 3, 2026.

   Jenn, on a phone held upright: Date and Start time were a single
   continuous gray band across the card with no edges and no text, sitting
   between "Dog" and "How long", both of which were plainly white boxes with
   visible borders. They did not read as fields -- they read as nothing being
   there.

   iOS Safari paints its own gray fill on date and time inputs and the pale
   border above disappears into it. The rule above sets padding, border and
   radius on these types and had done since Aug 31; what it never set was a
   background, so on that platform it was overruled by a fill it did not know
   about.

   Not a portrait bug. It was the same in landscape, and on every date field
   in the app -- the narrow screen is only where it became obvious, because
   two of them landed side by side and merged into one bar.

   The same class as the accent color wired to a variable nothing read, and
   the applies_to box that took commas while the seed wrote spaces: a control
   that is silently doing nothing while the code around it looks right. */
input[type=date], input[type=time], input[type=datetime-local] {
  -webkit-appearance: none;
  appearance: none;
  background: var(--card);
  min-height: 38px;
}

/* Admin-locked fields (Aug 25, 2026 fix): every gated field now looks
   consistently locked, whichever control type it is. Before this, only
   <select> fields (Sex, Pet Size) visibly grayed out when disabled — Chrome
   renders disabled <input type=date>/<input type=number> almost identically
   to an enabled one, so Date of Birth, Weight, and Spayed/Neutered looked
   editable even though the server was silently rejecting changes to them
   until "Unlock with admin code" was used. This isn't a logic bug (the
   gating itself was already correct and working) — it's a missing visual
   cue, fixed here. */
select:disabled, input:disabled, textarea:disabled {
  background: var(--bg);
  color: var(--muted);
  border-color: var(--border);
  cursor: not-allowed;
  opacity: 1;
  -webkit-text-fill-color: var(--muted);
}

button, .btn {
  background: var(--green-dark);
  color: #fff;
  border: none;
  padding: 9px 16px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 0.9rem;
  text-decoration: none;
  display: inline-block;
}
button.small, .btn.small { padding: 5px 10px; font-size: 0.8rem; }
button.secondary { background: #fff; color: var(--green-dark); border: 1px solid var(--green-dark); }

.empty { color: var(--muted); font-style: italic; padding: 8px 0; }

.badge.over { background: #fbe9e7; color: #a33; }

/* Dashboard Feeding/Medications record forms (Aug 24, 2026) */
.slot-record-group { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.slot-record { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.slot-record select { padding: 5px 6px; font-size: 0.8rem; }
.done { font-size: 0.8rem; color: var(--green-dark); font-weight: 600; white-space: nowrap; }
.done-row { display: flex; align-items: center; gap: 8px; }
.slot-undo { display: inline; margin: 0; }
.slot-undo button { padding: 3px 8px; font-size: 0.72rem; }

.messages { list-style: none; padding: 0; margin: 0 0 12px; }
.messages li { padding: 10px 14px; border-radius: 6px; margin-bottom: 6px; background: var(--green-light); color: var(--green-dark); }
.messages li.error { background: #fbe9e7; color: #a33; }

.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 16px; }
.form-grid .field.full { grid-column: 1 / -1; }
.checkbox-list { display: flex; flex-direction: column; gap: 6px; max-height: 220px; overflow-y: auto; border: 1px solid var(--border); border-radius: 6px; padding: 10px; }
.checkbox-list label { display: flex; align-items: center; gap: 8px; font-size: 0.9rem; font-weight: normal; }
.detail-row { display: flex; gap: 24px; flex-wrap: wrap; margin-bottom: 6px; }
.detail-row .k { color: var(--muted); font-size: 0.75rem; text-transform: uppercase; }
.detail-row .v { font-size: 0.95rem; }
.actions-row { display: flex; gap: 10px; margin-bottom: 16px; }
@media (max-width: 640px) {
  .form-grid { grid-template-columns: 1fr; }
}

/* Resource calendar */
.calendar-scroll { overflow-x: auto; }
.cal-table { border-collapse: collapse; font-size: 0.82rem; }
.cal-table th, .cal-table td { border: 1px solid var(--border); padding: 4px 6px; text-align: center; vertical-align: top; white-space: nowrap; }
.cal-resource-col { text-align: left; position: sticky; left: 0; background: var(--card); z-index: 1; min-width: 150px; white-space: normal; }
.cal-resource-meta { font-size: 0.72rem; color: var(--muted); font-weight: normal; }
.cal-today { background: var(--green-light); }
.cal-cell { min-width: 92px; height: 30px; }
/* A WHOLE MONTH WITHOUT SCROLLING SIDEWAYS. Sep 3, 2026. Thirty-one columns
   at the fortnight width is 2,800px of swiping, which is the thing this view
   was asked for to avoid. The bar keeps its name; a bar too short to show one
   clips rather than stretching the grid. */
.cal-month .cal-cell { min-width: 26px; }
.cal-month th, .cal-month td { padding: 3px 2px; font-size: 0.74rem; }
.cal-month .cal-resource-col { min-width: 120px; }
.cal-month .cal-pill { overflow: hidden; text-overflow: ellipsis; }
.cal-over { background: #fbe9e7; }
.cal-over-label { font-size: 0.68rem; color: #a33; font-weight: 600; text-transform: uppercase; }
.cal-bar-cell { padding: 3px 4px; text-align: left; }
.cal-pill {
  display: block;
  border-radius: 6px;
  padding: 3px 8px;
  font-size: 0.75rem;
  text-decoration: none;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cal-pill.cal-cont-before { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.cal-pill.cal-cont-after { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.cal-boarding { background: #d8f3dc; }
.cal-board_train { background: #ffe8cc; }
.cal-day_academy { background: #d0ebff; }
.cal-grooming { background: #ffd6e8; }
.cal-training { background: #e5dbff; }
.cal-legend { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 12px; font-size: 0.8rem; color: var(--muted); }
.cal-legend .swatch { display: inline-block; width: 12px; height: 12px; border-radius: 3px; margin-right: 4px; vertical-align: middle; }
.cal-legend .cal-over-swatch { background: #fbe9e7; border: 1px solid #e0a89f; }

.login-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--green-dark);
}
.login-card {
  background: #fff;
  padding: 32px;
  border-radius: 12px;
  width: 320px;
}

/* ---------------------------------------------------------------------------
   A PHONE HELD UPRIGHT.  Sep 3, 2026.

   Jenn, relaying Stacie and Kari: "the view on the phone is great in landscape
   view, but not so good in portrait."

   Landscape was fine because a landscape phone is about as wide as a small
   laptop, so nothing here ever fired. Everything below is what breaks when the
   same page is 390px across instead of 844.
   --------------------------------------------------------------------------- */
@media (max-width: 640px) {

  /* 1. THE NAVIGATION RAN OFF THE RIGHT-HAND EDGE AND TOOK THE PAGE WITH IT.
     .nav-links is a single non-wrapping flex row of nine links. On a phone
     held upright it fitted four, and the other five were not scrolled to,
     hidden, or grayed out -- they were simply off the side of the glass with
     no way to reach them. Record Activity was one of them, which is the page
     Kari and Sydney open on a phone more than any other.
     So on a narrow screen the bar becomes two rows: who you are on top, where
     you can go underneath, wrapping as far down as it needs to. */
  .topbar { flex-wrap: wrap; padding: 8px 14px; row-gap: 6px; }
  .topbar .brand { font-size: 1rem; }
  .topbar .brand-logo { height: 34px; max-width: 150px; }
  .topbar .nav-links {
    order: 3;
    flex: 1 0 100%;
    margin-left: 0;
    /* One link per line, behind the Menu button. Nine of them wrapped across
       two rows was already the ceiling -- Jenn, Sep 3, 2026: "if we add any
       more roads up there, we might as well just put a hamburger up there."
       Wrapping degrades a link at a time and silently; a menu does not. */
    display: none;
    flex-direction: column;
    gap: 0;
    font-size: 1rem;
    border-top: 1px solid rgba(255, 255, 255, 0.25);
    margin-top: 4px;
    padding-top: 4px;
  }
  .nav-toggle-box:checked ~ .nav-links { display: flex; }
  /* A whole line to tap, not a word. */
  .topbar .nav-links a { padding: 9px 2px; display: block; }
  .topbar .nav-links a + a { border-top: 1px solid rgba(255, 255, 255, 0.15); }

  /* The button sits ON the brand bar, so it takes the bar's own text color --
     and says so on the line that reads the variable, which is how the accent
     is kept off the rest of the page. */
  .topbar .nav-toggle { color: var(--on-brand); }
  .nav-toggle {
    display: inline-block;
    font-size: 0.95rem;
    font-weight: 600;
    padding: 5px 10px;
    border: 1px solid rgba(255, 255, 255, 0.45);
    border-radius: 6px;
    cursor: pointer;
    -webkit-user-select: none;
    user-select: none;
  }
  /* Open, the button stays lit, so it is obvious what is holding the list
     down and what will put it away again. */
  .nav-toggle-box:checked ~ .nav-toggle { background: rgba(255, 255, 255, 0.18); }

  /* Log out moves into the menu, so the bar is a name and one button. */
  .topbar a.logout { display: none; }
  .topbar form.logout { display: none; }
  .topbar .nav-links a.nav-logout { display: block; }
  .topbar .nav-links form.nav-logout { display: block; }

  /* 2. A STACKED TABLE ROW THAT STILL SAYS WHAT EACH THING IS.
     The old rule hid <thead> and stacked the cells, so an Occupants row read
     as seven unlabelled lines -- "Sarah Boese / Bindi / Golden Retriever /
     Boarding / Run 3 / Paid / 2 days till check-out" -- with nothing saying
     which was the run and which was the breed.
     Now each cell carries its column name from the header (data-label), and
     the cells sit side by side and wrap instead of one per line, so a dog is
     about three lines instead of seven. That is the same objection Jenn made
     about feeding an hour earlier: "it's too high ... it makes the page too
     long." */
  table, tbody, tr, td { display: block; }
  thead { display: none; }
  tr {
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--card);
    padding: 8px 10px;
    margin-bottom: 8px;
  }
  td {
    display: inline-block;
    vertical-align: top;
    border: none;
    padding: 3px 16px 3px 0;
    max-width: 100%;
  }
  td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--muted);
    font-weight: 600;
  }
  /* The customer is the heading of the block, not one chip among seven. */
  tr > td:first-child { display: block; font-weight: 700; padding-right: 0; }
  tr > td:first-child::before { content: none; }
  /* An action cell with nothing in it must not leave a gap. */
  td:empty { display: none; }

  /* The handling-rule line belongs to the dog above it. Left as its own
     stacked block it floated free of the booking it warns about -- which on a
     safety line is not a cosmetic problem. */
  tr.handling-row {
    margin-top: -8px;
    border-top: none;
    border-top-left-radius: 0;
    border-top-right-radius: 0;
    padding-top: 4px;
  }
  tr.handling-row td { display: block; padding: 0; }

  /* 3. THE FORMS.
     form.inline bottom-aligns a row of fields, which on a phone squeezed Date,
     Start time and How long into slivers. Two to a row, and full width for
     anything that needs the space. */
  .stat-row { justify-content: space-between; }
  .stat-tile { min-width: 40%; flex: 1; }
  form.inline { align-items: stretch; }
  form.inline .field { flex: 1 1 140px; }
  form.inline .field select,
  form.inline .field input { width: 100%; }

  /* The resource calendar is a real grid and must stay one -- it already
     lives inside .calendar-scroll, which swipes sideways. Stacking it turned
     a week's occupancy into a column of dates. */
  .calendar-scroll table { display: table; }
  .calendar-scroll thead { display: table-header-group; }
  .calendar-scroll tbody { display: table-row-group; }
  .calendar-scroll tr { display: table-row; border: none; border-radius: 0;
    background: none; padding: 0; margin: 0; }
  .calendar-scroll td, .calendar-scroll th { display: table-cell;
    border: 1px solid var(--border); padding: 4px 6px; }
  .calendar-scroll td::before { content: none; }

  /* 4. A card should not spend a fifth of the screen on its own margins. */
  .container { padding: 12px 10px; }
  .card { padding: 12px; }
}

/* Customers list (Aug 25, 2026 — item 1) */
.az-filter { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.az-letter { display: inline-block; min-width: 22px; text-align: center; padding: 3px 6px; border-radius: 4px; font-size: 0.8rem; text-decoration: none; color: var(--green-dark); border: 1px solid var(--border); }
.az-letter.active, .az-letter:hover { background: var(--green-light); }
.pet-chip-row { display: flex; flex-wrap: wrap; gap: 10px 20px; }
.pet-chip { display: inline-flex; align-items: center; gap: 6px; font-size: 0.9rem; text-decoration: none; color: var(--ink); position: relative; }
.pet-chip img, .pet-chip-noimg { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; background: var(--green-light); display: inline-flex; align-items: center; justify-content: center; font-size: 1.1rem; }
.pet-chip img { transition: transform 0.15s ease-out, border-radius 0.15s ease-out; transform-origin: left center; cursor: zoom-in; }
.pet-chip:hover { z-index: 30; }
.pet-chip:hover img { transform: scale(3.25); border-radius: 8px; box-shadow: 0 6px 18px rgba(0,0,0,0.35); border: 2px solid #fff; }

/* Pet "block" style (Aug 26, 2026 — Jenn: "just the photo and the dog's name,
   one for each dog" — photo on top, name underneath, one clearly separated
   block per pet. Used on Booking pages and Customer Detail's bookings tables.
   Replaces the earlier inline pet-chip-row-compact attempt on those pages. */
.pet-block-row { display: flex; flex-wrap: wrap; gap: 14px 18px; }
.pet-block { display: flex; flex-direction: column; align-items: center; text-decoration: none; color: var(--ink); width: 72px; text-align: center; }
.pet-block img, .pet-block-noimg { width: 60px; height: 60px; border-radius: 10px; object-fit: cover; background: var(--green-light); display: flex; align-items: center; justify-content: center; font-size: 1.4rem; }
.pet-block .name { margin-top: 5px; font-size: 0.82rem; font-weight: 600; line-height: 1.2; word-break: break-word; }

/* Compact variant for Booking pages (Aug 26, 2026 — Jenn: doesn't need to be
   as big as the Customer page's version, but needs clear separation). */
.pet-block-row-compact { gap: 10px 14px; }
.pet-block-row-compact .pet-block { width: 46px; }
.pet-block-row-compact .pet-block img,
.pet-block-row-compact .pet-block-noimg { width: 40px; height: 40px; border-radius: 8px; font-size: 1.05rem; }
.pet-block-row-compact .pet-block .name { font-size: 0.7rem; margin-top: 3px; }

/* Booking Detail page — bordered photo-card grid for the main Pet(s) list
   (Aug 26, 2026 — Jenn sent an actual drawing after the pet-block attempt
   above still wasn't right: bordered box per dog, photo filling most of the
   box, name bold underneath, wrapping into rows; the per-resource-assignment
   list below it should show plain dog names only, no photos — see the
   removal of .pet-block-row from that spot in booking_detail.html). Scoped
   to the Booking Detail page only, per Jenn's explicit answer — the
   Bookings list table and Customer Detail's booking tables keep the
   existing compact .pet-block-row-compact treatment above. Cards remain
   clickable through to the dog's own Pet Detail page. */
.pet-card-grid { display: flex; flex-wrap: wrap; gap: 14px; margin: 6px 0 4px; }
.pet-card { display: flex; flex-direction: column; align-items: center; width: 120px; padding: 10px; border: 1px solid var(--border); border-radius: 10px; background: var(--card); box-shadow: 0 1px 3px rgba(0,0,0,0.08); text-decoration: none; color: var(--ink); transition: box-shadow 0.15s ease, transform 0.15s ease; }
.pet-card:hover { box-shadow: 0 4px 12px rgba(0,0,0,0.15); transform: translateY(-2px); }
.pet-card img, .pet-card-noimg { width: 100px; height: 100px; border-radius: 8px; object-fit: cover; background: var(--green-light); display: flex; align-items: center; justify-content: center; font-size: 2rem; }
.pet-card .name { margin-top: 8px; font-weight: 700; text-align: center; word-break: break-word; }

/* Customers list — photo-card grid (Jenn request, Aug 25, 2026) */
.customer-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 18px; margin-top: 14px; }
.customer-card { display: block; background: var(--card); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; text-decoration: none; color: var(--ink); transition: box-shadow 0.15s ease, transform 0.15s ease; }
.customer-card:hover { box-shadow: 0 6px 16px rgba(0,0,0,0.10); transform: translateY(-2px); }
.customer-card-photo { position: relative; width: 100%; aspect-ratio: 4 / 3.3; background: var(--green-light); overflow: hidden; }
.customer-card-photo-strip { display: flex; width: 100%; height: 100%; will-change: transform; }
.customer-card-photo-slot { flex: 0 0 100%; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; overflow: hidden; }
.customer-card-photo-slot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.customer-card-photo-slot .placeholder-icon { font-size: 2.6rem; opacity: 0.45; }
.customer-card-body { padding: 12px 14px 14px; }
.customer-card-name { font-weight: 700; font-size: 1.05rem; margin: 0 0 10px; color: var(--ink); }
.customer-card-field { margin-bottom: 8px; }
.customer-card-field:last-child { margin-bottom: 0; }
.customer-card-field .k { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); margin-bottom: 3px; }
.customer-card-field .v { font-size: 0.9rem; }
.customer-card-field .v.truncate { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.k9-pill { display: inline-block; background: var(--green-light); color: var(--green-dark); font-size: 0.78rem; padding: 2px 9px; border-radius: 10px; margin: 0 4px 4px 0; }
.email-pill { display: inline-block; background: var(--green-dark); color: #fff; font-size: 0.8rem; padding: 3px 10px; border-radius: 10px; }


.pet-photo-gallery {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
.pet-photo-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.pet-photo-item img {
  width: 120px;
  height: 120px;
  border-radius: 8px;
  object-fit: cover;
  border: 1px solid var(--border);
  background: var(--green-light);
}

.badge.deceased { background: #2f2f2f; color: #e8c468; }

.pet-memorial-badge {
  display: inline-flex;
  align-items: center;
  margin-left: 8px;
  padding-left: 8px;
  border-left: 1px solid var(--border);
  vertical-align: middle;
}
.pet-memorial-badge img {
    height: 44px;
  width: auto;
  display: block;
  background: none;
  border-radius: 0;
  object-fit: contain;
}

/* ---------------------------------------------------------------------------
   Safety surfaces (safety and handling model §5, §13) — Aug 28, 2026.

   Color discipline, agreed with Jenn Aug 28: RED is reserved for a dog-safety
   fact — an active handling rule, or a No-Go with a dog currently on property.
   AMBER is everything administrative: vaccinations, medications, stale
   verdicts. If red comes to mean four different things it stops meaning any of
   them, and staff learn that red means "Sarah's dogs, as usual".

   A border alone says "look", not "why" — so every red surface here carries a
   reason next to it, never a bare outline.
--------------------------------------------------------------------------- */

.safety-alert {
  border: 3px solid #c62828;
  border-radius: 8px;
  background: #fdf3f3;
  padding: 10px 14px;
  margin: 12px 0;
}

.safety-alert-label {
  color: #c62828;
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin-bottom: 4px;
}

.safety-alert-list {
  margin: 0;
  padding-left: 18px;
}

.safety-alert-list li { margin: 2px 0; }

/* Compact inline version for cards on list/overview screens. */
.safety-flag {
  display: block;
  gap: 5px;
  border: 2px solid #c62828;
  border-radius: 5px;
  background: #fdf3f3;
  color: #a01c1c;
  font-size: 0.74rem;
  font-weight: 600;
  line-height: 1.25;
  padding: 2px 6px;
  margin-top: 4px;
  max-width: 100%;
  text-align: left;
}

/* The marker used where a flag has no room for words -- a 46px pet chip in
   a list. The title attribute is unchanged, so hovering still gives the full
   rule text, which is the part Jenn actually uses: "I can scroll over it and
   it tells me everything." The words themselves move to .handling-line. */
/* A dog that went home before the money did. Deliberately still visible
   after the client pays -- the debt gets settled, the night it happened
   does not get unhappened. */
/* Weight (Aug 30, 2026). A flag is an open question, so it looks like one
   until somebody answers it. */
.amend > summary {
  cursor: pointer;
  font-size: 0.7rem;
  color: var(--muted);
  list-style: none;
  opacity: 0.65;
}
.amend > summary:hover { opacity: 1; text-decoration: underline; }
.amend[open] > summary { opacity: 1; }
.amend-was {
  font-size: 0.72rem;
  color: var(--muted);
  margin: 3px 0 0;
  font-style: italic;
}

.typeahead-hits {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 40;
  min-width: 260px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 6px 18px rgba(0,0,0,0.15);
  overflow: hidden;
}
.typeahead-hit {
  display: block;
  width: 100%;
  text-align: left;
  padding: 7px 10px;
  border: 0;
  background: none;
  font: inherit;
  color: var(--ink);
  cursor: pointer;
}
.typeahead-hit:hover, .typeahead-hit:focus { background: var(--green-light); }
.typeahead-none { padding: 7px 10px; font-size: 0.82rem; color: var(--muted); }

.weight-pattern {
  background: var(--green-light, #eaf3ec);
  border-radius: 6px;
  padding: 8px 10px;
  margin: 8px 0;
  font-size: 0.86rem;
}
.weight-stay { margin: 8px 0; }
.weight-stay > summary {
  cursor: pointer;
  padding: 6px 4px;
  border-bottom: 1px solid var(--border);
  font-size: 0.88rem;
}
.weight-stay > summary:hover { background: var(--green-light, #eaf3ec); }
.weight-older > summary {
  cursor: pointer;
  font-size: 0.78rem;
  color: var(--muted);
  padding: 4px 0;
}
.weight-down { color: #a01c1c; }
.weight-up { color: #2e6b3a; }

.weight-flag {
  border-left: 4px solid #c62828;
  background: #fdf3f3;
  padding: 8px 10px;
  margin: 6px 0;
  border-radius: 0 6px 6px 0;
  color: #a01c1c;
}
.weight-flag-inline {
  color: #a01c1c;
  font-size: 0.74rem;
  font-weight: 600;
  margin-top: 2px;
}
.weight-change { color: #a01c1c; font-weight: 600; }
.weight-chart-wrap { margin: 10px 0 4px; max-width: 420px; }
.weight-chart {
  width: 100%;
  height: auto;
  color: var(--green-dark, #2e5d3a);
  overflow: visible;
}
.weight-chart-scale {
  display: flex;
  justify-content: space-between;
  font-size: 0.72rem;
  color: var(--muted);
}

.went-home-owing {
  color: #a01c1c;
  font-size: 0.74rem;
  font-weight: 600;
}

.safety-flag-mark {
  display: inline-block;
  margin-top: 3px;
  color: #c62828;
  font-size: 0.95rem;
  line-height: 1;
  cursor: help;
}

/* One line per booking, naming each rule once, full width of the table. */
.handling-row td {
  border-top: 0;
  padding-top: 0;
  padding-bottom: 10px;
}
.handling-line {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 8px;
  align-items: baseline;
  font-size: 0.78rem;
}
.handling-line-label {
  color: #a01c1c;
  font-weight: 700;
  white-space: nowrap;
}
.handling-line-rule {
  border: 1px solid #e0b4b4;
  background: #fdf3f3;
  color: #a01c1c;
  border-radius: 4px;
  padding: 1px 6px;
  font-weight: 600;
}
.handling-line-pets { font-weight: 500; opacity: 0.85; }

.pet-card.has-safety-flag,
.pet-block.has-safety-flag {
  border: 2px solid #c62828;
  border-radius: 8px;
  padding: 6px;
}

.handling-rule-row {
  padding: 8px 12px;
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
  flex-wrap: wrap;
  border-left: 4px solid #c62828;
}

.handling-rule-lift {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
}

.handling-rule-lift input[type="text"] { max-width: 190px; }

.verdict-signoff { font-style: italic; }

/* "Not assessed" must never read as "fine" — safety model §2. */
.verdict-unsigned {
  color: #8a6d00;
  background: #fff6d8;
  border: 1px solid #e0c66a;
  border-radius: 4px;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 1px 6px;
}


/* Payment STATUS badges — visible to everyone, unlike amounts.
   Staff need to know a booking is settled before a dog leaves; they do not
   need the figures (Stacie, Aug 28, 2026). */
.pay-badge {
  display: inline-block; font-size: 0.72rem; font-weight: 700;
  padding: 1px 7px; border-radius: 4px; letter-spacing: 0.02em;
}
.pay-badge.paid   { background: #d8f3dc; color: #1b5e33; border: 1px solid #a9d9bb; }
.pay-badge.part   { background: #fff6d8; color: #8a6d00; border: 1px solid #e0c66a; }
.pay-badge.unpaid { background: #fdf3f3; color: #a01c1c; border: 1px solid #e0a0a0; }


/* Codes — the general classification mechanism (config inventory §3.3).

   THE COLOR DISCIPLINE, and it is the whole reason a code carries a kind:

     RED    the dog's physical safety, or a person's. Biter. Dog Reactive.
            A food allergy, if the facility says so.
     AMBER  administrative. Early pickup. Paperwork.
     SLATE  identity and classification. Working Dog. Service Dog. Trailing.

   Red never means paperwork (safety model §13.3). The moment an
   administrative code borrows red, red stops meaning "stop and read" and
   every genuinely dangerous dog loses its only visual claim on attention.
   That is why the color is decided by the code's kind rather than by whoever
   types the label. */
.code-strip {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  margin: 8px 0 4px;
}
.code-badge, .code-badge-sm {
  display: inline-block; border-radius: 4px; font-weight: 600;
}
.code-badge { font-size: 0.76rem; padding: 2px 8px; }
.code-badge-sm {
  font-size: 0.68rem; padding: 0 5px; margin: 0 4px 2px 0; border-radius: 3px;
}

.code-badge.slate, .code-badge-sm.slate {
  background: #e8eef5; color: #24405c; border: 1px solid #adc0d4;
}
.code-badge.amber, .code-badge-sm.amber {
  background: #fff6d8; color: #8a6d00; border: 1px solid #e0c66a;
}
/* Red carries the heavier border deliberately — it has to survive being one
   badge among six on a booking card. */
.code-badge.red, .code-badge-sm.red {
  background: #fdf3f3; color: #a01c1c; border: 2px solid #c62828;
}

/* Handling notes print under the strip rather than living in a tooltip. Jenn
   works from an iPad a great deal, where there is no hover, and a note that
   only exists on hover may as well not exist at 6am. */
.code-note { font-size: 0.76rem; color: #5b6b7c; font-style: italic; }
.code-note.red { color: #a01c1c; font-style: normal; font-weight: 600; }

/* Picker — grouped by kind, because this list only ever grows. */
.code-group-label {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; color: #35506b; margin: 10px 0 2px;
}
.code-group-label.safety { color: #a01c1c; }
.code-group-label.care { color: #8a6d00; }
.code-group-label.operational { color: #8a6d00; }

.code-picker { display: flex; flex-wrap: wrap; gap: 6px 14px; margin: 2px 0 6px; }
.code-pick {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 0.84rem; font-weight: normal; white-space: nowrap;
}
.code-pick input { margin: 0; }

/* Nesting, shown by indent and a rule rather than by a tree widget. SAR is an
   umbrella, not a peer — area search, trailing, tracking and HRD sit inside
   it, and a picker that offers SAR beside HRD tells any handler at a glance
   that the software was not built by one. */
.code-pick.depth-1, .code-pick.depth-2, .code-pick.depth-3 {
  border-left: 2px solid #cfd8e0; padding-left: 8px;
}
.code-pick.depth-1 { margin-left: 10px; }
.code-pick.depth-2 { margin-left: 24px; }
.code-pick.depth-3 { margin-left: 38px; }

.code-add {
  margin-top: 12px; padding-top: 10px;
  border-top: 1px dashed #cfd8e0;
}

/* Collapsed by default — most dogs at most kennels carry no codes at all, and
   they should not carry the editing form on every page view (Jenn, Aug 28).

   But collapsed is not the same as invisible. On Aug 30 Jenn went looking for
   where to mark a dog a Service Dog Candidate and could not find it: this sat
   directly above Handling Rules and Buddy/No-Go, both of which show a real
   button, so the only hidden control on the page was the one being hunted for.
   It stays collapsed and it looks like something you can press. */
.code-details > summary {
  cursor: pointer; width: fit-content; margin-top: 10px;
  list-style: none;
}
.code-details > summary::-webkit-details-marker { display: none; }
.code-details > summary.disclosure-button {
  display: inline-block; padding: 6px 14px;
  font-size: 0.85rem; font-weight: 600; color: #35506b;
  background: #fff; border: 1px solid #35506b; border-radius: 5px;
}
.code-details > summary.disclosure-button::before { content: "+ "; font-weight: 700; }
.code-details > summary.disclosure-button:hover { background: #eef3f8; }
.code-details[open] > summary.disclosure-button::before { content: "\2212 "; }
.code-details[open] > summary { margin-bottom: 8px; }

.btn.code-btn { background: #35506b; border-color: #35506b; color: #fff; }
.btn.code-btn:hover { background: #2a4157; }

/* Staged bookings: blocks, not a table.
   Aug 31, 2026. Ten columns of form controls needed a horizontal scrollbar,
   and a row you have to drag sideways is a row whose right-hand end nobody
   reads -- Cost, "Then what" and Remove were all off the edge. Jenn:
   "longer so that there's no need for scrolling." Each staged booking is now
   a block whose fields wrap, so it grows down the page. Same shape works on a
   phone, which is where the staff app lives. */
.staged-row {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 10px;
}
.staged-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.staged-head > div { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.staged-fields { display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: end; }

/* The booking flow's step 1 (Aug 31, 2026). The rail is a real sequence, so
   the numbers carry information rather than decorating the page. */
.steps-rail { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 14px; }
.step-chip {
  display: inline-flex; align-items: baseline; gap: 6px;
  padding: 6px 11px; border: 1px solid var(--border); border-radius: 4px;
  background: #fff; color: var(--muted); font-size: 0.82rem;
}
.step-chip b { font-variant-numeric: tabular-nums; }
.step-chip.now { border-color: var(--green-dark); color: var(--text); box-shadow: inset 0 -3px 0 var(--green-dark); }

.segmented { display: flex; flex-wrap: wrap; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
.segmented button {
  flex: 1 1 auto; padding: 9px 14px; border: 0; border-right: 1px solid var(--border);
  background: #fff; color: var(--muted); font-size: 0.9rem; font-weight: 600; cursor: pointer;
}
.segmented button:last-child { border-right: 0; }
.segmented button.on { background: var(--green-dark); color: #fff; }

.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--green-light); color: var(--green-dark);
  border-radius: 4px; padding: 4px 8px; font-size: 0.9rem; font-weight: 600;
}
.chip button { border: 0; background: transparent; color: inherit; cursor: pointer; font-size: 1rem; line-height: 1; padding: 0; }

.family { margin-top: 10px; padding: 10px 12px; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; }
.family-list { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0; }
.family-rule { margin: 0; font-size: 0.82rem; color: var(--muted); }

.typeahead-none { padding: 8px 10px; color: var(--muted); font-size: 0.9rem; }

/* Space proposals. Jenn chose "propose, you choose" over auto-assigning, and
   a busy space is still offered — warn, don't block. */
.space-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 10px; }
.space {
  display: flex; flex-direction: column; gap: 3px; text-align: left; cursor: pointer;
  padding: 10px 12px; border: 1px solid var(--border); border-radius: 6px;
  background: #fff; color: var(--text); font-family: inherit; font-size: 0.9rem;
}
.space:hover { border-color: var(--green-dark); }
.space-name { font-weight: 700; font-size: 0.98rem; }
.space-free { color: var(--green-dark); font-weight: 600; font-size: 0.82rem; }
.space-warn { color: #a3611a; font-size: 0.82rem; }
.space-busy { background: #fffaf2; }

/* Moving a dog between spaces, from the booking page (Aug 31, 2026). */
.move-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 6px; }
.move-row strong { min-width: 90px; }
.move-row select, .move-row input[type=text] { padding: 5px 7px; font-size: 0.88rem; }
.move-row input[type=text] { width: 160px; }

/* The pricing page (Aug 31, 2026). The worked figure beside each price is the
   point of the screen: every drifted number found in KennelBooker was caught
   by doing this arithmetic, and none was visible as a price on its own. */
.worked { color: var(--muted); font-variant-numeric: tabular-nums; }
.note-line {
  border-left: 3px solid var(--border); padding: 8px 12px;
  color: var(--muted); background: var(--bg); border-radius: 4px;
}

/* Discounts and comped sessions, shown as lines beside the quote (Aug 31, 2026). */
.adjustment-void { opacity: 0.62; }
.adjustment-void > strong { text-decoration: line-through; }
.adjustment { margin-top: 6px; font-size: 0.9rem; }
.adjust-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 8px; }
.adjust-row select, .adjust-row input { padding: 5px 7px; font-size: 0.88rem; }

/* Extras, step 3 of a booking (Aug 31, 2026). */
.extras-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(18rem,1fr)); gap: 8px; }
.extra { display: flex; gap: 8px; align-items: flex-start; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: 6px; cursor: pointer; font-weight: 400; }
.extra:hover { border-color: var(--green-dark); }

/* The step rail goes backwards (Aug 31, 2026). A step already passed is a
   button; a step ahead is not somewhere you can jump to. */
button.step-chip { font-family: inherit; font-size: 0.82rem; cursor: pointer; }
button.step-chip:hover { border-color: var(--green-dark); color: var(--text); }
.step-chip.ahead { opacity: 0.55; }

.shared-offer { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 6px; }

/* A line waiting on an answer reads red, so it is not mistaken for a price
   that has already been worked out. Jenn, Aug 31, 2026: "make those words red." */
.needs-answer { color: #a3321a; }

/* Putting each dog in a room, one click per dog (Aug 31, 2026). */
.seating { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.seat {
  display: inline-flex; gap: 6px; align-items: baseline;
  background: var(--green-light); color: var(--green-dark);
  border-radius: 4px; padding: 5px 9px; font-size: 0.9rem;
}
.seat-empty { background: var(--bg); color: var(--muted); border: 1px dashed var(--border); }
.space-ours { color: var(--green-dark); font-weight: 600; font-size: 0.85rem; }
/* A room you have put a dog in goes green, so somebody placing six dogs can
   see at a glance which rooms they have already used. Jenn, Aug 31, 2026:
   "make the click color green??? so that whoever is doing the click they can
   see right away that they have 2,3 , or more assigned." */
.space-taken-by-us {
  background: var(--green-light);
  border-color: var(--green-dark);
  box-shadow: inset 0 0 0 2px var(--green-dark);
}
.space-taken-by-us .space-name { color: var(--green-dark); }


/* The way into a booking from a dashboard row. Sep 3, 2026.

   A plain link, not a button -- Jenn sent a picture of what she wanted after
   the first attempt used the small secondary button style: "I don't want a
   visible open link. I really like the little view link. So not that it says
   open. I think it should say view."

   It takes the facility's own link color like every other link on the page,
   so it stays quiet next to the Check In and Check Out buttons, which are the
   things a person is actually reaching for on those rows. */
.row-view { font-weight: 600; text-decoration: none; white-space: nowrap; }
.row-view:hover { text-decoration: underline; }


/* Viewing as somebody else, outside Settings. Deliberately loud: an owner
   looking through a kennel tech's eyes must never forget they are. */
.view-as-bar {
  background: var(--warn-bg);
  color: var(--warn-text);
  border-bottom: 2px solid var(--warn-text);
  padding: 8px 20px;
  font-size: 0.88rem;
}
.view-as-bar a { color: var(--warn-text); font-weight: 700; margin-left: 10px; }


/* Feeding and medications as one block per dog rather than one wide table row.
   Jenn, Sep 3, 2026: "it's too high ... it makes the page too long." The old
   shape repeated a staff dropdown and a button per slot per dog inside a
   table cell, so a dog cost several inches whether it ate once or three
   times. */
.slot-cards {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
}
.slot-card {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  background: var(--card);
}
.slot-card-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
.slot-card-who { font-weight: 700; text-decoration: none; }
.slot-card-room {
  font-size: 0.78rem;
  color: var(--muted);
  text-decoration: none;
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0 7px;
}
.slot-card-note {
  font-size: 0.8rem;
  color: var(--muted);
  margin-top: 3px;
  line-height: 1.35;
}
.slot-card-slots {
  display: flex;
  gap: 8px;
  margin-top: 8px;
  flex-wrap: wrap;
}
.slot-card-slots .slot {
  flex: 1 1 90px;
  min-width: 92px;
  border-top: 2px solid var(--border);
  padding-top: 5px;
}
.slot-when { font-size: 0.7rem; font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--muted); }
.slot-amount { font-size: 0.82rem; margin: 1px 0 5px; }
.slot-card-slots select { width: 100%; font-size: 0.78rem; padding: 2px 4px; }
.slot-card-slots button { width: 100%; margin-top: 3px; }
.slot-none { font-size: 0.8rem; color: var(--muted); }

/* ONE LINE PER DOG. Sep 3, 2026 -- Jenn, on Sarah Boese's six dogs reading as
   three comma-separated lists: "the pictures, the name, the canine, the
   triangle, laboratory retriever, and their run all are in a row. Everything
   is stacked neatly on top of each other, but they're all in a nice row."
   Each dog's facts sit together, so they cannot fall out of alignment the way
   three separate columns did. */
/* A GRID, so the columns line up. Sep 3, 2026 -- the first version was a
   flowing line per dog, and Gregg (no K9 badge) had his breed and room sitting
   a badge's width left of everyone else's. Jenn: "The names all need to start
   from a left justified. The canines all need to be from a left justified...
   otherwise, my OCD is gonna kill me because they're not lined up."

   Five auto columns, so each takes the width of its widest entry across every
   dog on the booking and they all begin on the same vertical line. It is also
   how you check six dogs are in six different runs at a glance -- a column you
   can run your eye down, instead of reading every line. */
.dog-lines { display: grid; grid-template-columns: auto auto auto auto auto auto;
             justify-content: start; align-items: center; gap: 5px 10px; }
.dog-photo { display: inline-flex; }
.dog-photo img, .dog-photo .pet-chip-noimg {
  width: 26px; height: 26px; border-radius: 50%; object-fit: cover;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--chip); font-size: 0.8rem; }
.dog-name { font-weight: 600; text-decoration: none; white-space: nowrap; }
/* Codes and the triangle are SEPARATE columns. Sharing one meant Gregg, who
   has no K9 badge, had his triangle slide left into the gap and stop lining up
   with everyone else's. Sep 3, 2026 -- Jenn: "the triangles need to all be
   left justified." */
.dog-codes, .dog-flag { display: inline-flex; align-items: center; gap: 4px;
                        white-space: nowrap; }
.dog-line-breed { color: var(--muted); font-size: 0.8rem; white-space: nowrap; }
.dog-line-room { font-size: 0.78rem; font-weight: 600;
                 border: 1px solid var(--line); border-radius: 999px;
                 padding: 1px 8px; white-space: nowrap; }

/* On a phone five columns do not fit, and the dashboard IS a phone surface.
   The breed goes rather than the alignment: at a kennel door the name, the
   safety badge and the room are what somebody is reading, and breed is on the
   dog's own page. Four columns still line up. Sep 3, 2026. */
@media (max-width: 640px) {
  .dog-lines { grid-template-columns: auto auto auto auto auto; }
  .dog-line-breed { display: none; }
}

/* ---------------------------------------------------------------------------
   THE HOUSE PAGE PATTERN -- the client and dog records, redrawn.

   Sep 4, 2026. Designed with Jenn and Stacie in two published sandboxes and
   recorded in claude/the-house-page-pattern-sep-4-2026.md: identity header,
   then the one thing that must never be hidden, then facts in cards with
   their own Edit, then ONE tabbed card, then buttons and locks that follow
   the role.

   Used by customer_preview.html and pet_preview.html. Nothing else reads
   these yet, and nothing is being restyled underneath anybody.
   --------------------------------------------------------------------------- */

/* Two columns on a desktop, one on a phone. Facts on the left, what is
   happening on the right. */
.pv-cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr); gap: 18px; align-items: start; }
@media (max-width: 900px) { .pv-cols { grid-template-columns: minmax(0, 1fr); } }

/* Facts as label-and-value pairs. Read as text; a card becomes its own form
   only when somebody presses that card's Edit. */
dl.facts { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 5px 16px; margin: 0; }
dl.facts dt { color: var(--muted); font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.03em; padding-top: 2px; }
dl.facts dd { margin: 0; font-size: 0.92rem; }
dl.facts dd.mono { font-variant-numeric: tabular-nums; }
@media (max-width: 480px) { dl.facts { grid-template-columns: minmax(0, 1fr); gap: 2px; } dl.facts dd { margin-bottom: 8px; } }

/* Who may change this card, said on the card rather than found out by
   pressing something. */
.whocan { font-size: 0.72rem; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; margin-left: 8px; }
.card h2 .whocan, .card h3 .whocan { vertical-align: middle; }

/* THE TABS, WITHOUT JAVASCRIPT.

   Radio buttons and labels, the same reasoning as the phone menu in base.html:
   the only way to the rest of a dog's record must not depend on a script
   loading. The radios are moved off-screen rather than display:none, so they
   stay in the tab order and a keyboard still walks the strip.

   Positional classes (t1..t8 / l1..l8 / p1..p8) rather than one rule per tab
   name, so a page can name its own tabs and this block never has to be
   edited again to add one. */
.tabbed { position: relative; }
.tabbed > input.tp { position: absolute; left: -9999px; width: 1px; height: 1px; }
.tab-strip { display: flex; flex-wrap: wrap; border-bottom: 1px solid var(--border); margin: 0 -16px 14px; padding: 0 16px; }
.tab-strip label { padding: 10px 14px; cursor: pointer; font-weight: 600; font-size: 0.85rem;
                   color: var(--muted); border-bottom: 3px solid transparent; margin-bottom: -1px; }
.tab-strip label:hover { color: var(--ink); }
.tab-strip label .n { font-weight: 400; font-size: 0.78rem; color: var(--muted); margin-left: 5px; font-variant-numeric: tabular-nums; }
.tab-strip label .lk { font-weight: 400; font-size: 0.78rem; margin-left: 5px; }
.tab-page { display: none; }

.tabbed > .t1:checked ~ .tab-strip .l1,
.tabbed > .t2:checked ~ .tab-strip .l2,
.tabbed > .t3:checked ~ .tab-strip .l3,
.tabbed > .t4:checked ~ .tab-strip .l4,
.tabbed > .t5:checked ~ .tab-strip .l5,
.tabbed > .t6:checked ~ .tab-strip .l6,
.tabbed > .t7:checked ~ .tab-strip .l7,
.tabbed > .t8:checked ~ .tab-strip .l8 {
  color: var(--green-dark); border-bottom-color: var(--green-dark); background: var(--card);
}

.tabbed > .t1:focus-visible ~ .tab-strip .l1,
.tabbed > .t2:focus-visible ~ .tab-strip .l2,
.tabbed > .t3:focus-visible ~ .tab-strip .l3,
.tabbed > .t4:focus-visible ~ .tab-strip .l4,
.tabbed > .t5:focus-visible ~ .tab-strip .l5,
.tabbed > .t6:focus-visible ~ .tab-strip .l6,
.tabbed > .t7:focus-visible ~ .tab-strip .l7,
.tabbed > .t8:focus-visible ~ .tab-strip .l8 { outline: 2px solid var(--green); outline-offset: -2px; }

.tabbed > .t1:checked ~ .p1,
.tabbed > .t2:checked ~ .p2,
.tabbed > .t3:checked ~ .p3,
.tabbed > .t4:checked ~ .p4,
.tabbed > .t5:checked ~ .p5,
.tabbed > .t6:checked ~ .p6,
.tabbed > .t7:checked ~ .p7,
.tabbed > .t8:checked ~ .p8 { display: block; }

/* The identity line at the top of a record. */
.pv-head { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 6px; }
.pv-head h1 { margin: 0; font-size: 1.7rem; }
.pv-head .sub { color: var(--muted); font-size: 0.95rem; }
.pv-photo { width: 68px; height: 68px; border-radius: 10px; object-fit: cover; border: 1px solid var(--border); }

/* The read-only banner. These two pages cannot save anything, and saying so
   is cheaper than somebody discovering it by typing into a field that was
   never going to keep it. */
.pv-readonly { background: var(--warn-bg); color: var(--warn-text); border: 1px solid #f0d9ab;
               border-radius: 8px; padding: 9px 14px; margin-bottom: 14px; font-size: 0.88rem; }

.mono { font-variant-numeric: tabular-nums; }


/* THE THREE ANSWERS ON A REGISTRATION QUESTION. Sep 5, 2026.
   No · Yes · Unsure or don't know, laid out along one line so the choice is a
   glance rather than a dropdown to open. Jenn: "three states yes no unsure or
   don't know, because they might not know." */
.q-answers { display: flex; flex-wrap: wrap; gap: 16px; margin: 4px 0 6px; }
.q-pick { font-weight: 400; display: inline-flex; align-items: center; gap: 5px; }
.q-pick input { margin: 0; }
