/* PROFILE·EDITBABY (1025) — the edit-baby sheet: the form a parent opens from the
 * profile's baby card to change name, sex at birth, due date, date of birth, birth
 * weight and feeding mode, and save it to the babies table.
 * ═══════════════════════════════════════════════════════════════════════════════
 * EXTRACTION, never a redesign (workbench/RULES.md §8). The chosen design is the code
 * that ships today: REPORT-131's spine row (`editBaby`, web/js/views/profile.js:466).
 * The rules below carry the shipped declarations of everything the sheet consumed —
 * the modal scaffold it rendered inside (.modal-overlay :2527 · .modal-sheet :2552 ·
 * .modal-top :2573 · .modal-title :2583 · .modal-close :2590 · .modal-body :2611 ·
 * .modal-foot :2654) and the shared form vocabulary it was drawn with (.error :1691 ·
 * .label :1705 + .modal-body .label :2620 · .input :1716 + .modal-body .input :2635 ·
 * .radio-grid/.radio-tile/.ic :1773-1808 + .modal-body .radio-grid :2650 · .btn :2058
 * + .btn.secondary/.btn.full :2092-2101 + .modal-foot .btn :2664) — plus the sheet's
 * own inline `width: 28px` on the title row's balancing spacer, which the view no
 * longer writes. Identity is pinned by REPORT-256's computed-style + pixel probes,
 * not asserted.
 *
 * ── THE STEM IS RENAMED, NOT REDESIGNED ──
 * Every class the sheet used is shared vocabulary: .modal-* is the scaffold six other
 * profile sheets and chat's two modals render inside, .btn/.label/.input/.error are
 * app-wide, and .radio-grid/.radio-tile are the other steps' and loggers' pick-one.
 * Check 16 gives a class prefix exactly ONE owner (the 238 `wn-`→`wsb-` and 1024
 * `radio-*`→`onbl-*` precedents), so this card owns `peb` and emits
 * peb/peb-sheet/peb-top/peb-close/peb-title/peb-spacer/peb-body/peb-error/peb-label/
 * peb-input/peb-grid/peb-tile/peb-ic/peb-foot/peb-cta with the same anatomy and the
 * same declarations. ⚠️ DO NOT REGISTER A BARE `pe` PREFIX: check 16 resolves ownership
 * by LONGEST matching prefix, so a bare `pe` would claim every `peb-*` rule in this file.
 *
 * ── WHY THE CARD OWNS THE SCAFFOLD (not the 1019 DISCLAIMER carve-out) ──
 * 1019 scoped to `.disclaimer-*` and left `.modal-*` in app.css because the disclaimer
 * HAD its own content vocabulary to carry. This sheet has none: every class it rendered
 * was shared, so a carve-out would leave the card with no stylesheet of its own and its
 * fields styled by a foreign file — the hole D-470 exists to close. The scaffold moves
 * WITH this card; app.css keeps it for the sheets that have not been extracted yet.
 * When those are extracted (MFA 257, activity 258, invite 259, caregiver 260, language
 * 1022), each carries its own declarations the same way, and the scaffold's remaining
 * app.css rules retire when the last consumer moves — consolidation owed at that pass,
 * NOT taken here.
 *
 * ── CARRIED INHERITS (what the sheet received from its host, not from its own rules) ──
 * · font-family / line-height: html,body's var(--font-body) and var(--leading-150) —
 *   carried on the card root, so the sheet reads the same wherever it mounts (the
 *   2026-09-02 `font: inherit` lesson). The INK the sheet's DIVs inherited from the page
 *   is carried on the one element whose text rode it (.peb-tile) rather than the overlay
 *   root: nothing renders on the scrim itself, and a colour declared there hands the
 *   contrast audit a phantom pair (ink against its own translucent background) — the
 *   audit refused the commit over exactly that until the declaration moved.
 * · the app's `button` reset (app.css:130 — font-family: inherit, cursor: pointer,
 *   border: 0, background: transparent, colour inherit) — carried explicitly on every
 *   button this card renders (peb-close, peb-cta).
 * · the app's global focus ring (app.css:43 — 2px accent outline, --focus-offset,
 *   --radius-2) — carried on the two buttons. The tiles carry none: they shipped as
 *   DIVs, are not focusable, and never drew a ring. FOUND, NOT FIXED.
 * · the global input reset (app.css:151 — font-family/size/colour inherit) and its
 *   control-height floor (app.css:157 — min-height 44px on non-checkbox inputs):
 *   carried as font-family: inherit and min-height: var(--control-min).
 * · box-sizing: the app's universal `*` reset (app.css:34) is NOT carried — it is a
 *   page-wide assumption every card in this repo makes. The mirror page loads app.css,
 *   so both sides run the same reset.
 *
 * ── TOKEN SWAPS ──
 * Exact-equal, by construction: app.css's own :root passthrough aliases
 * (--paper-card→--surface-card · --rule→--border-hairline · --ink→--text-primary ·
 * --paper→--surface-ground · --col-max→--layout-col-max · --r-sm→--radius-control ·
 * --r-md→--radius-card · --r-lg→--radius-card-lg — app.css:18-26, tokens.css:525-527);
 * raw 0.15s/0.1s/0.18s easings → --duration-150/--duration-100/--duration-180 +
 * --ease-standard; the 44px close disc → --dim-44; the 28px spacer → --dim-28; the
 * input's 44px floor → --control-min; 50% → --radius-round; 4px radius → --radius-4;
 * the full `border` hairlines and the 1px press → --nudge-1 (the optical token minted
 * for exactly this — D-511 rule 4a; the SIDE-specific border-top/bottom forms are not
 * covered by that rule, so their 1px stays a marked literal); the focus ring's 2px
 * offset → --focus-offset; type with an exact role (11px→--text-label,
 * 16px→--text-body, 13px→--text-caption).
 *
 * ── SHIPPED VALUES WITH NO EXACT TOKEN stay on token-exception markers ──
 * Each is a design ruling owed to Andrew, not taken in an extraction: the 10px tile
 * gap and the 14px/6px field stands (the space ladder is 4/8/12/16…; no 6, 10 or 14
 * exists); the 2px tile hairline; the two side-specific 1px hairlines; the 120px
 * foot-door minimum; the max-height's 0px is --kb-h's runtime FALLBACK, not a design
 * value; and three type sizes that pre-date the D-463 role ladder — the title's 17px
 * (no role is 17; the ladder's neighbours are 16/18), the doors' 15px (--text-body
 * re-anchored 15→16; snapping grows a shipped door label), and the tile glyph's 32px
 * (an emoji glyph, not text — no role carries it).
 * ═════════════════════════════════════════════════════════════════════════════════ */

