/* ════════════════════════════════════════════════════════════
   panel-shell.css — shared chrome for the "panel pages"
   (state, selfless, blocs, coordinate, developmental, …).

   Owns: the flush-left icon rail (.pnav) that widens on hover
   while the panel steps aside, the horizontal panel name that
   sits above the card (.panel-spine), the back button tucked into
   the card's top-left corner (.panel-back), the shared top-right
   action pill (.panel-action), and the relocation of the sitewide
   messenger + gear controls into the rail foot (moved there by nav.js).

   Every rule is scoped under `body[data-shell="panel"]`, so this
   file is a pure additive layer: it out-specifies each page's own
   copy of the shared classes without those copies being deleted.
   Activate per page by linking this AFTER the page stylesheet and
   setting <body data-shell="panel">. Page-specific .panel-card
   visuals stay in the page's own CSS.
   ════════════════════════════════════════════════════════════ */

:root {
  /* Legible Cosmos text scale. Standalone pages retain the same fallback sizes. */
  --lc-1: 12px; --lc-2: 14px; --lc-3: 16px; --lc-4: 20px;
  --lc-5: 26px; --lc-6: 34px; --lc-7: 48px;
  --rail-gap-left:     14px;   /* space between screen edge and the rail */
  --rail-w:            42px;   /* collapsed icon-rail pill width         */
  --rail-w-open:      178px;   /* expanded (hover) pill width            */
  --shell-gutter:      56px;   /* .panel left padding at rest (= gap+rail; pills dock flush) */
  --shell-gutter-open:192px;   /* …while the rail is hovered             */
  --shell-ease: cubic-bezier(.4, 0, .2, 1);
  --shell-fade-rgb: 26, 15, 31;   /* the cosmos base — what the mobile bottom fade resolves to */
}
html[data-theme="light"] { --shell-fade-rgb: 217, 218, 228; }   /* the light page bg (#d9dae4) */

/* ════════════════════════════════════════════════════════════
   PERSISTENT SHELL CHROME — the cosmos backdrop + the rail's base geometry.

   These live OUTSIDE (or survive) the swapped region and must never lose their
   styling mid-navigation. Every page also declares .cosmos in its OWN
   stylesheet. Previously nss-swap disabled the outgoing page's sheet and
   only then enabled/loaded the incoming one — and re-enabling a stylesheet is
   NOT synchronous. So for at least a frame (and far longer on the first visit
   to a domain, while its sheet downloads) .cosmos had no page styling at all:
   the gradient vanished, position collapsed fixed→static, and the starfield
   canvas jumped 0.55→1 opacity with its blend mode lost. That is the
   "background shifting" during a domain switch. Declaring the same values here
   — in a sheet every panel page declares, so preloadCss always keeps it
   enabled — means the backdrop is continuously styled across the swap.

   Specificity is deliberate: these are UNSCOPED (0,1,0), which
   (a) loses to theme-light.css's `html[data-theme="light"] .cosmos` (0,2,1), so
       light mode still wins, and
   (b) ties with each page's own `.cosmos`, resolved by source order — this file
       is linked after the page sheet, and the values are identical anyway.
   Keep these in sync with the page copies; they are duplicated on purpose.
   ════════════════════════════════════════════════════════════ */
/* Root geometry belongs to the persistent shell too. Domain sheets may be
   loading or disabled during navigation; never fall back to the UA body margin.
   The mobile rules below retain document scrolling for long phone pages. */
html:has(body[data-shell="panel"]),
body[data-shell="panel"] {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  height: 100%;
  overflow: hidden;
}

