/* ═══════════════════════════════════════════════════════════════════════
   PETS · Concept P   (b209)
   Loaded after design-v2-app.css, profile-c.css, trips-c.css, garage-c.css
   and school-c.css.

   Gated on `body.pv-on`, set by show() for the Pets view only. Every rule
   below is either prefixed with that class or confined to the `.pv-`
   namespace, so nothing here can reach another screen.

   WHY THIS FILE EXISTS, AND WHY IT IS LAST.
   Pets is the ORIGINAL. School was copied from it at b144 and Garage at
   b146, and both were rebuilt to Concept C while the section they came from
   was left on the b132 shape — a single sheet with the whole animal stacked
   down it in accordions, sixteen Material Symbols and thirteen emoji. The
   same one-line gate the other two needed is needed here: `pets` was not in
   show()'s dv2Views list, so `body.dv2-app` was never set, so every
   `var(--dv2-*)` written for this section resolved to nothing and voided its
   whole declaration, silently. That line is what makes this file possible.

   AND WHY IT IS NOT A COPY OF EITHER.
   School and Garage were each built by copying the section before them, and
   both inherited the previous one's defects along with its shape. Nothing
   here is copied: this file defines its own tokens, its own namespace and
   its own components, and where Pets uses shared machinery it CALLS it
   (the task rows, the assignee chip, the document actions) rather than
   restating it. What is deliberately shared with School and Garage is the
   STANDARD, not the source — an entity is a tile, the container behind the
   tiles is transparent, and exactly one thing per section is allowed to be
   a photograph instead.

   THE ONE DELIBERATE EXCEPTION. A pet is not a row with a thumbnail beside
   its name. On the Pets page the pet IS the photograph, full width, with
   its name, what it is and its one live health fact laid over it.
   Everything else on the page is a tile.
   ═══════════════════════════════════════════════════════════════════════ */

body.pv-on {
  /* Pets reuses the tile tokens the other three sections already agree on
     rather than defining a fifth set — five token sets for one visual
     standard is how they drift apart. */
  --pv-tile-bg: rgba(255, 255, 255, 0.72);
  --pv-tile-bd: rgba(20, 16, 38, 0.07);
  --pv-shadow: 0 1px 3px rgba(20, 20, 40, 0.05);
  --pv-rad: 16px;
  --pv-field-bd: rgba(20, 16, 38, 0.10);
  --pv-chip-bd: rgba(20, 16, 38, 0.22);
  --pv-act-bg: rgba(255, 255, 255, 0.62);
  /* The call button. Garage uses this green for the control that matters at
     the roadside and School for ringing the office; Pets' equivalent is
     ringing the vet, so it is the same green. */
  --pv-call-bg: #16704A;
  --pv-call-tx: #ffffff;
  --pv-ok-ink: #1F7A52;
  --pv-ok-bg: rgba(31, 122, 82, 0.10);
  --pv-warn-ink: #A0620C;
  --pv-warn-bg: rgba(232, 147, 12, 0.14);
  --pv-bad-ink: #B3312A;
  --pv-bad-bg: rgba(179, 49, 42, 0.12);
  --pv-quiet-bg: rgba(120, 120, 128, 0.09);
  /* THE SIX MAJOR TINTS, defined here and passed to the renderer by name.
     b205's lesson in School: six tint names were handed in from JavaScript
     and defined nowhere, so six of seven majors lost their icon colour and
     nothing said so. Each of these is defined in all three theme blocks. */
  --pv-t-about: rgba(120, 120, 128, 0.14);
  --pv-t-health: rgba(47, 143, 95, 0.16);
  --pv-t-task: rgba(10, 108, 255, 0.14);
  --pv-t-ins: rgba(232, 147, 12, 0.18);
  --pv-t-doc: rgba(120, 120, 128, 0.14);
  --pv-t-life: rgba(110, 86, 207, 0.16);
  /* The scrim under a pet's name on their photograph. Fixed, not themed: it
     sits on a photograph, not on the app's ground. */
  --pv-veil: linear-gradient(to top, rgba(0,0,0,.64) 0%, rgba(0,0,0,.18) 48%, transparent 72%);
  --pv-badge-bg: hsl(355 72% 48%);
  --pv-badge-tx: #ffffff;
  --pv-badge-ring: rgba(238, 242, 255, 1);
  --pv-sheet-bg: rgba(255, 255, 255, 0.88);
}
html[data-theme="dark"] body.pv-on {
  --pv-tile-bg: rgba(255, 255, 255, 0.07);
  --pv-tile-bd: rgba(255, 255, 255, 0.12);
  --pv-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
  --pv-field-bd: rgba(255, 255, 255, 0.14);
  --pv-chip-bd: rgba(255, 255, 255, 0.30);
  --pv-act-bg: rgba(255, 255, 255, 0.07);
  --pv-call-bg: #2F8F5F;
  --pv-ok-ink: #7BE0AE;
  --pv-ok-bg: rgba(123, 224, 174, 0.14);
  --pv-warn-ink: #F0B45C;
  --pv-warn-bg: rgba(240, 180, 92, 0.16);
  --pv-bad-ink: #FF8A80;
  --pv-bad-bg: rgba(255, 138, 128, 0.14);
  --pv-quiet-bg: rgba(255, 255, 255, 0.08);
  --pv-t-about: rgba(255, 255, 255, 0.10);
  --pv-t-health: rgba(123, 224, 174, 0.20);
  --pv-t-task: rgba(90, 166, 255, 0.20);
  --pv-t-ins: rgba(255, 180, 80, 0.22);
  --pv-t-doc: rgba(255, 255, 255, 0.10);
  --pv-t-life: rgba(168, 150, 240, 0.22);
  --pv-badge-bg: hsl(355 78% 58%);
  --pv-badge-tx: #14121F;
  --pv-badge-ring: rgba(20, 16, 38, 1);
  --pv-sheet-bg: rgba(26, 20, 50, 0.92);
}
@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) body.pv-on {
    --pv-tile-bg: rgba(255, 255, 255, 0.07);
    --pv-tile-bd: rgba(255, 255, 255, 0.12);
    --pv-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
    --pv-field-bd: rgba(255, 255, 255, 0.14);
    --pv-chip-bd: rgba(255, 255, 255, 0.30);
    --pv-act-bg: rgba(255, 255, 255, 0.07);
    --pv-call-bg: #2F8F5F;
    --pv-ok-ink: #7BE0AE;
    --pv-ok-bg: rgba(123, 224, 174, 0.14);
    --pv-warn-ink: #F0B45C;
    --pv-warn-bg: rgba(240, 180, 92, 0.16);
    --pv-bad-ink: #FF8A80;
    --pv-bad-bg: rgba(255, 138, 128, 0.14);
    --pv-quiet-bg: rgba(255, 255, 255, 0.08);
    --pv-t-about: rgba(255, 255, 255, 0.10);
    --pv-t-health: rgba(123, 224, 174, 0.20);
    --pv-t-task: rgba(90, 166, 255, 0.20);
    --pv-t-ins: rgba(255, 180, 80, 0.22);
    --pv-t-doc: rgba(255, 255, 255, 0.10);
    --pv-t-life: rgba(168, 150, 240, 0.22);
    --pv-badge-bg: hsl(355 78% 58%);
    --pv-badge-tx: #14121F;
    --pv-badge-ring: rgba(20, 16, 38, 1);
    --pv-sheet-bg: rgba(26, 20, 50, 0.92);
  }
}