/* ── the overlay: fixed scrim, sheet anchored to the bottom (phone) / centred (≥600px) ── */
.peb {
  position: fixed;
  inset: 0;
  bottom: var(--kb-h, 0px);
  z-index: 1000;
  background: var(--overlay-scrim);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 0;
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  transition: bottom var(--duration-180) var(--ease-standard);
  /* carried from html,body (app.css:46) — the face and leading every line inherited.
   * The INK is not restated here: nothing renders directly on the scrim, and a colour on
   * the overlay hands the contrast audit a phantom pair (ink on its own translucent
   * background). The one element whose text rode the page's ink declares it — .peb-tile. */
  font-family: var(--font-body);
  line-height: var(--leading-150);
}

@media (min-width: 600px) {      /* token-exception */ /* the shipped breakpoint, carried verbatim — no breakpoint token exists */
  .peb {
    align-items: center;
    padding: var(--space-24);
  }
}

/* ── the sheet (app.css:2552). dvh so the keyboard shrinks the viewport on platforms
 * that report it; --kb-h is the belt-and-braces set at runtime by native.js/util.js,
 * so its 0px FALLBACK stays a literal — it is not a design value. ── */
.peb-sheet {
  background: var(--surface-ground);
  width: 100%;
  max-width: var(--layout-col-max);
  height: auto;
  max-height: calc(100dvh - var(--kb-h, 0px) - var(--space-24)); /* token-exception */
  display: flex;
  flex-direction: column;
  border-top-left-radius: var(--radius-card-lg);
  border-top-right-radius: var(--radius-card-lg);
  box-shadow: var(--shadow-sheet);
  overflow: hidden;
}

@media (min-width: 600px) {      /* token-exception */
  .peb-sheet {
    border-radius: var(--radius-card-lg);
    max-height: 88dvh;
  }
}

/* ── the head row (app.css:2573) ── */
.peb-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-12) var(--space-16);
  border-bottom: 1px solid var(--border-hairline);   /* token-exception */ /* the shipped 1px hairline — the optical tokens stop at plain `border` (D-511 rule 4a allows no side-specific form), so the width stays a literal */
  background: var(--surface-ground);
  flex-shrink: 0;
}

