/* =================================================================
   YEC. — chrome: nav, footer, mobile drawer, tweaks panel
   ================================================================= */

/* ---------------- NAV ---------------- */
.site-nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 80;
  transition: background .35s ease, box-shadow .35s ease, padding .35s ease;
  padding-block: 8px;
}
.nav-inner { display: flex; align-items: center; justify-content: space-between; gap: 24px; }
.nav-logo { display: inline-flex; align-items: center; }
.nav-logo img { height: 30px; width: auto; transition: opacity .3s ease; }
.nav-logo .logo-dark { display: none; }

.nav-links { display: flex; align-items: center; gap: clamp(18px, 2vw, 34px); }
.nav-link {
  font-family: var(--font-kicker); font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.12em; font-size: 0.74rem;
  padding-block: 6px; position: relative; white-space: nowrap;
  transition: opacity .2s ease;
}
.nav-link::after {
  content: ""; position: absolute; left: 0; bottom: -2px; height: 2px; width: 0;
  background: var(--tw-accent); transition: width .25s ease;
}
.nav-link:hover::after, .nav-link.is-active::after { width: 100%; }
.nav-portal { opacity: 1; } /* was 0.82 — dimming dropped nav-portal below AA contrast on orange */

.nav-actions { display: flex; align-items: center; gap: 16px; }
.nav-cta { padding: 0.85em 1.35em; font-size: 0.72rem; }

/* color modes */
.site-nav.nav-light { color: var(--white); }
.site-nav.nav-light .nav-logo .logo-light { display: block; }
.site-nav.nav-light .nav-logo .logo-dark { display: none; }
.site-nav.nav-dark { color: var(--navy); }
.site-nav.nav-dark .nav-logo .logo-light { display: none; }
.site-nav.nav-dark .nav-logo .logo-dark { display: block; }
.site-nav.nav-light .nav-cta { background: var(--white); color: var(--navy); }
.site-nav.nav-light .nav-cta:hover { background: var(--cream); }

/* on-orange hero: navy link text passes AA on orange (white fails 2.68:1);
   keep the white logo + white CTA so they stay visible on the orange field */
.site-nav.nav-onorange { color: var(--navy); }
.site-nav.nav-onorange .nav-logo .logo-light { display: block; }
.site-nav.nav-onorange .nav-logo .logo-dark { display: none; }
.site-nav.nav-onorange .nav-cta { background: var(--white); color: var(--navy); }
.site-nav.nav-onorange .nav-cta:hover { background: var(--cream); }

/* scrolled — solid cream bar, teal logo, navy text ALWAYS. This block must sit
   AFTER every mode block above: equal specificity means source order decides,
   and scrolled has to win in all modes (audit 2026-07-07: the onorange block
   below it was overriding the scrolled state on Home — white logo on cream). */
.site-nav.scrolled {
  background: var(--cream);
  box-shadow: 0 1px 0 rgba(23,32,41,0.08), 0 14px 34px -22px rgba(23,32,41,0.5);
  color: var(--navy);
}
.site-nav.scrolled .nav-logo .logo-light { display: none; }
.site-nav.scrolled .nav-logo .logo-dark { display: block; }
.site-nav.scrolled .nav-cta { background: var(--tw-accent); color: var(--navy); }
.site-nav.scrolled .nav-cta:hover { background: var(--orange-deep); }

/* menu open — header goes dark to match the drawer, in every page mode and
   even when scrolled (higher specificity than .scrolled, so it wins). Keeps
   the logo + close X light and legible on the navy drawer (7/14) */
body.drawer-open .site-nav { background: var(--navy); box-shadow: none; color: var(--cream); }
body.drawer-open .site-nav .nav-logo .logo-light { display: block; }
body.drawer-open .site-nav .nav-logo .logo-dark { display: none; }
/* the burger is a <button> and does not inherit color, so its currentColor X
   falls back to black — force it light so the close X reads on the navy */
body.drawer-open .nav-burger { color: var(--cream); }

/* Dark (S3-02): the signed-out header (sign-in; /vote and /application-status
   load no tokens.css, so they stay light) is fixed and see-through over the
   page's hero, which may still be cream. In dark it is a solid bar on tokens
   with the white logo, readable whatever sits under it. The shell's own
   #site-nav rules outrank this on every member page. */
[data-theme="dark"] .site-nav { background: var(--surface); color: var(--ink); box-shadow: inset 0 -1px 0 var(--line); }
[data-theme="dark"] .site-nav .nav-logo .logo-light { display: block; }
[data-theme="dark"] .site-nav .nav-logo .logo-dark { display: none; }
/* styles.css draws the scrolled bar's ring in --navy (its bar is cream):
   1.00:1 on the dark --surface bar, and --teal is 3.05:1 unscrolled. */
[data-theme="dark"] .site-nav :focus-visible, [data-theme="dark"] .site-nav.scrolled :focus-visible { outline-color: var(--focus); }
/* "Back to yec.co" (S1-12): the footer's 44px text link, pulled into the
   logo's row so the header keeps its height. */
.nav-back { margin-block: -7px; }

/* burger. color: inherit, or the currentColor bars take the browser's button
   ink (black, or white under color-scheme dark) instead of the bar's: black
   on /apply's navy hero, white on a white bar (S3-02B, 1.00:1). */
