/* shared/portal-shell.css
 *
 * THE PORTAL SHELL. Step 5 of the MVP build plan, started 30 Aug 2026.
 *
 * WHY THIS IS A STEP OF ITS OWN, having been argued the other way on 21 August.
 * The founder said, looking at a preview: "the family portal looks like the old
 * portal." The answer then was that each screen should be built to the demo as
 * it is reached, and that was wrong. A dashboard is not a screen you reach. It
 * is the FRAME every other screen sits inside, so building the screens first
 * means building them twice.
 *
 * THE REFERENCE IS `_design-preview.html`, which is what was derived from the
 * founder's own mockup at `_design-assets/reference/portal-reference-mockup.png`.
 * The values below are taken from it rather than invented: 48px navigation rows
 * with 24px glyphs, a 40px avatar, the rust tint for the selected row.
 *
 * ── WHY EVERYTHING IS NAMESPACED UNDER .psh ────────────────────────────────
 *
 * The old hibant.css owns THIRTY SEVEN rules that style this shell: .pside,
 * .nitem, .plbl, .pusr, .plog, .pcon, .portal, .portal-tab, .nav-badge. They sit
 * at (0,1,0) and (0,2,0).
 *
 * The footer was fixed by taking its rules OUT of hibant.css, and that was right
 * there because `.fg2` appeared 101 times and every one was inside a <footer>.
 * THIS IS DIFFERENT. The portal is the surface with the least verification
 * behind it: its signed in screens cannot be reached without an account, so a
 * cut here cannot be checked the way the footer's could. Namespacing wins the
 * cascade without removing anything, so if a rule here is wrong the old one is
 * still underneath rather than gone.
 *
 * `.psh .nitem` is (0,2,0) and beats a bare `.nitem`. Where hibant.css already
 * uses (0,2,0), such as `.pside-l .plbl`, the rule here carries a third class so
 * it wins on specificity rather than on load order.
 *
 * ── WHAT IS DELIBERATELY NOT HERE ──────────────────────────────────────────
 *
 * THE CARE BUDGET CARD. The founder's reference draws "My care budget GBP
 * 370.00" on the dashboard. The scope agreed with Chris Watson on 14 Aug puts
 * the budget view in LATER, and he ruled on 30 Aug that the scope stands rather
 * than being widened by a drawing. Nothing in this shell names a figure.
 */

/* ── THE FRAME ─────────────────────────────────────────────────────────────── */

.psh {
  background: var(--page);
  color: var(--t1);
  font-family: var(--font-body);
}

.psh .pcon {
  background: var(--page);
}

/* ── THE SIDEBAR ───────────────────────────────────────────────────────────── */

.psh.pside,
.psh .pside {
  background: var(--surface);
  border-right: 1px solid var(--bd);
  padding: var(--sp-5) 14px;
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* The mark and the word, which the old sidebar did not carry at all: it opened
   on a grey uppercase label. */
.psh .pbrand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 8px var(--sp-4);
}
.psh .pbrand b {
  font-family: var(--font-display);
  font-size: var(--fs-lead);
  font-weight: 600;
  letter-spacing: -.015em;
  color: var(--t1);
}
.psh .pbrand svg { width: 26px; height: 26px; flex: none; }

/* WHO IS SIGNED IN, as a card rather than two loose lines. The name leads and
   the role follows it, which is the reverse of the old order: the label
   "FAMILY & SERVICE USER" came first and the person second. */
/* A CONTROL SINCE 31 Aug 2026, on the founder's instruction: "when you click
   james blake client account it should take you back to the dashboard". It was
   a <div>, so it looked like the most personal thing in the sidebar and did
   nothing when pressed. It carries data-cnav / data-rnav / data-anav, which the
   delegated handler in hibant-app.js already listens for, so no JavaScript
   changed. The inner divs became spans because a <button> may only contain
   phrasing content, and .pusr and .plbl are kept exactly where they were:
   updatePortalUserName() writes to `#pg-client .pusr` and `#pg-* .pav`. */