.peb-title {
  font-family: var(--font-display);
  font-size: var(--size-17);                        /* token-exception */ /* 17px shipped — pre-dates the D-463 role ladder; no role is 17 (16 body / 18 subtitle). Snapping moves a shipped sheet title. Ruling owed, not taken */
  font-weight: 500;
  color: var(--text-primary);
}

.peb-close {
  /* the app's `button` reset, carried — this card's taps declare their own text,
   * background, border and cursor instead of riding a page-wide rule (D-470) */
  font-family: inherit;
  color: var(--ink-600);
  cursor: pointer;
  border: 0;
  background: transparent;
  width: var(--dim-44);
  height: var(--dim-44);
  border-radius: var(--radius-round);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--size-22);                        /* token-exception */ /* the × glyph rode .modal-title's ladder neighbour --size-22; no role carries a glyph size. Ruling owed */
  line-height: var(--leading-100);
  transition: background var(--duration-150) var(--ease-standard),
              color var(--duration-150) var(--ease-standard);
}

.peb-close:hover {
  background: var(--surface-card);
  color: var(--text-primary);
}

.peb-close:focus-visible {
  /* the app's global focus ring (app.css:43), restated so the card owns it */
  outline: 2px solid var(--accent);                  /* token-exception */
  outline-offset: var(--focus-offset);
  border-radius: var(--radius-2);
}

/* the title row's balancing spacer — the sheet's own inline `width: '28px'`, which the
 * view used to write. A DIMENSION (how wide the balance is), not a gap: --dim-28. */
.peb-spacer {
  width: var(--dim-28);
}

/* ── the scrolling body (app.css:2611) ── */
.peb-body {
  padding: 14px 20px 16px;          /* token-exception */ /* 14px shipped — no ladder value; 20/16 are --space-20/--space-16. Ruling owed */
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  flex: 1 1 auto;
  min-height: 0;
}

/* ── the failed-save line (.error, app.css:1691) ── */
.peb-error {
  background: var(--white);
  border-left: 3px solid var(--danger);
  padding: 10px 12px;               /* token-exception */ /* 10px/12px shipped — the ladder has no 10. Ruling owed */
  border-radius: var(--radius-4);
  font-size: var(--text-caption);
  color: var(--danger);
  margin-bottom: 14px;              /* token-exception */ /* 14px shipped — no ladder value. Ruling owed */
}

/* ── the field label (.label :1705 + .modal-body .label :2620, merged — inside a modal
 * the modal-scoped rule contributed the 14px stand and the bare rule the 500 weight) ── */
.peb-label {
  display: block;
  font-family: var(--font-label);
  font-size: var(--text-label);
  letter-spacing: var(--tracking-12);
  text-transform: uppercase;
  color: var(--ink-600);
  font-weight: 500;
  margin: 14px 0 6px;               /* token-exception */ /* 14px/6px shipped — the ladder has no 14 or 6. Ruling owed */
}

.peb-body .peb-label:first-child {
  margin-top: 0;
}

/* ── the field (.input :1716 + .modal-body .input :2635 + the app's global input reset,
 * app.css:151/157, merged) ── */
.peb-input {
  display: block;
  width: 100%;
  font-family: inherit;             /* the global input reset, carried — the 2026-09-02 lesson */
  font-size: var(--text-body);      /* 16px+ stops iOS auto-zooming on focus (shipped comment) */
  color: var(--text-primary);
  background: var(--surface-card);
  border: var(--nudge-1) solid var(--border-hairline);
  border-radius: var(--radius-control);
  padding: 12px 14px;               /* token-exception */ /* 14px shipped — no ladder value. Ruling owed */
  min-height: var(--control-min);   /* the global input floor (app.css:157), carried */
  outline: none;                    /* the shipped input keeps its ring off; focus is the accent border alone */
  transition: border-color var(--duration-150) var(--ease-standard);
  margin-bottom: 14px;              /* token-exception */ /* 14px shipped — no ladder value. Ruling owed */
}

.peb-input:focus {
  border-color: var(--accent);
}

.peb-input[type="date"] {
  font-family: var(--font-body);
}

/* ── the pick-one grid (.radio-grid :1773 + .modal-body .radio-grid :2650 — inside a
 * modal the grid's shipped 14px stand tightens to 4px) ── */