.nav-burger { display: none; flex-direction: column; gap: 5px; padding: 14px; margin: -6px; color: inherit; } /* 44px+ tap target (audit) */
.nav-burger span { width: 24px; height: 2px; background: currentColor; transition: transform .3s ease, opacity .3s ease; }
body.drawer-open .nav-burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
body.drawer-open .nav-burger span:nth-child(2) { opacity: 0; }
body.drawer-open .nav-burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* drawer */
.nav-drawer {
  position: fixed; inset: 0; z-index: 70;
  background: var(--navy); color: var(--cream);
  /* flex + margin:auto on the inner centers when it fits, but scrolls from
     the top (never clips the first item behind the header) when the menu is
     taller than the viewport (7/14) */
  display: flex; overflow-y: auto; -webkit-overflow-scrolling: touch;
  opacity: 0; pointer-events: none; visibility: hidden;
  transition: opacity .35s ease, visibility .35s ease;
}
/* visibility:hidden also pulls the closed drawer's links out of the tab order */
body.drawer-open .nav-drawer { opacity: 1; pointer-events: auto; visibility: visible; }
.nav-drawer-inner { margin: auto; padding: 76px 0 40px; display: flex; flex-direction: column; gap: 4px; text-align: center; width: min(420px, 86vw); }
.nav-drawer-inner a:not(.btn) {
  font-family: var(--font-head); font-weight: 300; font-size: 1.9rem;
  padding: 10px 0; border-bottom: 1px solid rgba(255,255,255,0.1);
}
.nav-drawer-inner a:not(.btn):hover { color: var(--orange); }

@media (max-width: 940px) {
  .nav-links { display: none; }
  .nav-cta { display: none; }
  .nav-burger { display: flex; }
}

/* ---------------- FOOTER ---------------- */
.site-footer { padding-block: clamp(64px, 8vw, 104px) 40px; }
.footer-top { display: grid; grid-template-columns: 1.6fr 1fr 1fr; gap: clamp(32px, 5vw, 72px); }
.footer-logo { height: 40px; width: auto; margin-bottom: 26px; }
.footer-tag { font-family: var(--font-head); font-weight: 300; font-size: 1.5rem; line-height: 1.25; color: var(--cream); }
.footer-cta { margin-top: 24px; color: var(--orange); }
.footer-h { font-family: var(--font-kicker); font-weight: 600; text-transform: uppercase; letter-spacing: 0.16em; font-size: 0.74rem; color: var(--orange); margin-bottom: 20px; }
.footer-list { display: flex; flex-direction: column; gap: 12px; }
.footer-list a { color: rgba(236,236,228,0.8); font-size: 0.98rem; transition: color .2s ease; }
.footer-list a:hover { color: var(--white); }
.footer-rule { margin-block: clamp(36px, 5vw, 56px); }

/* footer social icons. Wraps: six 42px squares are 302px, past the 276px a
   320 phone leaves, and unwrapped they widened the whole column (A-FIX1). */