.psh .pwho {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 11px;
  /* --control-bd, not --bd: the design system's rule is that a CONTROL's edge
     has to be visible enough to read as pressable, and the decorative border is
     not. It was --bd while this was a <div>, which was correct then. The guard
     in test/design-system.test.js caught the change within a minute of it
     becoming a button. */
  border: 1px solid var(--control-bd);
  border-radius: var(--r-md);
  background: var(--card);
  margin-bottom: var(--sp-4);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.psh .pwho:hover { border-color: var(--rust); }
.psh .pwho:focus-visible { outline: 3px solid var(--brand); outline-offset: 2px; }
.psh .pwho__t { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.psh .pav {
  width: 40px; height: 40px; flex: none;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--rust-tint);
  color: var(--rust);
  font-weight: 700;
  font-size: var(--fs-min);
  letter-spacing: .01em;
}
/* .pusr is the NAME and must keep that class inside its #pg-* wrapper:
   updatePortalUserName() in hibant-app.js writes to `#pg-client .pusr`. */
.psh.pside-l .pusr,
.psh .pusr {
  display: block;
  margin: 0;
  font-size: var(--fs-min);
  font-weight: 600;
  line-height: 1.25;
  color: var(--t1);
  text-transform: none;
  letter-spacing: 0;
}
.psh.pside-l .plbl,
.psh .plbl {
  display: block;
  font-size: var(--fs-min);
  color: var(--t3);
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  margin: 0;
  padding: 0;
}

/* ── THE NAVIGATION ────────────────────────────────────────────────────────── */

.psh .pnav {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

/* 48px and a 24px glyph, both from the locked accessibility spec and both what
   the reference draws. The old rows were 44px with an 18px icon. */
.psh.pside-l .nitem,
.psh .nitem {
  display: flex;
  align-items: center;
  gap: 13px;
  width: 100%;
  min-height: var(--tap-min);
  padding: 0 13px;
  border: 1px solid transparent;
  border-radius: 11px;
  background: transparent;
  color: var(--t2);
  font: 600 var(--fs-min)/1.2 var(--font-body);
  text-align: left;
  cursor: pointer;
  margin: 0;
}
.psh .nitem svg { width: 24px; height: 24px; flex: none; }
.psh .nitem:hover:not(.act) { background: var(--card); }

/* SELECTED IS NOT COLOUR ALONE. Tint, ink and a border all change, because the
   locked spec says nothing encodes meaning in hue by itself. */
.psh.pside-l .nitem.act,
.psh .nitem.act {
  background: var(--rust-tint);
  color: var(--rust);
  border-color: var(--rust);
}

/* The unread count. hibant-app.js sets it by id through setBadge() and toggles
   display, so this only styles it. */
.psh .nav-badge {
  position: static;
  transform: none;
  margin-left: auto;
  min-width: 26px;
  height: 26px;
  padding: 0 7px;
  border-radius: 999px;
  background: var(--rust);
  color: #fff;
  font-size: var(--fs-min);
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

/* ── THE FOOT OF THE SIDEBAR ───────────────────────────────────────────────── */

.psh .psidefoot {
  margin-top: auto;
  padding-top: var(--sp-4);
  border-top: 1px solid var(--bd);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.psh.pside-l .plog,
.psh .plog {
  display: flex;
  align-items: center;
  gap: 13px;
  width: 100%;
  min-height: var(--tap-min);
  padding: 0 13px;
  border: 1px solid transparent;
  border-radius: 11px;
  background: transparent;
  color: var(--rust);
  font: 600 var(--fs-min)/1.2 var(--font-body);
  text-align: left;
  cursor: pointer;
  margin: 0;
}
.psh .plog svg { width: 24px; height: 24px; flex: none; }
.psh .plog:hover { background: var(--card); }

/* ── FOCUS ─────────────────────────────────────────────────────────────────── */
/* hibant.css groups .nitem:focus-visible at (0,6,0), which no reasonable
   selector here beats, so this matches that shape rather than fighting it. */
.psh .nitem:focus-visible,
.psh .plog:focus-visible,
.psh .portal-tab:focus-visible {
  outline: 3px solid var(--brand);
  outline-offset: 2px;
}

/* ── THE PHONE TAB BAR ─────────────────────────────────────────────────────── */

.psh .portal-tabs,
.portal-tabs.psh-tabs {
  background: var(--card);
  border-top: 1px solid var(--bd);
}
.portal-tabs.psh-tabs .portal-tab {
  color: var(--t2);
  font-size: var(--fs-min);
  min-height: var(--tap-min);
}
.portal-tabs.psh-tabs .portal-tab.act { color: var(--rust); }
.portal-tabs.psh-tabs .tab-badge {
  background: var(--rust);
  color: #fff;
}

/* ══════════════════════════════════════════════════════════════════════════
   THE SIDEBAR STAYS ON THE SCREEN. Added 31 Aug 2026: "log out is now literally
   too low on the screen."

   WHY IT MOVED WITHOUT ANYBODY MOVING IT. `.portal` is a flex row whose height
   is the taller of the viewport and the content, and the sidebar is a flex
   column that stretches to match. `.psidefoot` uses `margin-top: auto`, so Help
   and support and Log out sit at the bottom of THE COLUMN. While every screen
   fitted the viewport those were the same place. Record grew past it on 31 Aug
   and they went with it, five hundred pixels below the fold, on a bar that never
   scrolls out of the way on any other app.

   So the column is pinned to the viewport and scrolls inside itself if it ever
   has to. `align-self: flex-start` is load bearing: without it the flex row
   stretches this item to the row's height and `position: sticky` has nothing to
   stick within.

   ONLY ABOVE 768px. Below that the portal stacks (`.portal { flex-direction:
   column }` in hibant.css) and the sidebar is a strip across the top, where
   pinning it would cover the screen.
   ══════════════════════════════════════════════════════════════════════════ */

@media (min-width: 769px) {
  .psh.pside,
  .psh .pside {
    position: sticky;
    top: 0;
    align-self: flex-start;
    height: 100vh;
    overflow-y: auto;
  }
}