/* THE GROUND. style.css paints #view-pets and .pets-body on the old flat
   surface; the aurora comes from the tokens now, so those fills have to
   stand down or they sit on top of it as an opaque slab — the same mistake
   #shops-box made in Profile, #trip-list in Travel, #car-hub in Garage and
   #school-hub in School. Fifth time. */
body.pv-on #view-pets,
body.pv-on .pets-body,
body.pv-on #pets-hub {
  background: transparent;
}
body.pv-on {
  /* style.css paints `html` as well as `body`, which stops the body's
     background propagating to the canvas — so on a short screen (one pet,
     or none) the aurora ended where the content ended and a flat grey band
     filled the rest of the phone. */
  min-height: 100dvh;
  background: var(--dv2-bg-grad, #F4F2FA);
}
/* body.dv2-app stands the shared 20px body padding down for the dashboard's
   near-full-bleed constellation. Pets is a reading surface and wants it back. */
body.pv-on #view-pets {
  padding: 0 16px calc(112px + env(safe-area-inset-bottom, 0px));
}
/* style.css gives .pets-body its own 16px on all four sides and a 640px cap.
   The gutter belongs to the view now (above), and the top padding would stack
   with .pv-wrap's — 30px of nothing above the photograph. */
body.pv-on .pets-body { padding: 0; max-width: none; }

/* ── THE HEADER ─────────────────────────────────────────────────────────
   b207's lesson, applied from the start rather than after a release.
   .topbar-row is justify-content:space-between, and three flex children
   under space-between go to the two edges AND THE MIDDLE — which is where
   the word "Pets" is. Two equal side regions with a title that shrinks to
   its text is exactly centred whatever either side holds, and nothing is
   taken out of the flow, so nothing can land on top of anything else.
   No min-width:0 on the sides: if the row runs out of room the title is
   what gives, never a control. */
body.pv-on #view-pets .pv-top-side {
  display: flex; align-items: center; gap: 8px; flex: 1 1 0;
}
body.pv-on #view-pets .pv-top-side.end { justify-content: flex-end; }
body.pv-on #view-pets .pets-topbar-row .title-wrap { flex: 0 1 auto; }
/* .pets-add-top carries margin-left:auto for the two-button header it was
   written for. Inside a group it would shove the pair to opposite ends. */
body.pv-on #view-pets .pv-top-side .pets-add-top { margin-left: 0; }
body.pv-on #pv-topbtns:empty { display: none; }
body.pv-on .pv-topbtn { position: relative; flex: none; }
body.pv-on .pv-topbtn .pv-ic { width: 21px; height: 21px; }
body.pv-on .pv-topcount {
  position: absolute; top: -3px; right: -3px; min-width: 16px; height: 16px;
  padding: 0 4px; border-radius: 99px; background: var(--pv-badge-bg);
  color: var(--pv-badge-tx); border: 1.5px solid var(--pv-badge-ring);
  font-size: 9.5px; font-weight: 800; line-height: 13px; text-align: center;
  font-variant-numeric: tabular-nums;
}

/* ── Icons ──────────────────────────────────────────────────────────────
   Pets draws from the SHARED map (DV2_UI_ICON falling through to
   DV2_LINE_ICON), not from a fifth private one. No PNGs, no Material
   Symbols, no emoji anywhere in this section. */
body.pv-on .pv-ic {
  width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor;
  stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round;
}
body.pv-on .pv-ic-sm { width: 17px; height: 17px; }
body.pv-on .pv-ic-xs { width: 14px; height: 14px; stroke-width: 2.1; }
body.pv-on .pv-ic-lg { width: 30px; height: 30px; stroke-width: 1.6; }