.footer-social { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 26px; }
.footer-social a { width: 42px; height: 42px; border: 1px solid rgba(236,236,228,0.22); display: grid; place-items: center; color: rgba(236,236,228,0.82); transition: background .2s ease, border-color .2s ease, color .2s ease, transform .2s ease; }
.footer-social a:hover { background: var(--orange); border-color: var(--orange); color: #fff; transform: translateY(-2px); }
.footer-social svg { width: 18px; height: 18px; display: block; }
.footer-bottom { display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.footer-legal { display: flex; flex-wrap: wrap; gap: 12px 26px; }
.footer-legal a { font-family: var(--font-kicker); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.1em; color: rgba(236,236,228,0.7); }
.footer-legal a:hover { color: var(--white); }
@media (max-width: 760px) {
  .footer-top { grid-template-columns: 1fr 1fr; }
  .footer-brand { grid-column: 1 / -1; }
}
@media (max-width: 480px) { .footer-top { grid-template-columns: 1fr; } }

/* ---------------- COUNTDOWN ---------------- */
.countdown { display: flex; gap: clamp(12px, 2.4vw, 28px); align-items: flex-start; }
.cd-unit { display: flex; flex-direction: column; align-items: center; min-width: 60px; }
.cd-num {
  font-family: var(--font-head); font-weight: 300;
  font-size: clamp(2.3rem, 5vw, 3.6rem); line-height: 1; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums; font-feature-settings: "tnum";
}
.cd-lab {
  font-family: var(--font-kicker); font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.16em; font-size: 0.62rem; margin-top: 10px; color: var(--accent-ink);
}
.cd-sep { font-family: var(--font-head); font-weight: 300; font-size: clamp(1.8rem, 4vw, 2.8rem); line-height: 1; opacity: 0.3; align-self: flex-start; }
/* label colour is surface-aware via --accent-ink (orange on dark, navy on orange, teal on light) */


/* =================================================================
   PORTAL SHELL — the grouped sidebar behind the login
   =================================================================
   Drew, 2026-09-02: "It's the layout that I like with the sidebar",
   and "It should be for members too, and we want to change the size
   up there as well."

   WHY A body CLASS AND NOT data-portal. That attribute is also on
   /vote, /application-status and /members/login — a vote link works
   for somebody with no session at all, and none of the three has a
   signed-in person to hang a sidebar on. site.js adds .pshell only on
   /members/ (login excluded), and only once the sidebar is actually in
   the DOM, so a failed script leaves the old chrome standing rather
   than a half-built shell.

   THE SIZE UP THERE. The marketing bar is position:fixed with a 30px
   logo, and [data-portal] .page-hero adds clamp(64px,7vh,88px) under
   it — about 138px before a member sees the thing they came for. The
   shell header is 52px and the hero padding goes with it.

   FIXED SIDEBAR, NOT A GRID ITEM — and this is load-bearing, not
   style. The first version laid body out as a three-row grid with the
   sidebar in a "side" area and position:sticky on the header. A grid
   item's sticky constraint rectangle is its GRID AREA, and the header
   row is auto-sized to exactly the header's own 52px, so it had zero
   travel and scrolled away like a static element. Measured on
   /members/code-of-conduct/: at scrollY 304 the bar sat at -304.
   Below 900px that bar holds the only navigation there is, so a member
   scrolling a long page had to scroll all the way back up to move.
   Taking the sidebar out of flow puts the header back in the body's
   own containing block, where sticky means what it says. It also means
   a stray document.body.appendChild (a toast, a modal) lands in the
   content column instead of an implicit grid row under the sidebar. */

body.pshell {
  background: var(--bg, var(--cream));
  min-height: 100vh;
  padding-left: var(--sidebar-w, 232px); /* INTEGRATION.md #4 */
  /* AND THE HEADER STILL DID NOT STICK after the grid came out, for a second
     and entirely separate reason: css/styles.css:65 sets overflow-x:hidden on
     body, and `hidden` on one axis computes the other to `auto`, which makes
     body a scroll container. A sticky child sticks to its nearest scrolling
     ancestor, so the bar was pinned to a box that never scrolls while the
     viewport did — barTop tracked -scrollY exactly. `clip` does the same
     clipping WITHOUT creating a scroll container. html already carries
     overflow-x:clip (styles.css:3) which is what actually holds iOS, per the
     note there, so this only relaxes the belt and keeps the braces. */
  overflow-x: clip;
}

/* ---- sidebar ----
   Both sides draw the same 44px rows (.ps-row, site.js menuRow). The
   member menu is 8 rows and fits; the staff menu is 22 rows plus the Press
   dropdown (A-STAFF-1), so on a short window the column scrolls and the
   foot (Member view) sticks to its bottom. The phone path is the tab bar. */
#ps-side {
  position: fixed; top: 0; left: 0; bottom: 0; width: var(--sidebar-w, 232px); z-index: var(--z-sidebar, 75);
  background: var(--sidebar-bg, #172029); color: var(--sidebar-ink-strong, #FFFFFF);
  display: flex; flex-direction: column; padding: 14px 0;
  overflow-y: auto; overscroll-behavior: contain;
}
.ps-brand { display: block; padding: 2px 20px 16px; }
.ps-brand img { height: 26px; width: auto; display: block; }
.ps-brand:focus-visible { outline: 2px solid var(--accent, #E98500); outline-offset: -2px; }

/* The switch between the two sides. Marked rather than just listed: it is the
   only row in the sidebar that changes what you are looking at rather than
   where you are in it, and an admin hunting for the way back should find it
   without reading four words of every row. */
.ps-switch { color: var(--sidebar-ink-strong, #FFFFFF); font-weight: 600; }
.ps-switch .ps-dot { background: var(--accent, #E98500); opacity: 1; }
#ps-side nav { display: flex; flex-direction: column; }
.ps-link {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 20px; color: var(--sidebar-ink, #D7DCE2); text-decoration: none;
  font-size: 0.82rem; line-height: 1.35;
  border-left: 3px solid transparent;
}
.ps-link:hover { color: var(--sidebar-ink-strong, #FFFFFF); background: rgba(255, 255, 255, 0.06); }
.ps-link:focus-visible { outline: 2px solid var(--accent, #E98500); outline-offset: -2px; }
.ps-link.is-on {
  color: var(--sidebar-ink-strong, #FFFFFF); background: var(--sidebar-active, rgba(233, 133, 0, 0.16));
  border-left-color: var(--accent, #E98500); font-weight: 600;
}
.ps-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: 0.45; flex: 0 0 auto; }
.ps-link.is-on .ps-dot { background: var(--accent, #E98500); opacity: 1; }
.ps-foot { margin-top: auto; padding: 10px 20px 0; border-top: 1px solid var(--sidebar-line, rgba(255, 255, 255, 0.12)); }
.ps-foot .ps-link { padding-left: 0; border-left: 0; }

/* ---- the member menu (S3-01): 8 rows at 44px with 16px labels and a 20px
   Lucide icon, then the pinned foot (Invite, Member offers, Code of Conduct).
   In the sidebar the foot sticks to the bottom if the column ever scrolls (a
   short window), and the nav grows so it sits at the bottom when it fits. */
#ps-side .ps-menu, .ps-menu { flex: 1 0 auto; display: flex; flex-direction: column; }
.ps-row { min-height: var(--target-min, 44px); padding: 0 20px 0 17px; gap: 12px; font-size: 16px; line-height: 20px; }
.ps-row-t { flex: 1 1 auto; min-width: 0; }
.ps-ico { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.ps-menu .ps-foot { position: sticky; bottom: 0; background: var(--sidebar-bg, #172029); padding: 8px 20px 0; }
.ps-menu .ps-foot .ps-link { min-height: var(--target-min, 44px); padding: 0; font-size: 14px; color: var(--sidebar-label, #B8B4B1); }
.ps-menu .ps-foot .ps-link:hover { color: var(--sidebar-ink-strong, #FFFFFF); background: none; text-decoration: underline; }
.ps-menu .ps-foot .ps-dot { display: none; }
.ps-menu .ps-foot .ps-switch { color: var(--sidebar-ink-strong, #FFFFFF); font-weight: 600; }
/* A closed row, tab or bell is [hidden] (site.js paintFeatures), but .ps-link,
   .ps-tab and .ps-bell set display, which beats the attribute. portal.css
   has the same rule page-wide; docShell pages (People, Press wins) load no
   portal.css, so the shell's own chrome carries it. */
body.pshell :is(#ps-side, #nav-drawer, #site-nav, .ps-tabs, #ps-tabbar, #ps-more) [hidden] { display: none !important; }
/* The staff menu's search (site.js staffMenuHtml): a row it filters out is
   .ps-nomatch; a row found by a tab's name lists those tabs under it. */
:is(#ps-side, #ps-more) .ps-nomatch { display: none !important; }
.ps-menu .ps-hit { min-height: var(--target-min, 44px); padding-left: 49px; font-size: 15px; }
.ps-find { padding: 0 20px 10px; }
.ps-find input { box-sizing: border-box; width: 100%; min-height: var(--target-min, 44px); padding: 0 12px; font: inherit; font-size: 16px; border-radius: 4px;
  color: var(--sidebar-ink-strong, #FFFFFF); background: rgba(255, 255, 255, 0.08); border: 1px solid var(--sidebar-line, rgba(255, 255, 255, 0.24)); }
.ps-find input::placeholder { color: var(--sidebar-label, #B8B4B1); opacity: 1; }
.ps-find input:focus-visible { outline: 2px solid var(--accent, #E98500); outline-offset: 1px; }
.ps-find-none { margin: 8px 0 0; font-size: 14px; color: var(--sidebar-ink, #D7DCE2); }
.ps-find-none:empty { display: none; }

/* ---- header: 52px, sticky, tells you where you are ---- */
body.pshell #site-nav {
  /* ABOVE the drawer (z-index 70), not below it. The base .site-nav is 80 and
     the first version of this rule dropped it to 60, which slid the bar under
     the open drawer and took the burger's X with it — Escape still closed the
     menu, which is no use on a phone. The bar stays on top so the X is there,
     and .nav-drawer-inner's 60px top padding clears it. */
  position: sticky; top: 0; left: auto; right: auto; z-index: var(--z-header, 80);
  background: var(--surface, #FFFFFF); border-bottom: 1px solid var(--line, #DCDCD4);
  padding: 0; box-shadow: none; color: var(--ink, #172029);
  min-height: 53px; box-sizing: border-box; /* QA-4 C-7: the 52px bar and its rule, kept before site.js fills it */
}
/* QA-4 C-7: the content column fills the screen from the first paint, so the
   footer starts below the fold and the rows arriving from the API push it
   further down unseen instead of shifting it across the screen. */
body.pshell main { min-height: 100vh; }
body.pshell #site-nav.scrolled { background: var(--surface, #FFFFFF); box-shadow: 0 1px 3px rgba(23, 32, 41, 0.06); }
.ps-bar {
  height: 52px; display: flex; align-items: center; gap: 14px;
  padding-inline: clamp(14px, 2.4vw, 26px);
}
.ps-title {
  font-family: var(--font-kicker); font-weight: 700; font-size: 0.88rem;
  letter-spacing: 0.02em; color: var(--ink, #172029); margin: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ps-who { margin-left: auto; display: flex; align-items: center; gap: 10px; flex: 0 0 auto; }
.ps-pill {
  font-family: var(--font-kicker); font-weight: 600; font-size: 0.75rem;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-2, #555C63);
  border: 1px solid var(--line, #DCDCD4); border-radius: 20px; padding: 7px 12px;
  text-decoration: none; line-height: 1;
}
.ps-pill:hover { border-color: var(--link, #005E7A); color: var(--link, #005E7A); }
.ps-av {
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--brand-teal, #007396); color: var(--white);
  display: grid; place-items: center; text-decoration: none;
  font-family: var(--font-kicker); font-weight: 700; font-size: 0.75rem;
  letter-spacing: 0.02em;
}
/* The chip is a menu button now (Drew 09-30): the headshot fills the circle. */
button.ps-av { border: 0; padding: 0; cursor: pointer; }
.ps-av img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; display: block; }
.ps-bell-menu.ps-av-menu { width: 200px; }
.ps-av-row { display: flex; align-items: center; width: 100%; min-height: 44px; padding: 0 14px; background: none; border: 0; font: inherit; font-size: 14px; color: var(--ink, #172029); text-decoration: none; text-align: left; cursor: pointer; }
.ps-av-row:hover, .ps-av-row:focus-visible { background: var(--raised, #F5F5F0); }
.ps-av-out { border-top: 1px solid var(--line, #DCDCD4); }
.ps-av-row[disabled] { opacity: .55; cursor: default; }
/* 44px hit area around the pill and the avatar, drawn size unchanged (UX audit 2026-09-29). */
.ps-pill, .ps-av { position: relative; }
.ps-pill::after, .ps-av::after {
  content: ""; position: absolute;
  top: calc(50% - 22px); bottom: calc(50% - 22px);
  left: min(0px, calc(50% - 22px)); right: min(0px, calc(50% - 22px));
}

/* ---- the bare shell (S1-11, site.js isBare) ----
   Logo, title and Sign out; no sidebar, so no gutter for one at any width,
   and the page column centres (portal.css pins it left, beside the sidebar),
   as on the WelcomeDesktop board. Sign out, and "Finish setup" on the other
   walled pages, borrow the footer's 44px text button. */
body.pshell[data-shell="bare"] { padding-left: 0; }
body.pshell[data-shell="bare"] .container { margin-inline: auto; }
.ps-bare-logo { height: 22px; width: auto; display: block; flex: 0 0 auto; }
/* The navy logo vanishes on the dark bar; the cream one takes its place. */
.ps-bare-logo-dark, [data-theme="dark"] .ps-bare-logo:not(.ps-bare-logo-dark) { display: none; }
[data-theme="dark"] .ps-bare-logo-dark { display: block; }
.ps-bare-setup, .ps-bare-signout { margin-left: auto; flex: 0 0 auto; }
.ps-bare-setup + .ps-bare-signout { margin-left: 0; }
/* At 320, beside Finish setup, the title kept three letters ("You..."); the
   page's H1 names the page just below. */
@media (max-width: 360px) { .ps-bar:has(.ps-bare-setup) .ps-title { display: none; } }

/* ---- the page's own hero, inside the shell ----
   The bar already names the page, so the display-size H1 sixty pixels
   below it said the same thing twice at four times the size. It stays
   the document's H1 and stops being a billboard.

   THE KICKER IS NOT DECORATION AND MUST NOT BE HIDDEN. It reads
   "Staff" on the admin pages, which is redundant next to a staff
   sidebar — but on /members/checkin/ it is a live field:
   members/checkin.njk:173 writes the check-in's own label into it
   ("Quarterly check-in", "Year in review"), and hiding it left a
   member looking at "How are you, Drew?" with nothing saying which
   check-in they were answering. So it shrinks; it does not vanish. */
body.pshell .page-hero { padding-top: clamp(16px, 2.2vw, 24px); }
body.pshell .page-hero .kicker { margin-bottom: 10px; }  /* size left alone: it can hold a live label */
/* ONE H1 RULE, and it is css/portal.css (body.pshell .h1, 28px and 23px).
   The clamp that stood here outranked it on every member page (S2-13, S3-01).
   What stays is width only: pages.css gives hero H1s 18ch for display type,
   which wraps a working title onto three lines. */
body.pshell .page-hero .h1 { max-width: 34ch; }
/* People and Press wins (docShell, functions/members/directory.js) load no
   portal.css, so they would fall back to the marketing display size.
   Zero-specificity :where() loses to portal.css wherever that file loads,
   and the values are portal.css's own.
   ponytail: a copy of portal.css's two sizes; delete once docShell loads portal.css. */
:where(body.pshell .page-hero) .h1 { font: 600 1.75rem/1.2 var(--font-body); letter-spacing: -0.01em; }
@media (max-width: 900px) { :where(body.pshell .page-hero) .h1 { font-size: 1.4375rem; } }

/* ---- section tabs (S3-01): drawn by site.js from the menu table at the
   foot of the page's hero. Same look as .y-tabs (components.css), which
   People and Press wins do not load. */
.ps-tabs { display: flex; flex-wrap: wrap; gap: 0 var(--space-6, 24px); margin-top: var(--space-4, 16px); box-shadow: inset 0 -1px 0 var(--line, #DCDCD4); }
.ps-tab { position: relative; display: inline-flex; align-items: center; min-height: var(--target-min, 44px); min-width: var(--target-min, 44px); justify-content: center; padding: 0 2px;
  font: 600 13px/16px var(--font-kicker); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-2, #555C63); text-decoration: none; white-space: nowrap; }
.ps-tab:hover, .ps-tab[aria-current="page"] { color: var(--ink, #172029); }
.ps-tab:focus-visible { outline: 2px solid var(--focus, #005E7A); outline-offset: -3px; }
.ps-tab[aria-current="page"]::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: var(--mark, #B86800); }
/* Staff tab rows (B1): one line that scrolls inside its own strip on a
   phone, never the page (the press pages' own row: css/portal.css). A
   tab's count sits after its name. */
.ps-strip { flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: thin; }
.ps-strip .ps-tab { flex: none; }
/* Drew 10-03: at 390 the staff tab row cut off with no cue. The strip is the
   tabs' offsetParent (site.js scrolls the open tab into view from its
   offsetLeft, again as the tabs change size). While more tabs sit past
   the right edge it fades there,
   like the member record's tabs (staff.css is-more). CSS only: a scroll
   timeline on the strip itself runs the fade from 40px at the start to 0 at
   the end, and a strip that does not scroll has no timeline, so no fade.
   Browsers without scroll timelines show the plain strip, as before. */
.ps-strip { position: relative; }
@property --ps-fade { syntax: "<length>"; inherits: false; initial-value: 0px; }
@keyframes ps-fade { from, 92% { --ps-fade: 40px; } to { --ps-fade: 0px; } }
@supports (animation-timeline: scroll()) {
  .ps-strip { animation: ps-fade linear both; animation-timeline: scroll(self inline);
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - var(--ps-fade)), transparent); mask-image: linear-gradient(to right, #000 calc(100% - var(--ps-fade)), transparent); }
}
.ps-tab .ps-cnt { margin-left: var(--space-2, 8px); letter-spacing: 0; }
/* Dark (S3-02): the hero under the tabs takes the page's tokens; .bg-cream
   stays cream, which left the current tab cream on cream. Its lead and
   kicker, on the untokenised --gray and --accent-ink, follow. No fallbacks:
   People and Press wins load no tokens.css, so they stay light. */
[data-theme="dark"] body.pshell .page-hero { background: var(--bg); color: var(--ink); --gray: var(--ink-2); --accent-ink: var(--kicker); }
body.pshell .page-hero p.lead { margin-top: 12px; font-size: 1rem; }
/* The marketing rhythm puts a full section break between the hero and the
   first band. On a working page that is a hundred pixels of nothing between
   the title and the thing you came to do; here the two are one screen. */
body.pshell .page-hero.portal-hero { padding-bottom: clamp(10px, 1.4vw, 16px); }
body.pshell .page-hero + .section { padding-top: clamp(14px, 2vw, 22px); }
.ps-who { position: relative; }
.ps-bell, .ps-ib { position: relative; width: 44px; height: 44px; display: inline-grid; place-items: center; background: none; border: 0; color: var(--ink, #172029); cursor: pointer; border-radius: 50%; }
.ps-bell:hover, .ps-ib:hover, .ps-bell[aria-expanded="true"] { background: var(--raised, #F5F5F0); }
.ps-bell-dot { position: absolute; top: 10px; right: 10px; width: 8px; height: 8px; border-radius: 50%; background: var(--mark, #B86800); box-shadow: 0 0 0 2px var(--surface, #fff); } /* S1-08: 4.2:1 on the bar (orange was 2.7:1); the fallbacks serve docShell and staff pages, which load no tokens.css */
.ps-bell-menu { position: absolute; right: 0; top: 48px; width: min(360px, calc(100vw - 24px)); background: var(--surface, #FFFFFF); border: 1px solid var(--line, #DCDCD4); box-shadow: var(--shadow-1, 0 12px 32px rgba(23,32,41,0.14)); padding: 6px 0; z-index: 60; text-align: left; }
.ps-bell-head { font-family: var(--font-kicker); font-weight: 600; text-transform: uppercase; letter-spacing: 0.12em; font-size: 12px; color: var(--kicker, #005E7A); padding: 8px 14px 4px; margin: 0; }
.ps-bell-row { display: block; padding: 10px 14px; color: var(--ink, #172029); text-decoration: none; border-top: 1px solid var(--line, #DCDCD4); }
.ps-bell-row:hover { background: var(--raised, #F5F5F0); }
.ps-bell-row.unread .ps-bell-title { font-weight: 700; }
.ps-bell-title { display: block; font-size: 14px; line-height: 1.3; }
.ps-bell-body { display: block; font-size: 12.5px; color: var(--ink-2, #555C63); margin-top: 2px; }
.ps-bell-empty { padding: 12px 14px; font-size: 13px; color: var(--ink-2, #555C63); margin: 0; }
.ps-bell-foot { display: flex; justify-content: space-between; border-top: 1px solid var(--line, #DCDCD4); } /* S2-12: See all and Settings, side by side */
.ps-bell-all { display: flex; align-items: center; min-height: 44px; padding: 0 14px; font-family: var(--font-kicker); font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em; font-size: 12px; color: var(--link, #005E7A); text-decoration: underline; text-underline-offset: 3px; }
/* Unscoped from body.pshell: sign-in, /vote and /application-status wear this short footer too (S1-12). */
.site-footer.ps-footer { background: transparent; color: var(--ink-2, #555C63); padding-block: 20px 28px; border-top: 1px solid var(--line, #DCDCD4); margin-top: clamp(24px, 4vw, 48px); }
/* Full width, like the bar above it: the page's .container caps at 1400px, so
   on a wide screen the copyright stopped at the content card's right edge
   while the header ran to the screen's (Drew, 2026-09-18). Same side padding
   as .ps-bar so the two line up. */
body.pshell .ps-footer .ps-footer-in { max-width: none; padding-inline: clamp(14px, 2.4vw, 26px); }
.ps-footer-in { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 20px; }
.ps-footer-links { display: flex; flex-wrap: wrap; align-items: center; gap: 0 20px; }
.ps-footer-links a, .ps-footer-signout, .ps-bare-setup, .nav-back { font-family: var(--font-kicker); font-weight: 600; font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink, #172029); text-decoration: underline; text-underline-offset: 3px; background: none; border: 0; padding: 0; min-height: 44px; display: inline-flex; align-items: center; cursor: pointer; }
.ps-footer-links a:hover, .ps-footer-signout:hover, .ps-bare-setup:hover, .nav-back:hover { color: var(--link, #005E7A); }
.ps-bar .ps-bare-setup, .ps-bar .ps-bare-signout { font-family: inherit; font-size: 14px; letter-spacing: 0; text-transform: none; } /* QA4 B-2: the board's bare() link, 14px sentence case */
.ps-footer-signout[disabled] { opacity: .55; cursor: default; }
/* .site-footer too, or portal.css's body.pshell .small (--gray, #515151 in
   both themes) wins: 2.33:1 on the dark page. */
.site-footer.ps-footer .small { color: var(--ink-2, #555C63); margin: 0; }

/* ---- phone: the sidebar hides, it does not shrink ----
   The tab bar and the More sheet below take over, on both sides. */
@media (max-width: 900px) {
  body.pshell { padding-left: 0; }
  body.pshell #ps-side { display: none; }
  body.pshell .ps-pill { display: none; }
}
/* A closed feature, as staff see it: the row stays, greyed and still a link (members do not see it at all, UX polish 2026-09-30). */
/* A closed row: the LABEL greys, the tag does not. The first version dimmed
   the whole row with opacity, which took the tag down with it — the one part
   that has to be read. #9AA5B1 on the navy is 6.6:1, so "unavailable" is
   carried by weight and colour rather than by making the text hard to read.
   Staff get the same grey and keep the link, which is what previewing needs. */
body.pshell .ps-link.ps-staff-soon { color: #9AA5B1; }
body.pshell .ps-link.ps-staff-soon .ps-dot { opacity: 0.3; }
/* ONE WORD, and it never wraps. "Coming soon" broke over two lines in a
   214px sidebar and pushed the label onto two lines with it, which is how a
   nine-row menu turned into a fifteen-row one. flex-shrink: 0 keeps the pill
   whole and lets the label wrap instead, if anything has to. */
body.pshell .ps-soon-tag {
  margin-left: auto; flex: 0 0 auto; align-self: center; white-space: nowrap;
  font: 600 12px/14px var(--font-kicker); /* QA4 B-2: y-soon's type (the tag also carries .y-soon); kept here for staff pages without components.css */
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--sidebar-ink-strong, #FFFFFF); background: rgba(255, 255, 255, 0.14);
  border: 0; border-radius: var(--radius-sm, 3px); padding: 2px 6px;
}
/* A closed section tab, as staff see it (members do not, UX polish
   2026-09-30): a light pill, like the More sheet's, because the tab row sits on the page. */
body.pshell .ps-tab .ps-soon-tag { margin-left: var(--space-2, 8px); color: var(--ink, #172029); background: var(--raised, #F5F5F0); border: 1px solid var(--line, #DCDCD4); }
/* The More sheet's Close (the shell drawer it came from is gone, A-STAFF-1). */
.ps-close { width: 44px; height: 44px; display: inline-grid; place-items: center; padding: 0; background: none; border: 0; color: var(--sidebar-ink-strong, #FFFFFF); cursor: pointer; }
.ps-close .ps-ico { width: 24px; height: 24px; }
.ps-close:focus-visible { outline: 2px solid var(--accent, #E98500); outline-offset: -2px; }

/* ---- the phone tab bar and More sheet (S3-01 commit 2, site.js buildTabBar) ----
   Members only, 900px and below: Home, Press, Events, People, More, 56px plus
   the safe area, over the bottom of the page. The body pads by the same
   amount so the footer clears it; .y-sticky-bar and toasts ride above it on
   body.y-has-tabs (components.css). The bar's Messages link and bell link
   (.ps-phone) replace the desktop bell button and avatar (.ps-wide). Same
   look as .y-tabbar and .y-sheet, which People and Press wins do not load.
   Screen only: a desktop print is about 740px wide, and the bar would print
   on every sheet. */
.ps-tabbar, .ps-phone { display: none; }
@media screen and (max-width: 900px) {
  body.pshell.y-has-tabs { padding-bottom: calc(var(--tabbar-h, 56px) + env(safe-area-inset-bottom, 0px)); }
  /* A control already on screen does not scroll when it takes focus, so the
     scroll area stops above the bar, as the header's scroll-padding-top does
     (WCAG 2.4.11, styles.css). buildTabBar sets the class on <html>. */
  html.ps-has-tabs { scroll-padding-bottom: calc(var(--tabbar-h, 56px) + env(safe-area-inset-bottom, 0px) + 8px); }
  .ps-tabbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-header, 80); display: flex;
    background: var(--surface, #FFFFFF); border-top: 1px solid var(--line, #DCDCD4); padding-bottom: env(safe-area-inset-bottom, 0px); }
  .ps-phone { display: inline-grid; }
  .ps-wide { display: none; }
}
/* An open message thread: the composer sits where the bar would (R6). */
body.pshell:has(#mg-thread-section:not([hidden])) { padding-bottom: 0; --tabbar-offset: 0px; }
body.pshell:has(#mg-thread-section:not([hidden])) .ps-tabbar { display: none; }
/* People's profile drawer (functions/members/directory.js: aria-modal, the
   screen's full height, z 70) sits over all the shell's chrome, so a contact
   revealed at the end of a card is not under Home and Close is not the bell. */
body.pshell:has(.dir-drawer:not([hidden])) :is(#site-nav, #ps-side, .ps-tabbar) { z-index: 0; }
/* 55px plus the bar's 1px rule: 56 in all, the height body and .y-sticky-bar clear. */
.ps-tb { position: relative; flex: 1 1 0; min-width: 0; min-height: calc(var(--tabbar-h, 56px) - 1px); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  padding: 0; background: none; border: 0; color: var(--ink-2, #555C63); font-family: inherit; font-size: 12px; font-weight: 600; line-height: 14px; text-decoration: none; cursor: pointer; }
.ps-tb .ps-row-t { flex: none; }
/* A staff tab's waiting count (A-STAFF-2) sits in the tab's top right corner, so the tab keeps its size and a 3-digit count stays inside it at 320. */
.ps-tb .ps-cnt { position: absolute; top: 4px; right: 4px; margin: 0; }
.ps-tb:hover, .ps-tb[aria-current="page"] { color: var(--ink, #172029); }
.ps-tb[aria-current="page"]::before { content: ""; position: absolute; top: -1px; left: 20%; right: 20%; height: 2px; background: var(--mark, #B86800); }
.ps-tb:focus-visible { outline: 3px solid var(--focus, #005E7A); outline-offset: -3px; }

.ps-more { box-sizing: border-box; width: 100%; max-width: 100%; max-height: calc(100vh - 48px); max-height: calc(100dvh - 48px); margin: auto 0 0; padding: 0; border: 0;
  background: var(--surface, #FFFFFF); color: var(--ink, #172029); box-shadow: var(--shadow-2, 0 16px 48px rgba(23, 32, 41, 0.24)); }
.ps-more[open] { display: flex; flex-direction: column; }
.ps-more::backdrop { background: var(--overlay, rgba(23, 32, 41, 0.55)); }
.ps-more-head { flex: none; display: flex; align-items: center; justify-content: space-between; min-height: 52px; padding: 0 4px 0 16px; border-bottom: 1px solid var(--line, #DCDCD4); }
.ps-more-head h2 { margin: 0; font-family: inherit; font-size: 18px; font-weight: 600; line-height: 24px; letter-spacing: 0; color: inherit; }
#ps-more .ps-close { color: var(--ink, #172029); }
.ps-more-body { flex: 1 1 auto; min-height: 0; overflow: auto; overscroll-behavior: contain; }
#ps-more .ps-link { min-height: 48px; padding: 0 16px 0 13px; gap: 12px; font-size: 16px; line-height: 20px; color: var(--ink, #172029);
  border-left: 3px solid transparent; border-bottom: 1px solid var(--line, #DCDCD4); }
#ps-more .ps-link:hover { color: var(--ink, #172029); background: var(--raised, #F5F5F0); }
#ps-more .ps-link.is-on { color: var(--ink, #172029); background: var(--raised, #F5F5F0); border-left-color: var(--mark, #B86800); font-weight: 600; }
#ps-more .ps-link.ps-staff-soon { color: var(--ink-2, #555C63); }
#ps-more .ps-soon-tag { color: var(--ink, #172029); background: var(--raised, #F5F5F0); border: 1px solid var(--line, #DCDCD4); }
#ps-more :focus-visible { outline: 3px solid var(--focus, #005E7A); outline-offset: -3px; }
/* The rule between the sheet's groups (nav proposal 2026-09-29): a band, not a heading, so no new copy. */
.ps-more-hr { margin: 0; height: 8px; border: 0; border-bottom: 1px solid var(--line, #DCDCD4); background: var(--raised, #F5F5F0); }
.ps-more-foot { padding: 4px 16px; }
#ps-more .ps-more-foot .ps-link { min-height: 44px; padding: 0; border: 0; font-size: 14px; background: none; text-decoration: underline; text-underline-offset: 3px; }
#ps-more .ps-dot { display: none; }
#ps-more .ps-more-me { min-height: 64px; } /* QA4 B-7: the 40px face and two lines */
.ps-more-sub { display: block; font-weight: 400; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#ps-more .ps-find { padding: 12px 16px; border-bottom: 1px solid var(--line, #DCDCD4); }
#ps-more .ps-find input { color: var(--ink, #172029); background: var(--surface, #FFFFFF); border-color: var(--ink-2, #555C63); }
#ps-more .ps-find input::placeholder { color: var(--ink-2, #555C63); }
#ps-more .ps-find-none { color: var(--ink, #172029); }
#ps-more .ps-hit { padding-left: 45px; }
.ps-more-end { flex: none; padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px)); border-top: 1px solid var(--line, #DCDCD4); }
.ps-more-out { width: 100%; min-height: 48px; display: flex; align-items: center; justify-content: center; gap: 8px; background: none; border: 1px solid currentColor;
  color: var(--ink, #172029); font-family: inherit; font-size: 16px; font-weight: 600; cursor: pointer; }
.ps-more-out:hover { background: var(--raised, #F5F5F0); }
.ps-more-out[disabled] { opacity: .55; cursor: default; }

/* The identity line on the member home: under the greeting, in the accent ink
   rather than the muted grey the rest of the small print uses, so "who am I
   signed in as" is answered at a glance instead of found by reading. */
.mp-identity {
  font-size: 0.875rem; line-height: 1.25rem; /* QA4 B-4: y-small size, sentence case */
  color: var(--accent-ink); margin: 10px 0 0;
}
/* QA-4 C-7: the line is kept (unseen) until /me answers, so the hub under it does not drop 30px when it does. */
.mp-identity[hidden] { display: block; visibility: hidden; }