.cosmos {
  position: fixed; inset: 0;
  background:
    linear-gradient(225deg,
      #1a0f1f 0%, #2a1635 22%, transparent 45%,
      transparent 55%, #2a1635 78%, #1a0f1f 100%),
    linear-gradient(225deg,
      #1a0f1f 0%, #2a1635 30%, #3d2050 50%,
      #2a1635 70%, #1a0f1f 100%);
  pointer-events: none;
  z-index: 0;
  overflow: hidden;
}
.cosmos canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  opacity: 0.55;
  mix-blend-mode: screen;
}
/* The rail stays visible through the exit (see .nss-exit below), so its base
   geometry must survive the same gap — without this it briefly reflowed from
   fixed to static. The ≤900px `display:none` and the ≥901px placement rules
   below are scoped (0,2,1) and still out-rank these. */
.pnav {
  position: fixed;
  display: flex;
  flex-direction: column;
}

/* ════════════════════════════════════════════════════════════
   CLIENT-NAV TRANSITION (nss-swap.js) — instant exit, graceful entrance.
   .nss-exit hides the leaving [data-swap] at once (only the rail stays). The
   !important here — plus the fact nss-swap never disables THIS file — also keeps
   a page's opacity:0-only overlays hidden while that page's own stylesheet is
   briefly disabled mid-swap, so no modal text leaks into the gap. .nss-enter then
   fades the incoming panel card in fast ("panel appears") and eases its content
   in slightly slower ("content transitions in"). Both classes are toggled by
   nss-swap.js on [data-swap]; tune the durations below.
   ════════════════════════════════════════════════════════════ */
/* The leaving/incoming content is taken OUT OF LAYOUT (display:none), not just
   made invisible. visibility:hidden still occupies space, and that mattered: the
   incoming page is installed while this class is on, and Chrome applies a
   re-enabled stylesheet ASYNCHRONOUSLY — so for a moment the new markup is
   completely unstyled. Measured on the live site switching to Selfless: all TEN
   .edit-overlay modals rendered as plain blocks, .stage lost position:fixed, and
   the document grew 763px -> 2549px -> 763px. That layout spike is the
   "background hiccup" (a scrollbar appears and vanishes) and the unstyled
   overlays are the "bunch of things that flash before the content".
   display:none contributes no layout and paints nothing, so neither can happen.
   The rail is excluded so it stays put across the swap. */
body[data-shell="panel"] [data-swap].nss-exit > *:not(.pnav) { display: none !important; }

body[data-shell="panel"] [data-swap].nss-enter .panel-card {
  animation: nss-panel-in 150ms ease-out both;
}

/* Selfless's .identity-card is a special case, and it needs BOTH halves below.
   Its page CSS holds it at opacity:0 until its data lands (.is-loaded), and on
   that page the card IS the panel rather than a container inside one.

   1) While still gated it must take NO entrance animation. A CSS animation
      out-ranks the page's opacity:0, so the entrance was forcing the EMPTY
      placeholder card visible for the whole entrance window — literally
      "things flashing before the actual content".
   2) When it does land — during the entrance, or a beat later once its query
      returns — it settles on the SAME curve as all other content, so a late
      arrival reads as one continuous motion instead of a pop. Declared OUTSIDE
      .nss-enter on purpose: the card often arrives after the entrance window
      has already closed, and it should still settle gracefully. */
body[data-shell="panel"] [data-swap].nss-enter .identity-card:not(.is-loaded) { animation: none; }
body[data-shell="panel"] .identity-card.is-loaded {
  animation: nss-content-in var(--nss-in-dur) var(--nss-in-ease) backwards;
}
/* Content SETTLES in — slower and softer than the card, as a gentle two-step
   cascade rather than one flat block, so it arrives like a breath instead of a
   pop. Step 1 is the card's own direct children; step 2 is the blocks nested one
   level in, which is where the real content actually lives (most panels wrap
   everything in a single body div, so a direct-children-only fade reads as one
   solid slab). Also covers Coordinate's Society panel — a full-bleed canvas with
   no .panel-card — and, because .nss-enter lingers (ENTER_CLEANUP_MS in
   nss-swap.js), anything rendered a beat later once its data lands.

   fill = backwards, NOT both: the from-state applies during the delay so nothing
   flashes before it fades, but each element returns to its OWN opacity when the
   entrance ends — intentionally dimmed content (disabled buttons, .locked steps,
   muted rows) is never pinned at full strength.
   Tuning: --nss-in-dur = how slowly content settles; the delays below are the
   cascade. Keep ENTER_CLEANUP_MS >= last delay + duration. */
body[data-shell="panel"] {
  --nss-in-dur: 760ms;
  --nss-in-ease: cubic-bezier(0.22, 1, 0.36, 1);
}
body[data-shell="panel"] [data-swap].nss-enter .panel-card > *,
body[data-shell="panel"] [data-swap].nss-enter .identity-card > *,
body[data-shell="panel"] [data-swap].nss-enter .panel-society > * {
  animation: nss-content-in var(--nss-in-dur) var(--nss-in-ease) 90ms backwards;
}
/* Step 2 — the nested blocks cascade in after their container. */
body[data-shell="panel"] [data-swap].nss-enter .panel-card > * > *,
body[data-shell="panel"] [data-swap].nss-enter .identity-card > * > * {
  animation: nss-content-in var(--nss-in-dur) var(--nss-in-ease) 190ms backwards;
}
body[data-shell="panel"] [data-swap].nss-enter .panel-card > * > *:nth-child(2),
body[data-shell="panel"] [data-swap].nss-enter .identity-card > * > *:nth-child(2) { animation-delay: 280ms; }
body[data-shell="panel"] [data-swap].nss-enter .panel-card > * > *:nth-child(3),
body[data-shell="panel"] [data-swap].nss-enter .identity-card > * > *:nth-child(3) { animation-delay: 370ms; }
body[data-shell="panel"] [data-swap].nss-enter .panel-card > * > *:nth-child(n+4),
body[data-shell="panel"] [data-swap].nss-enter .identity-card > * > *:nth-child(n+4) { animation-delay: 460ms; }
@keyframes nss-panel-in { from { opacity: 0; } to { opacity: 1; } }
/* Pure fade — no vertical movement (Mozhi: "just fade in, no vertical transform"). */
@keyframes nss-content-in { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  body[data-shell="panel"] [data-swap].nss-enter .panel-card,
  body[data-shell="panel"] [data-swap].nss-enter .identity-card,
  body[data-shell="panel"] [data-swap].nss-enter .panel-card > *,
  body[data-shell="panel"] [data-swap].nss-enter .identity-card > *,
  body[data-shell="panel"] [data-swap].nss-enter .panel-society > *,
  body[data-shell="panel"] [data-swap].nss-enter .panel-card > * > *,
  body[data-shell="panel"] [data-swap].nss-enter .identity-card > * > *,
  body[data-shell="panel"] .identity-card.is-loaded { animation: none !important; }
}

/* ── The horizontal section header (big serif title + italic subtitle)
      is retired on panel pages; the panel name now lives on the vertical
      spine instead. Hidden wherever it appears — wrapped in .section-head
      or standalone. Titles that carry real dynamic content (a state's
      name, "X's Blocs") are fed into the spine by the page JS. ── */
body[data-shell="panel"] .section-head:not(.proto-head),
body[data-shell="panel"] .section-title,
body[data-shell="panel"] .section-sub { display: none; }

/* ── Panel name: a small horizontal mono label in the upper-left
      corner of the panel (above the card). ── */
body[data-shell="panel"] .panel-spine > span {
  font-family: var(--f-mono, 'IBM Plex Mono', monospace);
  font-size: var(--lc-1, 12px);
  letter-spacing: 4px;
  text-transform: uppercase;
  color: var(--t4, rgba(255,255,255,0.56));
  white-space: nowrap;
}

/* ── Back button: tucked into the panel-card's top-left corner. It is a
      sibling of the card (not a child), painted over the card's top
      padding band via z-index — so the card's overflow:hidden never clips
      it and it sits clear of the drill-in content that starts below. ── */
body[data-shell="panel"] .panel-back {
  position: absolute;
  top: calc(var(--topbar-h, 72px) + 18px);  /* inside the card's top padding band (mobile geometry) */
  left: 24px;
  z-index: 6;
  font-family: var(--f-mono, 'IBM Plex Mono', monospace);
  font-size: var(--lc-3, 16px);
  letter-spacing: 1.8px;
  text-transform: uppercase;
  color: var(--t3, rgba(255,255,255,0.56));
  background: none;
  border: none;
  padding: 4px 0;
  padding-left: 12px;  /* insets the label from its anchor, matching the spine */
  cursor: pointer;
  transition: transform .24s var(--shell-ease), color .15s;
}
body[data-shell="panel"] .panel-back:hover { color: var(--gold, #f5d87a); }

/* ── Shared top-right action pill (New bloc / Update availability …),
      lifted from blocs' .bl-btn-new. ── */
body[data-shell="panel"] .panel-action {
  position: absolute;
  top: 22px;
  right: 22px;
  z-index: 6;
  font-family: var(--f-mono, 'IBM Plex Mono', monospace);
  font-size: var(--lc-3, 16px);
  font-weight: 500;
  letter-spacing: 2.2px;
  text-transform: uppercase;
  color: var(--gold, #f5d87a);
  background: rgba(245, 216, 122, 0.12);
  border: 1px solid rgba(245, 216, 122, 0.35);
  border-radius: 999px;
  padding: 9px 17px;
  cursor: pointer;
  transition: background .2s, color .2s, border-color .2s, transform .2s;
}
/* Keep touch targets stationary; retain the established mouse affordance. */
@media (min-width: 901px), (hover: hover) and (pointer: fine) {
  body[data-shell="panel"] .panel-action:hover {
    background: rgba(245, 216, 122, 0.22);
    border-color: rgba(245, 216, 122, 0.55);
    color: #fff;
    transform: translateY(-1px);
  }
}

/* ════════════════════════════════════════════════════════════
   DESKTOP / TABLET — the flush-left rail + hover "widen & push".
   At ≤900px the mobile shell (bottom bar) takes over; the rail owns
   ≥901px. This single 900/901 split matches every page's own mobile
   breakpoint (CSS + JS) and nav.js's chrome breakpoint, so there is
   no in-between band where neither the rail nor the bottom bar shows.
   ════════════════════════════════════════════════════════════ */
@media (min-width: 901px) {

  /* Rail container: hugs the panel (not the screen) — a small gap on the
     left, the pills docking against the card's left edge. Vertically
     centered. (Out-specifies the page's .pnav.) */
  body[data-shell="panel"] .pnav {
    left: var(--rail-gap-left);
    top: 50%;
    transform: translateY(-50%);
    gap: 6px;
    padding: 0;
  }

  /* Rail pills: accent-tinted (the page's top-nav section colour, set by
     nav.js as --section-accent-rgb), rounded toward the screen and docking
     square against the panel on the right; compact, icon-only at rest, and
     filled only when selected — more transparent than the top nav itself. */
  body[data-shell="panel"] .pnav-item {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 12px;
    width: var(--rail-w);
    min-width: 0;
    height: 40px;
    padding: 0 0 0 11px;
    overflow: visible;
    white-space: nowrap;
    border: 1px solid rgba(var(--section-accent-rgb, 245,216,122), 0.16);
    border-right-width: 0;
    border-radius: 7px 0 0 7px;
    background: transparent;
    color: rgba(var(--section-accent-rgb, 245,216,122), 0.85);
    cursor: pointer;
    transition: width .24s var(--shell-ease), background .15s, border-color .15s, color .15s;
  }

  /* Rail icons a touch smaller (the rail is tighter now). */
  body[data-shell="panel"] .pnav-icon { width: 20px; height: 20px; flex-shrink: 0; }

  /* Labels hidden until the rail is hovered. */
  body[data-shell="panel"] .pnav-label {
    overflow: hidden;
    font-family: var(--f-mono, 'IBM Plex Mono', monospace);
    font-size: var(--lc-1, 12px);
    letter-spacing: 2.2px;
    text-transform: uppercase;
    opacity: 0;
    transition: opacity .18s .04s;
  }

  /* Hover the rail → every pill widens in place; labels fade in. */
  body[data-shell="panel"] .pnav:hover .pnav-item { width: var(--rail-w-open); }
  body[data-shell="panel"] .pnav:hover .pnav-label { opacity: 1; }

  body[data-shell="panel"] .pnav-item:hover {
    background: rgba(var(--section-accent-rgb, 245,216,122), 0.10);
    border-color: rgba(var(--section-accent-rgb, 245,216,122), 0.30);
    color: rgba(var(--section-accent-rgb, 245,216,122), 1);
  }
  body[data-shell="panel"] .pnav-item.active {
    background: rgba(var(--section-accent-rgb, 245,216,122), 0.20);
    border-color: rgba(var(--section-accent-rgb, 245,216,122), 0.45);
    color: rgba(var(--section-accent-rgb, 245,216,122), 1);
  }

  /* A 12px notification dot sits 1px left of the 1px border's center:
     -1.5px from the padding edge, at half the item's height. */
  body[data-shell="panel"] .pnav-item { position: relative; }
  body[data-shell="panel"] .pnav-item > .nss-panel-notice-dot,
  body[data-shell="panel"] .pnav-item > .stodo-notification-dot,
  body[data-shell="panel"] .pnav-badge {
    position: absolute;
    top: 50%;
    left: -1.5px;
    right: auto;
    transform: translate(-50%, -50%);
    width: 12px;
    min-width: 12px;
    height: 12px;
    padding: 0;
    margin: 0;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(var(--section-accent-rgb, 245,216,122), 0.5);
    color: #fff;
    font-family: var(--f-mono, 'IBM Plex Mono', monospace);
    font-size: 0;
    font-weight: 700;
    line-height: 1;
    z-index: 2;
    pointer-events: none;
  }
  body[data-shell="panel"] .pnav-item > .nss-panel-notice-dot[hidden],
  body[data-shell="panel"] .pnav-item > .stodo-notification-dot[hidden],
  body[data-shell="panel"] .pnav-badge:empty,
  body[data-shell="panel"] .pnav-badge[hidden] { display: none; }

  /* Top-right control is the messenger (it takes the prominent corner where
     the gear used to be, keeping its rounded nav chrome). The gear/settings
     moves to the bottom-left with the same rounded interaction area. Both keep the nav's
     native z-index 1000, so they sit above page content. */
  body[data-shell="panel"] .nss-msg-link {
    top: 12px;
    right: 80px;
    left: auto;
    bottom: auto;
  }

  body[data-shell="panel"] .nss-profile-menu {
    top: auto;
    right: auto;
    left: 8px;
    bottom: 16px;
  }
  body[data-shell="panel"] .nss-profile-trigger svg { width: 24px; height: 24px; }
  /* The dropdown now opens UPWARD from the bottom-left icon. */
  body[data-shell="panel"] .nss-profile-dropdown {
    top: auto;
    bottom: calc(100% + 8px);
    left: 0;
    right: auto;
  }

  /* The panel makes room for the expanded rail while its labels appear. */
  body[data-shell="panel"] .panel {
    padding-left: var(--shell-gutter);
    transition: padding-left .24s var(--shell-ease);
  }
  body[data-shell="panel"]:has(.pnav:hover) .panel {
    padding-left: var(--shell-gutter-open);
  }

  /* Panel name: anchored at the open position, translated back at rest. */
  body[data-shell="panel"] .panel-spine {
    position: absolute;
    left: var(--shell-gutter-open);
    top: calc(var(--topbar-h, 72px) - 24px);
    z-index: 6;
    pointer-events: none;
    transform: translateX(calc(var(--shell-gutter) - var(--shell-gutter-open)));
    transition: transform .24s var(--shell-ease);
    padding-left: 20px;
  }
  body[data-shell="panel"]:has(.pnav:hover) .panel-spine { transform: translateX(0); }

  /* Back button follows the expanding panel gutter. */
  body[data-shell="panel"] .panel-back {
    top: calc(var(--topbar-h, 72px) + 8px);
    left: calc(var(--shell-gutter-open) + 8px);
    transform: translateX(calc(var(--shell-gutter) - var(--shell-gutter-open)));
  }
  body[data-shell="panel"]:has(.pnav:hover) .panel-back { transform: translateX(0); }
}

/* ════════════════════════════════════════════════════════════
   NUMERALS — lining + tabular figures. The large stat numbers render
   in Cormorant (--f-serif) / Bebas (--f-display), whose figures read
   as letters ("1 / 0 / 0" → "I / O / O"). Force unambiguous lining,
   tabular digits everywhere a count is shown. Also exposed as the
   .nss-nums utility for any new stat element.
   ════════════════════════════════════════════════════════════ */
body[data-shell="panel"] .tm-stat-num,
body[data-shell="panel"] .dev-stat-num,
body[data-shell="panel"] .dev-hero-num,
body[data-shell="panel"] .dev-metric-num,
body[data-shell="panel"] .dev-mini-num,
body[data-shell="panel"] .bl-stat-num,
body[data-shell="panel"] .promise-stat-num,
body[data-shell="panel"] .promise-open-count,
body[data-shell="panel"] .home-promise-num,
body[data-shell="panel"] .mp-stat-num,
body[data-shell="panel"] .nss-nums {
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "lnum" 1, "tnum" 1;
}

/* ════════════════════════════════════════════════════════════
   LEVEL 3 — sticky underline sub-section tabs (.subtabs / .subtab).
   A single horizontal row of text tabs that pins to the top of the
   viewport once scrolled past the header. Active = section accent with
   a 2px accent underline; inactive = muted. Overflows by horizontal
   scroll (one row, never wraps). Reusable on any panel.
   ════════════════════════════════════════════════════════════ */
body[data-shell="panel"] .subtabs {
  position: sticky;
  top: 0;
  z-index: 7;
  display: flex;
  gap: 26px;
  align-items: stretch;
  margin: 0 0 14px;
  padding: 2px 2px 0;
  border-bottom: 0.5px solid var(--b2, rgba(255, 255, 255, 0.14));
  background: transparent;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}
body[data-shell="panel"] .subtabs::-webkit-scrollbar { display: none; height: 0; }
body[data-shell="panel"] .subtab {
  flex: 0 0 auto;
  padding: 10px 0;
  margin-bottom: -1px;
  font-family: var(--f-ui, 'Inter', system-ui, sans-serif);
  font-size: var(--lc-3, 16px);
  line-height: 1;
  color: var(--t3, rgba(255, 255, 255, 0.56));
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.15s;
}
body[data-shell="panel"] .subtab:hover { color: var(--t2, rgba(255, 255, 255, 0.72)); }
body[data-shell="panel"] .subtab.active {
  font-weight: 400;
  color: rgb(var(--section-accent-rgb, 245, 216, 122));
  border-bottom-color: rgb(var(--section-accent-rgb, 245, 216, 122));
}
body[data-shell="panel"] .subtab-badge {
  margin-left: 7px;
  color: rgb(var(--section-accent-rgb, 245, 216, 122));
  font-variant-numeric: tabular-nums lining-nums;
}

/* ════════════════════════════════════════════════════════════
   MOBILE (≤900px) — the mobile nav shell.
   Unwinds the fixed desktop "deck" so the document scrolls, hides the
   spine, and turns each page's own .pnav into the shared stable bottom
   SECTION bar (Level 2). Same 900px breakpoint every page already uses
   (CSS + JS), so the bottom bar and the desktop rail meet at 900/901
   with no gap. (nav.js switches the top chrome to the domain rail +
   messages + gear cluster at this same breakpoint.)
   ════════════════════════════════════════════════════════════ */
@media (max-width: 900px) {
  :root {
    --shell-mobile-gutter: 16px;
    --shell-mobile-gap: 16px;
    --shell-mobile-nav-size: 44px;
    /* Rail top + icon + notification count (3px gap + 10px line) + air.
       Bottom bar = 48px control + 12px padding + 1px border + safe area. */
    --shell-mobile-top: calc(env(safe-area-inset-top, 0px) + 6px + var(--shell-mobile-nav-size) + 13px + var(--shell-mobile-gap));
    --shell-mobile-bottom: calc(61px + env(safe-area-inset-bottom, 0px) + var(--shell-mobile-gap));
  }
  /* Let the document scroll (kill the fixed-stage deck). */
  html:has(body[data-shell="panel"]),
  body[data-shell="panel"] {
    height: auto;
    overflow-x: hidden;
    overflow-y: auto;
  }
  html:has(body[data-shell="panel"]) {
    scroll-padding-top: var(--shell-mobile-top);
    scroll-padding-bottom: var(--shell-mobile-bottom);
  }
  body[data-shell="panel"] .stage {
    position: static;
    height: auto;
    overflow: visible;
    scroll-snap-type: none;
    padding-bottom: 0;
  }
  body[data-shell="panel"] .panel {
    height: auto;
    min-height: 100vh;
    min-height: 100svh;
    /* Shell spacing must beat page ID rules and fixed to-do overrides.
       Keep the padding inside the existing scroll owner, including at edges. */
    padding: var(--shell-mobile-top) var(--shell-mobile-gutter) var(--shell-mobile-bottom) !important;
    scroll-padding-top: var(--shell-mobile-top);
    scroll-padding-bottom: var(--shell-mobile-bottom);
    scroll-snap-align: none;
    /* Fill the screen: the panel is a flex column so its card can grow to
       occupy the full viewport content box below the top nav band. Per-page
       CSS then makes the RIGHT inner region grow / scroll / center so the
       height reads as intentional rather than a short card with a dead gap
       below. Panels still exceed one screen when an inner region overflows
       (it scrolls internally). */
    display: flex;
    flex-direction: column;
  }
  /* The card is the growing flex child. The min-height makes it fill the
     viewport content box (100svh minus the ~68px top nav band) EVEN on pages
     whose own mobile CSS sets the panel to min-height:0 via an id selector
     (which out-specifies the .panel rule above) — so the fill is robust
     regardless of per-page panel rules. The card still grows past this when
     content is taller. Society (#society) has no .panel-card; its canvas is
     position:absolute inset:0 and fills anyway. */
  body[data-shell="panel"] .panel > .panel-card,
  body[data-shell="panel"] .panel > .identity-card {
    flex: 1 1 auto;
    min-height: calc(100svh - var(--shell-mobile-top) - var(--shell-mobile-bottom));
  }
  body[data-shell="panel"] .panel-spine { display: none; }

  /* ── Bottom fade: content dissolves into the cosmos toward the viewport
        bottom (the desktop rail panels' fade quality). Slimmed now that no
        bottom bar reserves space beneath it. ── */
  body[data-shell="panel"]::after {
    content: "";
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: calc(48px + env(safe-area-inset-bottom));
    background: linear-gradient(
      to top,
      rgb(var(--shell-fade-rgb)) 0%,
      rgb(var(--shell-fade-rgb)) 30%,
      rgba(var(--shell-fade-rgb), 0) 100%
    );
    pointer-events: none;
    z-index: 850;
  }

  /* ── The bottom section bar is GONE (R9, stage 3): home panels +
        drill-ins (panel-home.js) are the mobile section navigation.
        The .pnav rail is data only — panel-home.js reads its items
        (labels, badges, conditional visibility) to build the home index. ── */
  body[data-shell="panel"] .pnav { display: none; }

  /* ── Level 4: back button on pushed detail views — top-left,
        clear of the card's top padding band (still a sibling painted
        over the card so overflow:hidden never clips it). ── */
  body[data-shell="panel"] .panel-back {
    top: calc(var(--topbar-h, 72px) - 6px);
    left: 16px;
  }

  /* ════════════════════════════════════════════════════════════
     HOME PANEL + DRILL-IN (panel-home.js, stage 3 — D5/R9).
     body[data-phome="home"]: the stage hides, the index shows.
     body[data-phome="drill"]: only the .phome-show panel renders.
     Both states exist ONLY ≤900px — panel-home deactivates on desktop.
  ════════════════════════════════════════════════════════════ */
  /* !important is deliberate and load-bearing: page CSS addresses panels by
     ID (#identity, #time… in selfless.css ≤900) which out-specifies any
     class chain — the home/drill mode toggle must beat arbitrary page rules
     or drilling on those pages shows every panel stacked. */
  body[data-phome] .stage .panel { display: none !important; }
  body[data-phome="drill"] .stage .panel.phome-show { display: flex !important; }
  body[data-phome="home"] .stage { display: none !important; }

  body[data-shell="panel"] .phome {
    display: flex;
    flex-direction: column;
    gap: 24px;
    /* Top-anchored with a band below the domain rail so the demo line +
       animation clear the menu. The animations themselves are tall enough to
       push the section buttons down (~3½ show on landing, scroll for the rest);
       buttons flow ~24px under the stats. Bottom pad clears the app bar. */
    padding: var(--shell-mobile-top) var(--shell-mobile-gutter) var(--shell-mobile-bottom);
    min-height: 100svh;
    box-sizing: border-box;
  }
  /* Zero the visual's bottom margin so the stats-to-buttons distance is just
     the .phome gap above (overrides the base rule from panel-home.js). */
  body[data-shell="panel"] .phome-visual { margin: 2px auto 0; }
  /* The active domain + glyph already show in the top rail, so a glance header
     that carries only the domain label is redundant and just adds space between
     the stats and buttons — hide it. Keep the glance where it carries a real
     title (State sets the state name via __nssHomeMeta). */
  body[data-phome="home"] .phome-glance:not(:has(.phome-title)) { display: none; }
  /* State's mobile home leads with the tall chart/image hero; the glance header
     (state name + mission) just opened a gap between the hero and the section
     buttons. Drop it on State and let the hero grow to fill (panel-visuals
     state.js), so the buttons land right under the stats. */
  body[data-shell="panel"][data-nav-key="states"] .phome-glance { display: none; }
  body[data-phome="drill"] .phome { display: none; }

  body[data-shell="panel"] .phome-glance {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 6px 4px 0;
  }
  body[data-shell="panel"] .phome-glyph {
    width: 44px;
    height: 44px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 12px;
    background: rgba(var(--section-accent-rgb, 245, 216, 122), 0.12);
    color: rgb(var(--section-accent-rgb, 245, 216, 122));
  }
  body[data-shell="panel"] .phome-glyph svg { width: 26px; height: 26px; }
  body[data-shell="panel"] .phome-domain {
    font-family: var(--f-mono, 'IBM Plex Mono', monospace);
    font-size: var(--lc-3, 16px);
    letter-spacing: 3px;
    text-transform: uppercase;
    color: var(--t4, rgba(255, 255, 255, 0.56));
  }
  body[data-shell="panel"] .phome-title {
    font-size: var(--lc-4, 20px);
    font-weight: 650;
    color: var(--t1, rgba(255, 255, 255, 0.95));
    line-height: 1.2;
  }
  body[data-shell="panel"] .phome-sub {
    font-size: var(--lc-3, 16px);
    color: var(--t3, rgba(255, 255, 255, 0.56));
    line-height: 1.35;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  body[data-shell="panel"] .phome-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 10px;
  }
  /* Single-column rows: icon on the left, section name to its right
     (SITE_UPDATE_PLAN Thread B). Badge/dot sit centred at the far right,
     so the card reserves right padding to keep the label clear of them. */
  body[data-shell="panel"] .phome-card {
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
    position: relative;
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 14px;
    min-height: 62px;
    padding: 14px 44px 14px 16px;
    border-radius: 16px;
    background: rgba(255, 255, 255, 0.035);
    border: 0.5px solid var(--b1, rgba(255, 255, 255, 0.08));
    color: var(--t2, rgba(255, 255, 255, 0.72));
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    transition: border-color 0.15s, background 0.15s;
  }
  body[data-shell="panel"] .phome-card:active {
    background: rgba(var(--section-accent-rgb, 245, 216, 122), 0.10);
    border-color: rgba(var(--section-accent-rgb, 245, 216, 122), 0.30);
  }
  body[data-shell="panel"] .phome-card-ic {
    color: rgb(var(--section-accent-rgb, 245, 216, 122));
  }
  body[data-shell="panel"] .phome-card-ic svg { width: 22px; height: 22px; display: block; }
  body[data-shell="panel"] .phome-card-ic:empty { display: none; }
  body[data-shell="panel"] .phome-card-lb {
    font-size: var(--lc-3, 16px);
    font-weight: 500;
    color: var(--t1, rgba(255, 255, 255, 0.92));
  }
  body[data-shell="panel"] .phome-card.phome-locked {
    opacity: 0.42;
    cursor: default;
  }
  /* Sibling-section footer at the bottom of a drilled panel: the domain's
     OTHER sections as cards (same look as the home index), so you can hop
     without going back up. Rendered by panel-home's renderSiblings(). */
  body[data-shell="panel"] .phome-siblings {
    /* Mobile panel links always fill their content column, even in centered panels. */
    align-self: stretch;
    width: auto;
    min-width: 0;
    max-width: none;
    box-sizing: border-box;
    margin: 36px 0 0;
    padding-top: 20px;
    border-top: 0.5px solid var(--b1, rgba(255, 255, 255, 0.08));
    display: flex;
    flex-direction: column;
    gap: 10px;
  }
  body[data-shell="panel"] .phome-siblings-t {
    font-family: 'IBM Plex Mono', ui-monospace, monospace;
    font-size: var(--lc-3, 16px);
    letter-spacing: 2px;
    text-transform: uppercase;
    color: var(--t3, rgba(255, 255, 255, 0.56));
    margin: 0 2px 2px;
  }
  body[data-shell="panel"] .phome-sibling {
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 14px;
    min-height: 56px;
    padding: 12px 16px;
    border-radius: 16px;
    background: rgba(255, 255, 255, 0.035);
    border: 0.5px solid var(--b1, rgba(255, 255, 255, 0.08));
    color: var(--t1, rgba(255, 255, 255, 0.92));
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s;
  }
  body[data-shell="panel"] .phome-sibling:active {
    background: rgba(var(--section-accent-rgb, 245, 216, 122), 0.10);
    border-color: rgba(var(--section-accent-rgb, 245, 216, 122), 0.30);
  }
  body[data-shell="panel"] .phome-sibling svg {
    width: 22px; height: 22px; flex: 0 0 auto; display: block;
    color: rgb(var(--section-accent-rgb, 245, 216, 122));
  }
  body[data-shell="panel"] .phome-sibling span { font-size: var(--lc-3, 16px); font-weight: 500; }
  body[data-shell="panel"] .phome-badge {
    position: absolute;
    top: 50%;
    right: 14px;
    transform: translateY(-50%);
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 9px;
    background: #fb7185;
    color: #fff;
    font-family: var(--f-ui, 'Inter', system-ui, sans-serif);
    font-size: var(--lc-3, 16px);
    font-weight: 700;
    line-height: 1;
  }
  body[data-shell="panel"] .phome-badge[hidden] { display: none; }
  /* stage-4 slot: painted by the unified notices loader, dormant now */
  body[data-shell="panel"] .phome-dot {
    position: absolute;
    top: 50%;
    right: 14px;
    transform: translateY(-50%);
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: rgb(var(--section-accent-rgb, 245, 216, 122));
  }
  body[data-shell="panel"] .phome-dot[hidden] { display: none; }

  /* Drill-in back chip: in-flow at the top of the stage so it can never
     collide with fixed chrome; the drilled panel renders directly below. */
  body[data-shell="panel"] .phome-back {
    display: none;
    align-items: center;
    gap: 8px;
    margin: 60px 14px -56px;
    padding: 8px 14px;
    width: max-content;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.05);
    border: 0.5px solid var(--b1, rgba(255, 255, 255, 0.10));
    color: var(--t2, rgba(255, 255, 255, 0.72));
    font-family: var(--f-ui, 'Inter', system-ui, sans-serif);
    font-size: var(--lc-3, 16px);
    cursor: pointer;
    position: relative;
    z-index: 10;
  }
  body[data-phome="drill"] .phome-back { display: inline-flex; }
}

@media (max-width: 360px) {
  :root { --shell-mobile-nav-size: 37px; }
}

/* Home artifacts must never leak to desktop: the module deactivates >900px,
   and this belt keeps any residue invisible even mid-resize. */
@media (min-width: 901px) {
  body[data-shell="panel"] .phome,
  body[data-shell="panel"] .phome-back { display: none; }
}

/* ── Light mode: the rail sits at full accent strength ────────────────
   The rail pills take their colour from --section-accent-rgb, which nav.js
   already sets to each domain's LIGHT accent (#be185d for coordinate, the
   same value the top nav gives that section). The hue was never wrong — the
   rest state just drew it at 0.85 alpha.

   That softening is a dark-page instinct: on black the accents are bright
   pastels and 85% keeps an inactive pill from shouting. In light the accents
   are already dark inks, so the same 85% only fades them toward the page and
   the rail reads washed next to the nav it is meant to match.

   Rest goes to full strength. Hover and active already sat at alpha 1, so
   this closes the gap between them rather than changing what they do.

   Inside the same min-width the rail itself lives in, and derived from the
   section token — so every domain's rail firms up in its own colour, not in
   coordinate's pink. */
@media (min-width: 901px) {
  html[data-theme="light"] body[data-shell="panel"] .pnav-item {
    color: rgb(var(--section-accent-rgb, 190, 24, 93));
  }
}

/* ── Light: the home rows need their edge to actually carry them ──────
   Measured on the mobile home: the row's fill is white at 3.5%, which on the
   #d9dae4 page composites to 1.01:1 — indistinguishable from the page. So
   unlike the cards elsewhere, where the fill helps a little and the border
   finishes the job, here the border is doing ONE HUNDRED PERCENT of the work
   of saying "this is a row".

   And it was the weakest border in the app: --b1 (8% ink) at 0.5px, measuring
   1.20:1. Thinner and fainter than anything else, while carrying more.

   Goes to 1px at 0.14 ink — 1.33:1, the same figure the readout tier reaches
   on every other card, so the rows are defined to the same standard rather
   than to a new one. The fill is deliberately left alone: with the edge
   carrying the definition, lifting the wash as well would make these read as
   panels rather than as list rows.

   Inside the same max-width the rows live in. */
@media (max-width: 900px) {
  /* Owner correction, 2026-10-13: every panel footer uses the Home
     directory's gray outline. Keep existing domain-specific pressed colors. */
  html[data-theme="light"] body[data-shell="panel"] .phome-sibling {
    border-width: 1px;
  }
  html[data-theme="light"] body[data-shell="panel"] .phome-sibling:not(:active) {
    border-color: rgba(17, 17, 27, 0.14);
  }
  html[data-theme="light"] body[data-shell="panel"] .phome-card {
    border-width: 1px;
    border-color: rgba(17, 17, 27, 0.14);
  }
  /* The pressed state has to be restated. Adding html[data-theme] to the rest
     rule lifts it to (0,3,2), which outranks the unscoped :active at (0,3,1)
     — so without this the row would keep its resting edge when tapped and
     lose the accent entirely. Same trap that cost the availability blocks
     their gold. The accent still comes from the section token, so each domain
     presses in its own colour. */
  html[data-theme="light"] body[data-shell="panel"] .phome-card:active {
    border-color: rgba(var(--section-accent-rgb, 190, 24, 93), 0.45);
  }
}

/* Match the exact inverse of panel-home's mobile query, including fractional
   widths. Hide stale mobile footers immediately, even before resize cleanup
   runs in a background tab or when an older script is still cached. */
@media not all and (max-width: 900px) {
  body[data-shell="panel"] .phome-siblings { display: none !important; }
}

/* Setup reminders use the existing rail and phone panel buttons. */
.stodo-notification-dot {
  display:inline-block; flex:none; width:8px; height:8px; border-radius:50%;
  background:#dc2626; margin-left:8px;
}
.stodo-notification-dot[hidden] { display:none; }
/* Use the shared middle-right position while counts load (and for local
   setup reminders). Once the shared dot is visible, show only that dot. */
.phome-card > .stodo-notification-dot {
  position:absolute; top:50%; right:14px; transform:translateY(-50%);
  width:7px; height:7px; margin-left:0;
}
.phome-card > .phome-dot:not([hidden]) ~ .stodo-notification-dot { display:none; }
/* Desktop setup reminders share the domain-colored rail dot rule above. */


/* Home notifications use the existing reading column as the scroll owner.
   Cards fill that column; mobile retains the page's normal side gutters. */
body[data-shell="panel"] .nss-home-notifications {
  display: grid; gap: 14px; width: 100%; min-width: 0;
}
body[data-shell="panel"] .nss-home-notifications:empty { display: none; }
body[data-shell="panel"] .nss-home-notification {
  min-width: 0; padding: 20px; border: 1px solid var(--b2, rgba(255,255,255,.2));
  border-radius: 16px;
  background: linear-gradient(135deg, rgba(var(--section-accent-rgb, 255,255,255), .045), rgba(var(--section-accent-rgb, 255,255,255), .005));
  border-color: rgba(var(--section-accent-rgb, 255,255,255), .18);
  color: var(--t1); overflow-wrap: anywhere;
}
body[data-shell="panel"] .nss-home-notification.is-new {
  background: rgba(var(--section-accent-rgb, 245,216,122), .1);
  border-color: rgba(var(--section-accent-rgb, 245,216,122), .45);
}
body[data-shell="panel"] .nss-home-notification-heading { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px 12px; }
body[data-shell="panel"] .nss-home-notification-new {
  padding: 2px 8px; border: 1px solid currentColor; border-radius: 999px;
  font: 500 var(--lc-2, 14px)/1.4 var(--f-ui, sans-serif); color: var(--t1);
}
body[data-shell="panel"] .nss-home-notification-kind {
  margin: 0 0 8px; font: 500 var(--lc-3, 16px)/1.5 var(--f-mono, monospace); letter-spacing: .08em;
}
body[data-shell="panel"] .nss-home-notification h3 { margin: 0; font: 400 var(--lc-4, 20px)/1.4 var(--f-serif, serif); }
body[data-shell="panel"] .nss-home-notification-body { margin: 10px 0 0; font-size: var(--lc-3, 16px); line-height: 1.5; color: var(--t2); }
body[data-shell="panel"] .nss-home-notification .nss-attention-actions { display: flex; align-items: stretch; flex-wrap: nowrap; gap: 8px; margin-top: 16px; }
body[data-shell="panel"] .nss-home-notification button,
body[data-shell="panel"] .nss-home-notifications-error button {
  min-height: 44px; padding: 10px 16px; border: 1px solid var(--b2, currentColor);
  border-radius: 10px; background: transparent; color: inherit; font: inherit; cursor: pointer;
}
body[data-shell="panel"] .nss-home-notification [data-attention-open] {
  background: rgb(var(--section-accent-rgb, 245,216,122));
  border-color: transparent; color: #1a0f1f;
}
html[data-theme="light"] body[data-shell="panel"] .nss-home-notification [data-attention-open] { color: #fff; }
body[data-shell="panel"] .nss-home-notification button:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }
body[data-shell="panel"] .nss-home-notification button:disabled { opacity: .6; cursor: wait; }
body[data-shell="panel"] .nss-home-notification [hidden] { display: none; }
body[data-shell="panel"] .nss-home-notification-feedback { margin: 8px 0 0; font-size: var(--lc-3, 16px); line-height: 1.5; }
body[data-shell="panel"] .nss-home-notification-feedback:empty { margin: 0; }
/* Selflessness keeps the complete identity illustration above Home notices.
   Its existing card is the sole content scroll owner; no extra list scroller. */
@media (min-width: 901px) {
  body[data-nav-key="selfless"] #identity > .identity-card:has(#selflessHomeNext .nss-home-notification),
  body[data-nav-key="selfless"] #identity > .identity-card:has(#selflessHomeNext .nss-home-notifications-error) {
    overflow-y: auto; min-height: 0;
  }
  body[data-nav-key="selfless"] #identity > .identity-card:has(#selflessHomeNext .nss-home-notification) > .identity-grid,
  body[data-nav-key="selfless"] #identity > .identity-card:has(#selflessHomeNext .nss-home-notifications-error) > .identity-grid {
    /* Viewport minus topbar, 32px panel bottom padding and 2px card border. */
    flex: 0 0 auto; height: calc(100vh - var(--topbar-h, 72px) - 34px);
  }
  body[data-nav-key="selfless"] #selflessHomeNext:has(.nss-home-notification),
  body[data-nav-key="selfless"] #selflessHomeNext:has(.nss-home-notifications-error) {
    flex: 0 0 auto; padding: 24px; width: 100%;
  }
}
@media (max-width: 900px) { #selflessHomeNext { display: none; } }
/* The fixed cosmos backdrop occupies layer 0; keep mobile notices above it. */
body[data-shell="panel"] .phome-notifications { position: relative; z-index: 1; width: 100%; margin-bottom: 14px; }
@media (min-width:901px) {
  /* Desktop Home introductions match Coordinate and State.
     Keep the phone directory's markup/styles independent. */
  body[data-shell="panel"] :is(.coord-home-copy, .blocs-home-copy, .dev-home-placeholder) {
    padding: 0 0 24px;
    border-top: 0;
    border-bottom: 1px solid var(--b2);
  }
  body[data-shell="panel"] :is(.coord-home-kicker, .blocs-home-kicker, .dev-home-placeholder-kicker) {
    margin: 0;
    font: 400 34px/1.15 var(--f-serif, 'Cormorant Garamond', serif);
    letter-spacing: 0;
    text-transform: none;
  }
  body[data-shell="panel"] :is(.coord-home-intro, .blocs-home-intro, .dev-home-placeholder-copy) {
    margin: 8px 0 0;
    max-width: none;
    font: 400 16px/1.5 var(--f-ui, Inter, sans-serif);
    letter-spacing: normal;
    color: var(--t2);
  }
  body[data-shell="panel"] :is(.coord-home-rule, .blocs-home-rule, .dev-home-rule) {
    display: none;
  }
  /* Coordinate's quiet card: same inset, border, surface and label in each domain. */
  body[data-shell="panel"] .nss-desktop-caught-up {
    padding: 20px;
    border: 1px solid var(--b1);
    border-radius: 16px;
    background: rgba(255,255,255,.02);
    color: rgb(var(--section-accent-rgb));
  }
  body[data-shell="panel"] .nss-desktop-caught-up p {
    margin: 0;
    font: 400 var(--lc-2, 14px)/1.5 var(--f-mono);
    letter-spacing: 2.4px;
    text-transform: uppercase;
  }
  body[data-shell="panel"] :is(.coord-home-static, .blocs-home-static, .state-home-static, .dev-home-static):has(.nss-home-notifications) {
    min-height: 0; min-width: 0; overflow-y: auto;
    overscroll-behavior-y: contain;
  }
  /* Preserve the live column's centering when cards fit; start at the top
     only when the stack overflows so the first card remains reachable. */
  body[data-shell="panel"] :is(.coord-home-static, .blocs-home-static, .dev-home-static):has(.nss-home-notifications) {
    justify-content: safe center;
  }
  body[data-shell="panel"] :is(.coord-home-static, .blocs-home-static, .state-home-static, .dev-home-static):has(.nss-home-notifications) > * {
    flex-shrink: 0;
  }
}

/* Keep the three notification choices together, including narrow phones. */
body[data-shell="panel"] .nss-home-notification .nss-attention-actions > button {
  flex: 1 1 0; min-width: 0; padding-inline: 6px;
}
body[data-shell="panel"] .nss-home-reminder-confirmation {
  margin: 0 0 16px; font-weight: 600; color: var(--t1);
}

/* Active horizontal text tabs share a regular label weight. */
body .co-tab.active,
body .cz-tab.active,
body .bl-vtab.active,
body .inv-tab.is-active,
body .relationship-tab.is-active,
body .pdeck-medium-tab.is-active,
body .studio-path-tabs button.is-active,
body .inq-tab.is-active,
body .ledger-domain-tabs button[aria-selected="true"],
body .ledger-lens-tabs button[aria-selected="true"],
body .aw-guided-workspace .aw-guided-steps [aria-current="step"] strong {
  font-weight: 400;
}

/* Coordinate portrait notifications — approved landing presentation. */
#coordHomeNext, #stateHomeNext, [data-nss-phome]:has(.portrait-notifications) { container-type: inline-size; }
body[data-shell="panel"] .coord-home-static { justify-content:flex-start; }
@media(min-width:901px) {
  body[data-shell="panel"] .coord-home-static { margin:0;padding:clamp(20px,3vw,42px); }
}
body[data-shell="panel"] .coord-home-copy {
  padding:0 0 24px;border-top:0;border-bottom:1px solid var(--b2);
}
body[data-shell="panel"] .coord-home-copy .coord-home-kicker {
  margin:0;font:400 34px/1.15 var(--f-serif,'Cormorant Garamond',serif);
  letter-spacing:0;text-transform:none;color:rgb(var(--section-accent-rgb,253,164,175));
}
body[data-shell="panel"] .coord-home-copy .coord-home-intro {
  margin:8px 0 0;max-width:none;font:400 16px/1.5 var(--f-ui,Inter,sans-serif);color:var(--t2);
}
body[data-shell="panel"] .coord-home-rule { display:none; }
body[data-shell="panel"] .nss-home-notifications.portrait-notifications { display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px; }
/* One minimum for every card: 3 title lines (57.6) + 2 date lines (32.4)
   + gap (4) + raised bottom inset (54) + initials (48) + clearance (8)
   + borders (2), divided by .84 for the initials' 16% top inset = 245.24.
   Round up to the next 8px step; wider cards retain the 4:5 proportion. */
body[data-shell="panel"] .nss-home-notification.portrait-notification { position:relative;isolation:isolate;aspect-ratio:4/5;width:100%;min-width:0;min-height:248px;box-sizing:border-box;overflow:hidden;border-radius:14px;border:1px solid rgba(255,255,255,.15);background:linear-gradient(145deg,rgba(255,255,255,.085),rgba(255,255,255,.042));box-shadow:0 14px 32px rgba(7,3,12,.12); }
body[data-shell="panel"] .portrait-notification .portrait-open { position:absolute;inset:0;width:100%;padding:0;border:0;background:transparent;text-align:left;color:#fff;cursor:pointer;font:inherit; }
.portrait-open img { position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 28%;opacity:.3;transition:opacity 650ms ease-in-out;mask-image:linear-gradient(to bottom,#000 0%,#000 42%,rgba(0,0,0,.65) 64%,transparent 91%); }
.portrait-open::after { content:'';position:absolute;inset:0;background:linear-gradient(to bottom,transparent 35%,rgba(35,17,47,.16) 45%,rgba(35,17,47,.96) 100%); }
.portrait-caption { position:absolute;z-index:1;left:14px;right:14px;bottom:18px;display:flex;flex-direction:column;gap:4px;transition:transform 550ms cubic-bezier(.2,.7,.2,1); }
.portrait-name { font:600 16px/1.2 var(--f-ui,Inter,sans-serif);text-shadow:0 2px 6px #23112f; }
.portrait-placeholder { position:absolute;inset:16% 0 auto;text-align:center;font-size:48px;line-height:1;color:var(--t3); }
body[data-shell="panel"] .portrait-notification .portrait-actions { position:absolute;z-index:2;bottom:4px;left:4px;right:4px;display:flex;gap:4px;opacity:0;visibility:hidden;transition:opacity 450ms ease-in-out,visibility 0s linear 450ms; }
body[data-shell="panel"] .portrait-notification .portrait-actions button { flex:1;min-width:0;min-height:44px;padding:6px 0;border:0;background:transparent;color:#f5dce7;font:400 14px/1.4 var(--f-ui,Inter,sans-serif);cursor:pointer;border-radius:8px; }
.portrait-actions button:hover { background:rgba(255,255,255,.1);color:white; }
.portrait-notification:hover .portrait-open img,.portrait-notification:focus-within .portrait-open img { opacity:.6; }
body[data-shell="panel"] .nss-home-notification.portrait-notification { transition:border-color 650ms ease-in-out; }
body[data-shell="panel"] .nss-home-notification.portrait-notification:is(:hover,:focus-within) { border-color:rgba(253,164,175,.65); }
body[data-shell="panel"] .portrait-notification:is(:hover,:focus-within) .portrait-actions { opacity:1;visibility:visible;transition-delay:120ms,0s; }
.portrait-notification:hover .portrait-caption,.portrait-notification:focus-within .portrait-caption { transform:translateY(-36px); }
.portrait-open:focus-visible { outline:2px solid #fda4af;outline-offset:-4px;border-radius:14px; }
.portrait-actions button:focus-visible { outline:2px solid #fda4af;outline-offset:-2px; }

/* Keep lifecycle feedback and newness, without duplicating visible copy. */
body[data-shell="panel"] .nss-home-notification.portrait-notification { display:block;padding:0; }
body[data-shell="panel"] .portrait-notification > h3,
body[data-shell="panel"] .portrait-notification > .nss-home-notification-body,
body[data-shell="panel"] .portrait-notification .nss-home-notification-kind { display:none; }
body[data-shell="panel"] .portrait-notification .nss-home-notification-heading { position:absolute;right:8px;top:8px;z-index:2;pointer-events:none; }
body[data-shell="panel"] .portrait-notification .portrait-open { margin:0;border:0;border-radius:0;background:transparent;color:#fff; }
body[data-shell="panel"] .portrait-notification .portrait-actions { margin:0;flex-wrap:nowrap; }
body[data-shell="panel"] .portrait-notification .portrait-actions button { margin:0;border:0;padding-inline:0; }
body[data-shell="panel"] .portrait-notification .nss-home-notification-feedback:not(:empty) { position:absolute;inset:0;z-index:3;margin:0;padding:12px;display:grid;place-content:center;background:#32203f;color:#fff;font-size:14px;pointer-events:none; }
body[data-shell="panel"] .coord-home-static:has(.nss-home-notifications) { justify-content:flex-start; }
.portrait-notification .portrait-caption { left:10px;right:10px; }
body[data-shell="panel"] .portrait-notifications > :not(.portrait-notification) { grid-column:1/-1; }
@container (max-width:473px) { body[data-shell="panel"] .nss-home-notifications.portrait-notifications { grid-template-columns:repeat(2,minmax(0,1fr)); } }
@media(hover:none),(pointer:coarse) { body[data-shell="panel"] .portrait-notification .portrait-actions { opacity:1;visibility:visible; }.portrait-caption{transform:translateY(-36px);} }
@media(max-width:600px) { body[data-shell="panel"] .portrait-notification .portrait-actions { opacity:1;visibility:visible; }.portrait-caption{transform:translateY(-36px);} }
@media(prefers-reduced-motion:reduce) { .portrait-caption,.portrait-open img,body[data-shell="panel"] .portrait-notification,body[data-shell="panel"] .portrait-notification .portrait-actions {transition:none;transition-delay:0s;} }

/* Non-portrait message cards retain their recorded time. */
.nss-chat-activity { display:flex;flex-direction:column;gap:4px;min-width:0; }
.nss-chat-preview { display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere;font:400 13px/1.35 var(--f-ui,Inter,sans-serif); }
.nss-chat-time { font:400 12px/1.35 var(--f-ui,Inter,sans-serif);opacity:.85; }
.nss-chat-activity [hidden] { display:none; }

/* Conversation invitations use the same date hierarchy as message cards. */
.portrait-arrival { font:400 12px/1.35 var(--f-ui,Inter,sans-serif);opacity:.85; }

/* Light glass shares the dark layout. Blur only the backdrop behind the
   card, never the portrait inside it; keep the caption veil translucent. */
html[data-theme="light"] body[data-shell="panel"] .nss-home-notification {
  background: rgba(255,255,255,.42);
  border-color: rgba(var(--section-accent-rgb, 124,58,237), .20);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.65), 0 1px 2px rgba(76,60,110,.06), 0 4px 12px rgba(76,60,110,.05);
  -webkit-backdrop-filter: blur(12px) saturate(1.08);
  backdrop-filter: blur(12px) saturate(1.08);
}
html[data-theme="light"] body[data-shell="panel"] .nss-home-notification.is-new {
  background: linear-gradient(rgba(var(--section-accent-rgb, 124,58,237), .05), rgba(var(--section-accent-rgb, 124,58,237), .05)), rgba(255,255,255,.48);
  border-color: rgba(var(--section-accent-rgb, 124,58,237), .45);
}
html[data-theme="light"] body[data-shell="panel"] .nss-home-notification-new {
  background: rgba(255,255,255,.88);
  color: rgb(var(--section-accent-rgb, 124,58,237));
}
html[data-theme="light"] body[data-shell="panel"] .nss-home-notification.portrait-notification {
  background: linear-gradient(145deg, rgba(255,255,255,.40), rgba(255,255,255,.22));
}
html[data-theme="light"] body[data-shell="panel"] .portrait-notification .portrait-open {
  color: var(--t1);
}
html[data-theme="light"] body[data-shell="panel"] .portrait-open::after {
  background: linear-gradient(to bottom, rgba(244,242,248,.06), rgba(244,242,248,.56) 18%, rgba(244,242,248,.60) 62%, rgba(244,242,248,.68));
}
html[data-theme="light"] body[data-shell="panel"] .portrait-open img { opacity: .8; }
html[data-theme="light"] body[data-shell="panel"] .portrait-notification:is(:hover,:focus-within) .portrait-open img { opacity: .95; }
html[data-theme="light"] body[data-shell="panel"] .portrait-name { text-shadow: none; }
html[data-theme="light"] body[data-shell="panel"] .portrait-notification .portrait-actions button {
  color: var(--t2);
}
html[data-theme="light"] body[data-shell="panel"] .portrait-notification .portrait-actions button:is(:hover,:active) {
  background: rgba(var(--section-accent-rgb, 124,58,237), .08);
  color: var(--t1);
}
html[data-theme="light"] body[data-shell="panel"] .nss-home-notification.portrait-notification:is(:hover,:focus-within) {
  border-color: rgba(var(--section-accent-rgb, 124,58,237), .65);
}
html[data-theme="light"] body[data-shell="panel"] .nss-home-notification button:focus-visible {
  outline-color: rgb(var(--section-accent-rgb, 124,58,237));
}
html[data-theme="light"] body[data-shell="panel"] .portrait-notification .portrait-open:focus-visible { outline-offset: -4px; }
html[data-theme="light"] body[data-shell="panel"] .portrait-notification .portrait-actions button:focus-visible { outline-offset: -2px; }
html[data-theme="light"] body[data-shell="panel"] .portrait-notification .nss-home-notification-feedback:not(:empty) {
  background: #fff;
  color: var(--t1);
}

/* Portraits in the opened digest retain their existing fallback treatment. */
.nss-artifact-reader-portrait { position:relative;display:grid;place-items:center;overflow:hidden;background:#604264;color:#fff;font:600 20px var(--f-ui, sans-serif); }
html[data-theme="light"] .nss-artifact-reader-portrait { background:#ecdbe5;color:#56243b; }

/* Use Coordinate's column inset and 30px content gap for both introductions. */
@media (min-width:901px) {
  body[data-shell="panel"] :is(.blocs-home-static, .dev-home-static),
  body[data-shell="panel"] :is(.blocs-home-static, .dev-home-static):has(.nss-home-notifications) {
    justify-content: flex-start;
    margin: 0;
    padding: clamp(20px, 3vw, 42px);
    gap: 30px;
  }
}

/* Owner correction, 2026-10-28: All domain Home statuses recede while
   navigation retains soft glass. Keep the established gray row outlines. */
html[data-theme="light"] body[data-shell="panel"]:is([data-nav-key="selfless"],[data-nav-key="develop"],[data-nav-key="projects"],[data-nav-key="coordinate"],[data-nav-key="states"]) .nss-home-notification[role="status"]:has(> h3:only-child) {
  background: rgba(255,255,255,.08);
  border-color: rgba(17,17,27,.045);
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  color: var(--t2);
}
/* Preserve the existing Selflessness and State pressed color recipes. */
html[data-theme="light"] body[data-nav-key="selfless"] { --nss-home-pressed-wash: rgba(var(--section-accent-rgb),.07); }
html[data-theme="light"] body[data-nav-key="states"] { --nss-home-pressed-wash: rgba(17,17,27,.08); }
@media (max-width: 900px) {
  html[data-theme="light"] body[data-shell="panel"]:is([data-nav-key="selfless"],[data-nav-key="develop"],[data-nav-key="projects"],[data-nav-key="coordinate"],[data-nav-key="states"]) :is(.phome-card, .phome-sibling) {
    background: rgba(255,255,255,.40);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    box-shadow: none;
  }
  html[data-theme="light"] body[data-shell="panel"]:is([data-nav-key="selfless"],[data-nav-key="develop"],[data-nav-key="projects"],[data-nav-key="coordinate"],[data-nav-key="states"]) :is(.phome-card, .phome-sibling):not(:disabled):hover {
    background: rgba(255,255,255,.55);
  }
  html[data-theme="light"] body[data-shell="panel"]:is([data-nav-key="selfless"],[data-nav-key="develop"],[data-nav-key="projects"],[data-nav-key="coordinate"],[data-nav-key="states"]) :is(.phome-card, .phome-sibling):not(:disabled):active {
    background: linear-gradient(var(--nss-home-pressed-wash,rgba(var(--section-accent-rgb),.10)),var(--nss-home-pressed-wash,rgba(var(--section-accent-rgb),.10))),rgba(255,255,255,.40);
  }
  html[data-theme="light"] body[data-shell="panel"]:is([data-nav-key="selfless"],[data-nav-key="develop"],[data-nav-key="projects"],[data-nav-key="coordinate"],[data-nav-key="states"]) :is(.phome-card, .phome-sibling):focus-visible {
    outline: 2px solid rgb(var(--section-accent-rgb));
    outline-offset: 3px;
  }
}