/* ── THE PHOTOCARD ──────────────────────────────────────────────────────*/
body.pv-on .pv-wrap { padding-top: 14px; }
body.pv-on .pv-card {
  position: relative; border-radius: 20px; overflow: hidden; height: 192px;
  box-shadow: var(--pv-shadow); background: var(--pv-tile-bg);
}
body.pv-on .pv-hero {
  position: absolute; inset: 0; width: 100%; height: 100%; border: 0; padding: 0;
  background-size: cover; background-position: center; cursor: pointer;
}
/* A pet with no photograph still gets a PICTURE, not a grey box: the card is
   a photograph by design, so the placeholder has to hold that shape. */
body.pv-on .pv-hero-add {
  display: grid; place-items: center; align-content: center; gap: 8px; color: #fff;
}
body.pv-on .pv-hero-add-t { font-size: 13.5px; font-weight: 600; }
body.pv-on .pv-veil {
  position: absolute; inset: 0; pointer-events: none; background: var(--pv-veil);
}
/* On the photograph, white is correct in BOTH themes: the ground is the
   picture and the veil, not the page. */
body.pv-on .pv-who { position: absolute; left: 16px; bottom: 14px; right: 16px;
  color: #fff; pointer-events: none; }
body.pv-on .pv-who b {
  display: block; font-size: 22px; font-weight: 700; letter-spacing: -.015em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.pv-on .pv-who span {
  display: block; font-size: 13.5px; font-weight: 500; opacity: .92; margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.pv-on .pv-cardmenu {
  position: absolute; top: 10px; left: 10px; z-index: 2;
  width: 34px; height: 34px; border: 0; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer;
  background: rgba(0, 0, 0, .45); color: #fff;
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
/* Where School puts the Ofsted rating, Pets puts the one health fact that
   changes without the household doing anything. It is a BUTTON, because the
   thing you want when you read "due in 14 days" is the record it came from.
   max-width so a long line cannot reach the menu on the other corner. */
body.pv-on .pv-pill {
  position: absolute; top: 12px; right: 12px; z-index: 2;
  display: flex; align-items: center; gap: 6px; max-width: calc(100% - 68px);
  border: 0; cursor: pointer; font-family: inherit;
  background: rgba(0, 0, 0, .55); color: #fff;
  padding: 6px 11px; border-radius: 999px; font-size: 11.5px; font-weight: 640;
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
body.pv-on .pv-pill span:last-child {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
body.pv-on .pv-pill i {
  width: 7px; height: 7px; border-radius: 50%; flex: none; background: hsl(38 82% 55%);
}
body.pv-on .pv-pill.good i { background: hsl(152 52% 50%); }
body.pv-on .pv-pill.bad i { background: hsl(355 72% 60%); }
body.pv-on .pv-pill.unknown i { background: rgba(255, 255, 255, .55); }

/* One dot per pet. With a single pet there is nothing to move between, so
   there are no dots — a control that can only do nothing is worse than none. */
body.pv-on .pv-dots { display: flex; justify-content: center; gap: 2px; padding: 8px 0 2px; }
/* b221.1 — SECTION_CHROME R6. The MARK stays 7px; the TARGET becomes 28px.
   health-c.css b214.1 measured this and wrote it down: "a 7px control is about
   a sixth of a fingertip, and this is the one you press every time you want a
   different person". Canon adopting the better answer, not the older one. */
body.pv-on .pv-dot {
  width: 28px; height: 28px; border-radius: 50%; border: 0; padding: 0; cursor: pointer;
  background: none; display: grid; place-items: center;
  -webkit-tap-highlight-color: transparent;
}
body.pv-on .pv-dot::before {
  content: ''; width: 7px; height: 7px; border-radius: 50%;
  background: var(--pv-chip-bd); transition: background .15s ease;
}
body.pv-on .pv-dot[aria-current="true"]::before { background: var(--dv2-text-primary); }

/* ── The vet card ───────────────────────────────────────────────────────
   Folded it is the practice and whether they are registered, which is what
   you need at a glance; the address and the three actions are one tap away
   rather than always occupying a third of the screen. */
body.pv-on .pv-vet {
  margin-top: 10px; padding: 13px 14px; border-radius: var(--pv-rad);
  background: var(--pv-tile-bg); border: 1px solid var(--pv-tile-bd);
  box-shadow: var(--pv-shadow);
}
body.pv-on .pv-vetfold-h {
  display: flex; align-items: center; gap: 10px; width: 100%; border: 0;
  background: none; cursor: pointer; padding: 0; color: var(--dv2-text-primary);
  font-family: inherit; text-align: left;
}
body.pv-on .pv-vetfold-h .pv-grow { min-width: 0; }
body.pv-on .pv-vet-n {
  display: block; font-size: 15px; font-weight: 700; letter-spacing: -.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.pv-on .pv-vet-s { display: block; font-size: 12.5px; color: var(--dv2-text-sub); margin-top: 1px; }
body.pv-on .pv-vetfold-chev { flex: none; color: var(--dv2-text-sub); transition: transform .22s ease; }
body.pv-on .pv-vet.is-open .pv-vetfold-chev { transform: rotate(90deg); }
body.pv-on .pv-vet-b { display: none; }
body.pv-on .pv-vet.is-open .pv-vet-b { display: block; }
body.pv-on .pv-vet-addr {
  margin: 11px 0 0; font-size: 13px; line-height: 1.45; color: var(--dv2-text-sub);
}
/* THE THREE ACTIONS. Equal thirds, because no one of them is the answer
   every time — you ring about a limp, email for a repeat prescription and
   open the site to book. Call is the filled one: it is the one you reach for
   when something is wrong. */
body.pv-on .pv-acts {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px; margin-top: 12px;
}
body.pv-on .pv-act {
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 11px 6px 9px; border-radius: 14px; min-width: 0;
  background: var(--pv-act-bg); border: 1px solid var(--pv-tile-bd);
  color: var(--dv2-text-primary); font-family: inherit; cursor: pointer;
  text-decoration: none; -webkit-tap-highlight-color: transparent;
}
body.pv-on .pv-act-l { font-size: 12.5px; font-weight: 650; letter-spacing: -.01em; }
/* The value under the label is the proof the button will work. It must not
   push the button wider than its third of the row. */
body.pv-on .pv-act-cap {
  max-width: 100%; font-size: 10px; font-weight: 550; color: var(--dv2-text-sub);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.pv-on .pv-act-call {
  background: var(--pv-call-bg); border-color: var(--pv-call-bg); color: var(--pv-call-tx);
}
body.pv-on .pv-act-call .pv-act-cap { color: rgba(255, 255, 255, 0.82); }
/* NOTHING TO CALL YET IS STILL A CONTROL. A dashed button that says "Add
   email" teaches the household the app can hold one; a missing row teaches
   nothing, and hiding the capability is how a feature stays undiscovered. */
body.pv-on .pv-act.add {
  background: transparent; border-style: dashed; color: var(--dv2-text-sub);
}
body.pv-on .pv-act:active { transform: scale(.96); }
@media (prefers-reduced-motion: reduce) { body.pv-on .pv-act:active { transform: none; } }

/* Expand all / Collapse all, above the majors it governs. */
body.pv-on .pv-allfold { display: flex; justify-content: flex-end; padding: 8px 2px 2px; }
body.pv-on .pv-allfold button {
  border: 0; background: none; cursor: pointer; padding: 6px 4px;
  color: var(--dv2-link, #5b4fe0); font-size: 13.5px; font-weight: 600; font-family: inherit;
}

/* ── THE MAJORS ─────────────────────────────────────────────────────────*/
body.pv-on .pv-majors { display: flex; flex-direction: column; gap: 9px; margin-top: 2px; }
body.pv-on .pv-major {
  border-radius: var(--pv-rad); background: var(--pv-tile-bg);
  border: 1px solid var(--pv-tile-bd); box-shadow: var(--pv-shadow); overflow: hidden;
}
body.pv-on .pv-major-head { display: flex; align-items: center; padding-right: 12px; }
body.pv-on .pv-major-head .pv-major-h { flex: 1; min-width: 0; }
body.pv-on .pv-major-h {
  display: flex; align-items: center; gap: 11px; padding: 15px; border: 0;
  background: none; text-align: left; cursor: pointer; color: var(--dv2-text-primary);
  font-family: inherit;
}
body.pv-on .pv-major-ic {
  width: 30px; height: 30px; border-radius: 9px; flex: none; display: grid; place-items: center;
}
body.pv-on .pv-grow { flex: 1; min-width: 0; }
body.pv-on .pv-major-n {
  display: block; font-size: 16px; font-weight: 600; letter-spacing: -.01em;
  color: var(--dv2-text-primary);
}
/* THE SUBTITLE IS THE WHOLE POINT OF A CLOSED MAJOR, so it may not be cut
   off mid-word. `nowrap` turned "Vaccination due in 14 days · 3 records" into
   "…· 3 re…" on a 393pt phone — the header exists to save you opening the
   section and it was withholding the half that would. Two lines, clamped. */
body.pv-on .pv-major-s {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  font-size: 13px; line-height: 1.35; color: var(--dv2-text-sub); margin-top: 2px;
  overflow: hidden;
}
body.pv-on .pv-major-s .warn { color: var(--pv-warn-ink); font-weight: 600; }
body.pv-on .pv-major-s .bad { color: var(--pv-bad-ink); font-weight: 600; }
body.pv-on .pv-major-s .ok { color: var(--pv-ok-ink); font-weight: 600; }
/* CLOSED POINTS RIGHT, OPEN POINTS DOWN — the list is below, so the arrow
   turns toward it. */
body.pv-on .pv-major-chev { flex: none; color: var(--dv2-text-sub); transition: transform .22s ease; }
/* A row inside an open major opens a SHEET; it does not fold. Its own mark, so
   the major's open-state rule cannot reach it. */
body.pv-on .pv-row-chev { flex: none; color: var(--dv2-text-sub); }
body.pv-on .pv-major.is-open .pv-major-chev { transform: rotate(90deg); }
body.pv-on .pv-major-pill {
  background: var(--pv-ok-bg); color: var(--pv-ok-ink);
  padding: 4px 9px; border-radius: 999px; flex: none; font-size: 12px; font-weight: 600;
}
body.pv-on .pv-major-pill.warn { background: var(--pv-warn-bg); color: var(--pv-warn-ink); }
body.pv-on .pv-major-tools { display: flex; gap: 4px; flex: none; }
body.pv-on .pv-mtool {
  width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center;
  background: var(--pv-tile-bd); color: var(--dv2-link, #5b4fe0); cursor: pointer;
  border: 0; padding: 0;
}
body.pv-on .pv-major-b { display: none; padding: 0 14px 14px; }
body.pv-on .pv-major.is-open .pv-major-b { display: block; }
/* The card already pads 14px at the bottom, so a trailing margin on the last
   child is a hole, not spacing: the last child has no sibling below it. */
body.pv-on .pv-major-b > :last-child { margin-bottom: 0; }
body.pv-on .pv-empty {
  margin: 4px 0 0; color: var(--dv2-text-sub); font-size: 13.5px; line-height: 1.45;
}

/* ── Info rows ──────────────────────────────────────────────────────────*/
body.pv-on .pv-row {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 10px 0; border: 0; border-bottom: 1px solid var(--pv-tile-bd);
  background: transparent; text-align: left; font-family: inherit;
  color: inherit; cursor: default;
}
body.pv-on button.pv-row { cursor: pointer; }
body.pv-on .pv-row:last-child { border-bottom: 0; }
body.pv-on .pv-row > .pv-ic { color: var(--dv2-text-sub); }
body.pv-on .pv-k {
  display: block; font-size: 9.5px; font-weight: 800; letter-spacing: .12em;
  text-transform: uppercase; color: var(--dv2-text-muted);
}
body.pv-on .pv-v {
  display: block; font-size: 13px; font-weight: 600; letter-spacing: -0.01em;
  color: var(--dv2-text-primary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.pv-on .pv-v.mut { color: var(--dv2-text-muted); }
body.pv-on .pv-v.ok { color: var(--pv-ok-ink); }
body.pv-on .pv-v.warn { color: var(--pv-warn-ink); }
body.pv-on .pv-v.bad { color: var(--pv-bad-ink); }
/* Where a value came from, said under it. A record read off a document that
   does not name the document is a number the household has to take on trust. */
body.pv-on .pv-src {
  display: flex; align-items: center; gap: 5px; margin-top: 3px;
  font-size: 10.5px; font-weight: 550; color: var(--dv2-text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.pv-on .pv-src .pv-ic { width: 12px; height: 12px; stroke-width: 2; }

/* The weight trend. Six bars is enough to read a direction and short enough
   to sit on one row beside the value it belongs to. */
body.pv-on .pv-spark { display: flex; align-items: flex-end; gap: 3px; height: 22px; flex: none; }
body.pv-on .pv-spark i {
  width: 5px; border-radius: 2px 2px 0 0; background: var(--pv-ok-ink); display: block;
  min-height: 3px;
}
body.pv-on .pv-spark i.dim { background: var(--pv-tile-bd); }

/* ── Task rows ─────────────────────────────────────────────────────────
   b210 — the bespoke `.pv-task` row that used to live here is GONE. Pets draws
   the shared `.row.tc-row` now, and what this file says about it is at the
   bottom of the file: tokens only. Everything that was here — its own check
   circle, its own type scale, its own tools rail, its own green completion
   ring — is the drift this release removed. */

/* ── The spine — a life in chapters ─────────────────────────────────────
   The knot is drawn with a border, not a shadow, because it sits on a
   translucent tile ground and a shadow on glass reads as smudge. */
body.pv-on .pv-spine { position: relative; padding-left: 22px; margin-top: 4px; }
body.pv-on .pv-spine::before {
  content: ''; position: absolute; left: 5px; top: 10px; bottom: 10px; width: 1.5px;
  background: var(--pv-tile-bd);
}
body.pv-on .pv-chap { position: relative; margin-bottom: 14px; }
body.pv-on .pv-chap:last-child { margin-bottom: 0; }
body.pv-on .pv-knot {
  position: absolute; left: -22px; top: 3px; width: 11px; height: 11px; border-radius: 50%;
  background: var(--pv-tile-bg); border: 2px solid var(--dv2-text-sub);
}
body.pv-on .pv-chap.now .pv-knot { border-color: var(--pv-warn-ink); background: var(--pv-warn-ink); }
body.pv-on .pv-chap-y {
  font-size: 13px; font-weight: 800; letter-spacing: .04em; color: var(--dv2-text-sub);
  font-variant-numeric: tabular-nums;
}
body.pv-on .pv-ent {
  display: flex; align-items: center; gap: 10px; margin-top: 7px; width: 100%;
  padding: 10px 11px; border-radius: 12px; background: var(--pv-tile-bd);
  border: 0; text-align: left; font-family: inherit; color: inherit; cursor: pointer;
}
/* Not yet happened, so it does not look like it has. */
body.pv-on .pv-ent.soon {
  background: transparent; border: 1px dashed var(--pv-chip-bd); opacity: .82;
}
body.pv-on .pv-ent-n {
  display: block; font-size: 13.5px; font-weight: 600; letter-spacing: -.01em;
  color: var(--dv2-text-primary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.pv-on .pv-ent-s {
  display: block; font-size: 11.5px; color: var(--dv2-text-sub); margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.pv-on .pv-more {
  width: 100%; margin-top: 8px; padding: 11px; border: 0; border-radius: 12px;
  background: var(--pv-tile-bd); color: var(--dv2-text-sub);
  font-size: 13.5px; font-weight: 600; cursor: pointer; font-family: inherit;
}

/* ── Documents ──────────────────────────────────────────────────────────*/
body.pv-on .pv-crumb {
  display: flex; align-items: center; gap: 9px; padding: 12px; width: 100%;
  border: 0; border-radius: 12px; background: var(--pv-tile-bd); margin-bottom: 8px;
  text-align: left; font-family: inherit; color: inherit; cursor: pointer;
}
body.pv-on .pv-crumb-t { display: block; font-size: 13.2px; font-weight: 650; color: var(--dv2-text-primary); }
body.pv-on .pv-crumb-p {
  display: block; font-size: 11px; color: var(--dv2-text-muted); margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.pv-on .pv-doc { margin-bottom: 7px; }
body.pv-on .pv-doc:last-child { margin-bottom: 0; }
body.pv-on .pv-doc-line {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 11px 12px;
  border: 0; border-radius: 12px; background: var(--pv-tile-bd);
  text-align: left; font-family: inherit; color: inherit; cursor: pointer;
}
body.pv-on .pv-doc-chev { transition: transform .22s ease; color: var(--dv2-text-sub); }
body.pv-on .pv-doc.is-open .pv-doc-chev { transform: rotate(90deg); }
body.pv-on .pv-doc-tools { display: none; flex-wrap: wrap; gap: 6px; padding: 8px 2px 2px; }
body.pv-on .pv-doc.is-open .pv-doc-tools { display: flex; }
body.pv-on .pv-doctool {
  display: inline-flex; align-items: center; gap: 6px; padding: 8px 11px;
  border-radius: 999px; border: 1px solid var(--pv-chip-bd); background: transparent;
  color: var(--dv2-text-primary); font-size: 12.5px; font-weight: 600;
  font-family: inherit; cursor: pointer; text-decoration: none;
}
body.pv-on .pv-doctool.danger { color: var(--pv-bad-ink); border-color: var(--pv-bad-ink); }

/* ── The papers the household already had ───────────────────────────────
   Dashed, so a SUGGESTION never looks like a filed fact. Two answers and no
   third: a suggestion that can only be accepted is a decision made for you. */
body.pv-on .pv-adopt {
  margin-top: 12px; padding: 12px; border-radius: 13px;
  border: 1px dashed var(--pv-chip-bd); background: transparent;
}
body.pv-on .pv-adopt-h { display: flex; align-items: center; gap: 8px; }
body.pv-on .pv-adopt-h .pv-ic { color: var(--dv2-link, #5b4fe0); }
body.pv-on .pv-adopt-t { font-size: 13.5px; font-weight: 700; letter-spacing: -.01em; }
body.pv-on .pv-adopt-s {
  font-size: 11.8px; color: var(--dv2-text-sub); margin: 4px 0 0; line-height: 1.45;
}
body.pv-on .pv-adopt-row {
  display: flex; align-items: center; gap: 8px; margin-top: 9px;
  padding: 9px 10px; border-radius: 11px; background: var(--pv-tile-bd);
}
body.pv-on .pv-adopt-n {
  display: block; font-size: 12.8px; font-weight: 600; color: var(--dv2-text-primary);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.pv-on .pv-adopt-w {
  display: block; font-size: 10.5px; color: var(--dv2-text-muted); margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
body.pv-on .pv-mini {
  padding: 7px 12px; border-radius: 999px; font-size: 11.5px; font-weight: 650;
  flex: none; border: 0; cursor: pointer; font-family: inherit;
  background: var(--pv-call-bg); color: var(--pv-call-tx);
}
body.pv-on .pv-mini.ghost {
  background: transparent; color: var(--dv2-text-sub); border: 1px solid var(--pv-chip-bd);
}

/* ── The quiet note — where a section explains itself once ──────────────*/
body.pv-on .pv-note {
  display: flex; gap: 8px; align-items: flex-start; margin-top: 11px;
  padding: 9px 11px; border-radius: 11px; background: var(--pv-quiet-bg);
  font-size: 11.8px; line-height: 1.45; color: var(--dv2-text-sub);
}
body.pv-on .pv-note .pv-ic { width: 14px; height: 14px; margin-top: 2px; color: var(--dv2-text-muted); flex: none; }

/* ── Loading ────────────────────────────────────────────────────────────*/
body.pv-on .pv-loading {
  display: flex; align-items: center; gap: 9px; padding: 12px 0;
  color: var(--dv2-text-sub); font-size: 13.5px;
}
body.pv-on .pv-spin {
  width: 16px; height: 16px; border-radius: 50%; flex: none;
  border: 2px solid currentColor; border-top-color: transparent;
  animation: pv-spin .7s linear infinite;
}
@keyframes pv-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { body.pv-on .pv-spin { animation: none; } }

/* ── The empty section ──────────────────────────────────────────────────*/
body.pv-on .pv-welcome {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: 46px 20px 30px; gap: 6px;
}
body.pv-on .pv-welcome-art {
  width: 92px; height: 92px; border-radius: 50%; display: grid; place-items: center;
  color: var(--dv2-link, #5b4fe0); background: var(--pv-tile-bg);
  border: 1px solid var(--pv-tile-bd); box-shadow: var(--pv-shadow); margin-bottom: 16px;
}
body.pv-on .pv-welcome-art .pv-ic { width: 40px; height: 40px; stroke-width: 1.5; }
body.pv-on .pv-welcome h2 {
  font-size: 24px; font-weight: 700; letter-spacing: -.028em; margin: 0;
  color: var(--dv2-text-primary);
}
body.pv-on .pv-welcome p {
  font-size: 14.5px; line-height: 1.55; color: var(--dv2-text-sub);
  margin: 6px 0 20px; max-width: 30ch;
}
body.pv-on .pv-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 14px 22px; border-radius: 15px; border: 0; cursor: pointer;
  background: var(--dv2-link, #5b4fe0); color: #fff;
  font-size: 15.5px; font-weight: 650; letter-spacing: -.01em; font-family: inherit;
}
body.pv-on .pv-btn.block { width: 100%; }
body.pv-on .pv-btn.ghost {
  background: transparent; color: var(--dv2-text-sub); border: 1px solid var(--pv-chip-bd);
}

/* ═══ THE SHEETS ══════════════════════════════════════════════════════
   Every Pets sheet owns its own header, so none of them wants the shared
   framework's. Scoped to the sheet ids rather than to body.pv-on, because a
   sheet is a child of <body> and the class is on the view. */
#sheet-pv-wizard, #sheet-pv-edit, #sheet-pv-record {
  font-family: inherit;
}
.pv-sheet-head {
  display: flex; align-items: center; gap: 10px; padding: 4px 4px 14px;
}
.pv-sheet-head .pv-grow { flex: 1; min-width: 0; text-align: center; }
.pv-sheet-t {
  font-size: 16.5px; font-weight: 700; letter-spacing: -.02em;
  color: var(--dv2-text-primary, #14102A);
}
.pv-x, .pv-sheet-save {
  width: 38px; height: 38px; border-radius: 50%; flex: none; display: grid;
  place-items: center; border: 0; cursor: pointer; padding: 0;
  background: rgba(120, 120, 128, .12); color: var(--dv2-text-primary, #14102A);
}
.pv-sheet-save { background: var(--dv2-link, #5b4fe0); color: #fff; }
.pv-sheet-save[disabled] { opacity: .5; cursor: default; }

/* The wizard. One question a screen, and the progress bar is the only thing
   that says how much is left — a step counter invites counting. */
.pv-wiz-top { display: flex; align-items: center; gap: 12px; padding: 4px 2px 2px; }
.pv-prog { flex: 1; height: 4px; border-radius: 99px; background: rgba(120,120,128,.2); overflow: hidden; }
/* A bar at 0% is a divider, not a progress bar. The floor is what makes the
   first question read as the first of several rather than as a rule. */
.pv-prog i {
  display: block; height: 100%; min-width: 14px; border-radius: 99px;
  background: var(--dv2-link, #5b4fe0); transition: width .3s ease;
}
@media (prefers-reduced-motion: reduce) { .pv-prog i { transition: none; } }
.pv-wiz-b { padding: 22px 2px 8px; min-height: 240px; }
.pv-wiz-q {
  font-size: 21px; font-weight: 700; letter-spacing: -.026em; line-height: 1.3;
  margin: 0 0 6px; color: var(--dv2-text-primary, #14102A);
}
.pv-wiz-sub { font-size: 13.5px; color: var(--dv2-text-sub, #6a6484); margin: 0 0 18px; }
.pv-chips { display: flex; flex-wrap: wrap; gap: 9px; }
.pv-chip {
  display: inline-flex; align-items: center; gap: 8px; padding: 11px 15px 11px 12px;
  border-radius: 14px; border: 1px solid var(--pv-chip-bd, rgba(20,16,38,.22));
  background: rgba(255,255,255,.5); cursor: pointer; font-family: inherit;
  font-size: 14.5px; font-weight: 600; letter-spacing: -.01em;
  color: var(--dv2-text-primary, #14102A);
}
.pv-chip .pv-ic { width: 18px; height: 18px; color: var(--dv2-text-sub, #6a6484); }
.pv-chip.on { background: var(--dv2-link, #5b4fe0); border-color: var(--dv2-link, #5b4fe0); color: #fff; }
.pv-chip.on .pv-ic { color: #fff; }
html[data-theme="dark"] .pv-chip { background: rgba(255,255,255,.07); }
@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) .pv-chip { background: rgba(255,255,255,.07); }
}
.pv-field {
  width: 100%; padding: 14px 15px; border-radius: 14px;
  border: 1px solid var(--pv-field-bd, rgba(20,16,38,.1));
  background: rgba(255,255,255,.6); color: var(--dv2-text-primary, #14102A);
  font-size: 16px; font-family: inherit; -webkit-appearance: none; appearance: none;
}
html[data-theme="dark"] .pv-field { background: rgba(255,255,255,.07); }
@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) .pv-field { background: rgba(255,255,255,.07); }
}
.pv-field:focus-visible, .pv-chip:focus-visible, .pv-btn:focus-visible,
.pv-mini:focus-visible, .pv-doctool:focus-visible {
  outline: 2px solid var(--dv2-link, #5b4fe0); outline-offset: 2px;
}
/* The objection, beside what it objects to. A message in a bar at the bottom
   of the screen is both far from the field and on top of the button. */
.pv-wiz-warn {
  margin: 10px 0 0; font-size: 13px; font-weight: 600;
  color: var(--pv-bad-ink, #B3312A);
}
.pv-field.bad { border-color: var(--pv-bad-ink, #B3312A); }

.pv-wiz-f { display: flex; gap: 10px; align-items: center; padding: 12px 2px 4px; }
.pv-wiz-skip {
  border: 0; background: none; cursor: pointer; padding: 13px 6px; font-family: inherit;
  font-size: 14.5px; font-weight: 600; color: var(--dv2-text-sub, #6a6484);
}
/* The answers already given, so the flow shows its own progress in content
   rather than only in a bar. */
.pv-done-list { display: flex; flex-direction: column; gap: 5px; padding: 2px 2px 12px; }
.pv-done-row {
  display: flex; align-items: center; gap: 8px; font-size: 12.5px;
  color: var(--dv2-text-sub, #6a6484);
}
.pv-done-row .pv-ic { width: 14px; height: 14px; color: var(--pv-ok-ink, #1F7A52); }
.pv-done-row b { font-weight: 650; color: var(--dv2-text-primary, #14102A); }

/* The wizard's photo step. A big tap target, because it is a photograph. */
.pv-photo-pick {
  width: 100%; aspect-ratio: 3 / 2; border-radius: 18px; cursor: pointer;
  border: 1px dashed var(--pv-chip-bd, rgba(20,16,38,.22)); background: rgba(255,255,255,.4);
  display: grid; place-items: center; align-content: center; gap: 10px;
  color: var(--dv2-text-sub, #6a6484); font-family: inherit; font-size: 14px; font-weight: 600;
  background-size: cover; background-position: center;
}
.pv-photo-pick.has { border-style: solid; color: #fff; }
.pv-photo-pick .pv-ic { width: 30px; height: 30px; }

/* The edit sheet's field stack. */
.pv-form { display: flex; flex-direction: column; gap: 14px; padding: 2px 2px 10px; }
.pv-lab {
  display: block; font-size: 10px; font-weight: 800; letter-spacing: .12em;
  text-transform: uppercase; color: var(--dv2-text-muted, #8a84a3); margin-bottom: 6px;
}
.pv-form-sec {
  font-size: 12.5px; font-weight: 700; letter-spacing: .02em;
  color: var(--dv2-text-sub, #6a6484); margin: 8px 0 -4px;
}
.pv-two { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

/* ── THE AI READ ────────────────────────────────────────────────────────
   IN THE MIDDLE, OVER A SCRIM, WHILE IT HAPPENS. Garage put this in a card
   at the bottom of the screen at b180 and it was still reported as "no
   obvious feedback" — a card below the fold of whatever you are reading is
   easy to miss, and there is nothing useful to do during the read anyway.
   Centred and over a dimmed ground it cannot be missed, and it makes the
   wait legible instead of ambiguous.

   THE STARS ARE THE ANIMATION. A spinner says "busy"; the stars say which
   kind of busy this is, and this is the pattern every AI-driven section
   should use from here. */
.pv-ai-scrim {
  position: fixed; inset: 0; z-index: 300;
  background: rgba(20, 20, 40, .42);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  display: grid; place-items: center;
  padding: calc(env(safe-area-inset-top) + 20px) 20px calc(env(safe-area-inset-bottom) + 20px);
}
.pv-ai {
  position: relative; width: min(320px, 100%); border-radius: 22px;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 26px 22px 32px; text-align: center;
  background: var(--pv-sheet-bg, rgba(255,255,255,.88));
  border: 1px solid var(--pv-tile-bd, rgba(20,16,38,.07));
  -webkit-backdrop-filter: blur(22px) saturate(180%); backdrop-filter: blur(22px) saturate(180%);
  box-shadow: 0 18px 46px rgba(20, 20, 40, .3);
  color: var(--dv2-text-primary, #14102A);
}
.pv-stars { position: relative; width: 54px; height: 54px; color: var(--dv2-link, #5b4fe0); }
.pv-stars svg {
  position: absolute; fill: none; stroke: currentColor;
  stroke-linecap: round; stroke-linejoin: round;
}
.pv-stars .s1 { width: 34px; height: 34px; left: 10px; top: 5px; stroke-width: 1.7;
                animation: pv-puls 1.9s ease-in-out infinite; }
.pv-stars .s2 { width: 17px; height: 17px; left: 33px; top: 28px; stroke-width: 2.1;
                animation: pv-puls 1.9s ease-in-out .38s infinite; }
.pv-stars .s3 { width: 13px; height: 13px; left: 3px; top: 31px; stroke-width: 2.3;
                animation: pv-puls 1.9s ease-in-out .76s infinite; }
@keyframes pv-puls {
  0%, 100% { opacity: .28; transform: scale(.86) rotate(0deg); }
  45%      { opacity: 1;   transform: scale(1.06) rotate(8deg); }
}
.pv-ai .pv-ai-ic { width: 32px; height: 32px; color: var(--pv-ok-ink, #16704A); }
.pv-ai.bad .pv-ai-ic { color: var(--pv-bad-ink, #B3312A); }
.pv-ai-t { font-size: 16.5px; font-weight: 700; letter-spacing: -.02em; }
.pv-ai-s { font-size: 13px; color: var(--dv2-text-sub, #6a6484); line-height: 1.42; }
/* The three states, named on screen so the wait says which part of it you
   are in. "Reading…" alone is indistinguishable from a dead button. */
.pv-ai-steps {
  display: flex; gap: 7px; margin-top: 4px;
  font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--dv2-text-muted, #8a84a3);
}
.pv-ai-steps span { opacity: .35; }
.pv-ai-steps span.on { opacity: 1; color: var(--dv2-link, #5b4fe0); }
.pv-ai-steps span.done { opacity: 1; color: var(--pv-ok-ink, #16704A); }
/* What it actually found, said back in the household's own terms. */
.pv-ai-found {
  margin-top: 6px; padding: 9px 12px; border-radius: 11px;
  background: var(--pv-ok-bg, rgba(31,122,82,.1)); color: var(--pv-ok-ink, #1F7A52);
  font-size: 12px; font-weight: 650; line-height: 1.4;
}
.pv-ai-bar {
  position: absolute; left: 22px; right: 22px; bottom: 14px; height: 4px;
  border-radius: 100px; background: var(--pv-tile-bd, rgba(20,16,38,.07)); overflow: hidden;
}
.pv-ai-bar i {
  display: block; height: 100%; width: 0%; border-radius: 100px;
  background: var(--dv2-link, #5b4fe0); transition: width .25s ease;
}
@media (prefers-reduced-motion: reduce) {
  .pv-stars svg { animation: none; opacity: 1; }
  .pv-ai-bar i { transition: none; }
}

/* ═══ THE SHARED TASK ROW, IN THIS SECTION'S CLOTHES (b210) ═════════════
   Pets draws `.row.tc-row` like Home, School, Garage and Health. Everything
   below is TOKENS ONLY — colour and ground. The grammar, the spacing and the
   type scale belong to the shared row and are not restated here, because
   restating them is exactly how five sections ended up with five rows. */