.peb-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;                        /* token-exception */ /* 10px shipped — the space ladder is 4/8/12/16…; no --space-10. Snapping moves a shipped tile rhythm: a design ruling owed, not taken (the 238/1024 precedents) */
  margin-bottom: var(--space-4);
}

/* ── the tile (.radio-tile :1784) — shipped as a DIV with onClick, so no button reset
 * applies and none is carried; its label inherits the card root's body face at body size */
.peb-tile {
  background: var(--surface-card);
  border: 2px solid var(--border-hairline);          /* token-exception */ /* 2px hairline border — shipped (.radio-tile); the grid governs layout, not hairlines (238/1024 carried theirs the same way) */
  border-radius: var(--radius-card);
  padding: var(--space-16);
  text-align: center;
  cursor: pointer;
  /* the tile label's ink — html/body's, which the sheet's DIVs inherited from the page
   * (the shipped .radio-tile declares no colour). Declared on the tile, not the overlay
   * root, so the card owns it and the audit reads the real pair: ink on the tile's cream. */
  color: var(--text-primary);
  transition: border-color var(--duration-150) var(--ease-standard),
              background var(--duration-150) var(--ease-standard);
}

.peb-tile:hover {
  border-color: var(--accent);
  background: var(--surface-hover-wash);
}

/* the selected tile — `.on`, set by the renderer, as shipped. The tiles carry no
 * :active and no :focus-visible because the shipped control has none (they are divs,
 * not focusable); their press/selected feedback is the hover/selected colour alone.
 * FOUND, NOT FIXED — an extraction does not invent motion. */
.peb-tile.on {
  border-color: var(--accent);
  background: var(--surface-notice);
}

.peb-ic {
  font-size: var(--size-32);                        /* token-exception */ /* 32px shipped — an emoji glyph, not text; no role carries a glyph size. Ruling owed */
  margin-bottom: var(--space-8);
  display: block;
}

/* ── the foot and its two doors (.modal-foot :2654 + .modal-foot .btn :2664 carrying
 * .btn/.btn.full/.btn.secondary, app.css:2058-2101 — the doors are THIS card's, not
 * app.css's, D-470) ── */
.peb-foot {
  display: flex;
  flex-direction: row-reverse;
  gap: 10px;                        /* token-exception */ /* 10px shipped — no ladder value. Ruling owed */
  padding: var(--space-12) var(--space-16) calc(14px + env(safe-area-inset-bottom)); /* token-exception */ /* 14px shipped inside the calc — no ladder value */
  border-top: 1px solid var(--border-hairline);      /* token-exception */ /* the shipped 1px hairline — see .peb-top */
  background: var(--surface-ground);
  flex-shrink: 0;
}

.peb-cta {
  /* the app's `button` reset, carried (D-470) */
  font-family: var(--font-body);
  cursor: pointer;
  border: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-8);
  font-size: var(--size-15);                        /* token-exception */ /* 15px shipped — .btn's own size, pre-dating the D-463 body floor of 16. No role is 15; snapping grows a shipped door label. Ruling owed, not taken (the 1024 CTA precedent) */
  font-weight: 500;
  padding: 14px 20px;               /* token-exception */ /* 14px/20px shipped — .modal-foot .btn's override of .btn's 12/20 */
  border-radius: var(--radius-pill);
  background: var(--surface-inverse);
  color: var(--text-on-dark);
  width: 100%;                      /* was .btn.full */
  flex: 1;                          /* was .modal-foot .btn */
  transition: transform var(--duration-100) var(--ease-standard),
              opacity var(--duration-150) var(--ease-standard);
}

.peb-cta.secondary {
  background: var(--surface-card);
  color: var(--text-primary);
  border: var(--nudge-1) solid var(--border-hairline);
}

.peb-cta:hover {
  opacity: 0.92;
}

.peb-cta:active {
  transform: translateY(var(--nudge-1));   /* .btn:active's shipped 1px press */
}

.peb-cta:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.peb-cta:focus-visible {
  /* the app's global focus ring (app.css:43), restated so the card owns it */
  outline: 2px solid var(--accent);                  /* token-exception */
  outline-offset: var(--focus-offset);
  border-radius: var(--radius-2);
}

@media (min-width: 600px) {      /* token-exception */
  .peb-cta {
    flex: 0 0 auto;
    min-width: 120px;               /* token-exception */ /* 120px shipped — a door minimum, not a ladder value. Ruling owed */
  }
}
