/* ============================================================
   Plumline — the plumliners' side
   The pages where coordinators and admins work: sign in, your
   sanghas, roles, the audit, settings, and in time the rest. A
   page that links this file links tokens.css and site.css before
   it. The sangha form also links sangha-form.css, and a sangha's own
   page links sanghas.css after it to show its public page as visitors
   see it. The chrome is the public chrome; this file only changes the
   ground it stands on, and adds the few things the public side has no
   need of — a table, a notice, a toolbar, a row of things to open, the
   rail. Built only from tokens.css: no raw hex, no one-off radius (#71).
   ============================================================ */

/* ---- the ground ----------------------------------------------
   Cool paper and indigo, where the public reads blossom and plum.
   The shared names are re-pointed here, so every rule in site.css
   draws the plumliners' colours on their pages without knowing it. On
   this side indigo carries both roles: the highlight, and the fill
   behind the one button that acts — so the action tokens point at
   it too, and a primary button, a focus ring and the current item
   in the bar all come out indigo. The footer reads only these shared
   names, so it goes cool with the rest.

   Someone who comes about their own sangha keeps the public side's
   blossom and plum on these pages, with the public bar: side.js marks
   the page .warm for them, and the names are left as site.css sets
   them. Sign In is on the public side for plumliners too, until they
   are signed in (Alipasha, 13 Oct 2026): it is reached from the public
   bar, so it keeps that bar and that look. */
html:not(.warm) body.plumliners:not(.sign-in-page) {
  --ground: var(--plumliners-ground);
  --ground-2: var(--plumliners-ground-2);
  --ground-blur: var(--plumliners-ground-blur);
  --card: var(--plumliners-card);
  --rule: var(--plumliners-rule);
  --muted: var(--plumliners-muted);
  --sect: var(--indigo);
  --sect-text: var(--indigo-text);
  --sect-soft: var(--indigo-soft);
  --accent: var(--indigo);
  --accent-strong: var(--indigo-text);
  --accent-strong-hover: var(--plumliners-fill-hover);
  --accent-soft: var(--indigo-soft);
  --charcoal: var(--plumliners-charcoal);
}

/* The plumliners' pages are worked in, a table of several columns at a
   time, so they take a wider page than the public side's 1000px. A sangha
   contact's pages keep the public width with the public colours. */
html:not(.warm) body.plumliners:not(.sign-in-page) { --maxw: 1200px; }

/* A page both sides open carries both bars, and shows the one for the
   side it is on. */
html.warm .bar-plumliner,
html:not(.warm) .bar-contact { display: none; }
/* On a phone the public bar's links fold under Menu (site-nav.js), which
   belongs to the public bar: on the cool side a plumliner has the rail's
   own menu, and their bar stays as it was. On the warm side the open list
   is the public bar's alone. */
@media (max-width: 620px) {
  html.nav-ready:not(.warm) .site-header .nav-menu.bar-contact { display: none; }
  html.nav-ready:not(.warm) .site-header:has(.nav-menu) .bar > nav.bar-plumliner { display: flex; }
  html.nav-ready.warm .site-header.nav-open .bar > nav.bar-plumliner { display: none; }
}

/* ---- the circle, top right ------------------------------------
   A plumliner's way to their account once signed in; Sign In itself has
   the public bar, with Plumliners as the page they are on. Until
   plumline knows who is here it holds the usual empty head and
   shoulders, drawn as a mask so it takes the text colour; once it
   knows, it holds their initials, filled like the button that acts.
   initials.js says which. */
/* Its shape is set softly, so the side rules above still hide it from
   someone who came about their own sangha. On the working pages it is a
   span, not a link: the rail is how a plumliner moves. */
:where(.site-header nav) .account-circle {
  display: inline-grid; place-items: center; width: 2.1rem; height: 2.1rem;
  margin-left: 0.5rem;
}
.site-header nav .account-circle,
.site-header nav .account-circle[aria-current] {
  padding: 0; border-radius: var(--radius-pill); overflow: hidden;
  background: var(--sect-soft); color: color-mix(in srgb, var(--sect-text) 70%, var(--sect-soft));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--sect-text) 45%, transparent);
}
.account-circle::before {
  content: ''; width: 100%; height: 100%; background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle cx='16' cy='12.6' r='5.6'/%3E%3Cpath d='M4.5 32c1.3-6.6 5.8-10.2 11.5-10.2S26.2 25.4 27.5 32z'/%3E%3C/svg%3E") center / 100% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle cx='16' cy='12.6' r='5.6'/%3E%3Cpath d='M4.5 32c1.3-6.6 5.8-10.2 11.5-10.2S26.2 25.4 27.5 32z'/%3E%3C/svg%3E") center / 100% no-repeat;
}
html.initials-known .site-header nav .account-circle {
  background: var(--accent-strong); color: var(--on-accent); box-shadow: none;
  font-size: 0.8rem; font-weight: 600; letter-spacing: 0.03em;
}
html.initials-known .account-circle::before {
  content: var(--initials); width: auto; height: auto; background: none; -webkit-mask: none; mask: none;
}
/* The circle is taller than a word, so the bar's words sit level with
   its middle rather than stretching to its height. */
.site-header nav:has(.account-circle) { align-items: center; }
.account-circle:hover { text-decoration: none; }
.account-circle:focus-visible { border-radius: var(--radius-pill); }
/* On a phone a bar holding only the circle stays beside the wordmark. */
@media (max-width: 620px) {
  html:not(.warm) .site-header nav:has(.account-circle) { width: auto; }
}

/* ---- the rail ------------------------------------------------
   The places a plumliner can go, down the left of every page where they
   work, in the dark of this side's charcoal, as a notes app keeps its
   sidebar. On a wide screen it is the frame: no bar runs across the top,
   and the wordmark heads the rail. It stays in view as the page scrolls,
   the handbook's sections at the top, their names in the rail's own hue, and
   who is signed in at the foot of the window; when the sections outgrow
   it, they scroll and the foot stays put. On a phone the bar stays,
   in the rail's dark, with the menu button that opens the rail over the
   page. */
/* The public side sets its titles light and its headings bold
   (site.css); the plumliners' pages keep theirs at the weight they were
   drawn at. Sign In and a sangha contact's pages are on the public side,
   so they take its weights (Alipasha, 21 Oct 2026). */
html:not(.warm) body.plumliners:not(.sign-in-page) :where(h1, h2, h3) { font-weight: 600; }
body.plumliners {
  --plumliners-bar: 3.6rem;
  --plumliners-rail: 15rem;
}
@media (min-width: 761px) {
  body.plumliners.has-rail {
    display: grid;
    min-height: 100dvh;
    grid-template-columns: var(--plumliners-rail) minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr) auto;
  }
  body.plumliners.has-rail > .site-header { display: none; }
  /* The rail's colour runs the column down to the footer; its places stay
     in view inside it as the page scrolls, as tall as the window, and stop
     at the footer. Size containment keeps them from stretching a short page
     past the window. */
  body.plumliners.has-rail > .plumliners-nav {
    grid-column: 1; grid-row: 1 / -1; align-self: stretch; contain: size;
    position: static; top: auto; max-height: none;
    overflow: visible; padding: 0;
  }
  body.plumliners.has-rail > .plumliners-nav .plumliners-nav-places {
    position: sticky; top: 0;
    height: 100dvh; max-height: 100%;
    overflow: hidden;
  }
  body.plumliners.has-rail .plumliners-nav-brand { display: flex; }
  body.plumliners.has-rail .plumliners-nav-links {
    flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  }
  body.plumliners.has-rail .plumliners-nav-foot {
    flex-shrink: 0; margin-top: 0; padding-bottom: 1rem;
  }
  body.plumliners.has-rail > main { grid-column: 2; min-width: 0; }
  /* The rail runs the page's whole height, and the footer sits beside it,
     under the page's own column, its words on the page's left edge. */
  body.plumliners.has-rail > .site-footer { grid-column: 2; margin-top: 0; }
  /* In a page's head, its buttons sit at the foot of the band, level with
     its last line, rather than beside the title. */
  body.plumliners.has-rail main > .hero:has(> .page-title-row) {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto auto; column-gap: 1.5rem;
  }
  body.plumliners.has-rail main > .hero > .page-title-row { display: contents; }
  body.plumliners.has-rail main > .hero > .page-title-row > .toolbar {
    grid-column: 2; grid-row: 1 / -1; align-self: end; margin: 0;
  }
  body.plumliners.has-rail main > .hero:has(> .page-title-row) > :not(.page-title-row),
  body.plumliners.has-rail main > .hero > .page-title-row > h1 { grid-column: 1; }
}
/* On a phone the bar over a page with the rail is the rail's dark too. */
body.plumliners.has-rail > .site-header {
  background: var(--rail); border-bottom-color: var(--rail-line); backdrop-filter: none;
}
body.plumliners.has-rail .site-header .bar { min-height: calc(var(--plumliners-bar) - 1px); }
body.plumliners.has-rail :is(.site-header, .plumliners-nav) .wordmark { color: var(--rail-bright); }
body.plumliners.has-rail :is(.site-header, .plumliners-nav) .sangha span { filter: drop-shadow(0 0 1.5px var(--rail)); }
.plumliners-nav {
  position: sticky; top: var(--plumliners-bar); align-self: start;
  max-height: calc(100dvh - var(--plumliners-bar)); overflow: auto;
  padding: 0;
  background: var(--rail); color: var(--rail-text);
  text-shadow: 0 1px 1px black;
}
.plumliners-nav :focus-visible { outline-color: var(--rail-text); }
.plumliners-nav-menu { display: none; }
.plumliners-nav-places { display: flex; flex-direction: column; }
/* The wordmark heads the rail on a wide screen, and leads to the Sangha Finder. */
.plumliners-nav a.plumliners-nav-brand {
  display: none; padding: 1.1rem 1.6rem 1rem; margin-bottom: 0.4rem;
}
.plumliners-nav a.plumliners-nav-brand:hover { background: none; }
/* Each place runs the rail's whole width, its words where the footer's
   start; the one the page is in is a raised band, edge to edge, at the
   words' usual weight (Alipasha, 16 Oct 2026). Under the pointer a place
   is lit a little, with no underline, though site.css gives a menu's
   links one: the light says enough. Every word on the rail has a shadow
   under it, as the dark buttons' words do. */
.plumliners-nav a {
  display: block; padding: 0.34rem 1.6rem;
  color: var(--rail-text); font-size: 1rem;
}
.plumliners-nav a:hover, .plumliners-nav a:not([class]):hover { text-decoration: none; background: var(--rail-hover); }
.plumliners-nav a[aria-current="page"] { background: var(--rail-current); box-shadow: var(--rail-current-lines); color: var(--rail-bright); }
.plumliners-nav-area { margin-top: 1.1rem; }
.plumliners-nav-links > .plumliners-nav-area:first-child { margin-top: 0; }
.plumliners-nav-section {
  font-size: 0.8rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  margin: 0 1.6rem 0.35rem; color: var(--rail-section);
}
/* Who is signed in, all in one place at the foot of the rail: their name,
   their address under it, and Sign Out, small and quiet, under them, each
   starting where the rail's words do. No circle: the name says who. */
.plumliners-nav-foot {
  margin-top: 1rem; padding: 0.9rem 1.6rem 0;
}
.plumliners-nav-account { margin: 0; }
.plumliners-nav-who { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }
.plumliners-nav-who strong { color: var(--rail-bright); font-weight: 500; font-size: 0.95rem; overflow-wrap: anywhere; }
.plumliners-nav-who #plumliners-nav-email { color: var(--rail-muted); font-size: 0.8rem; overflow-wrap: anywhere; }
.plumliners-nav-foot #plumliners-nav-logout { margin: 0.6rem 0 0; padding: 0.25rem 0.75rem; font-size: 0.85rem; }
/* On a page with the rail, who is signed in is at its foot, so the header carries no circle. */
body.plumliners.has-rail .site-header .account-circle { display: none; }
@media (max-width: 760px) {
  .plumliners-nav {
    position: static; max-height: none; padding: 0; border: 0; background: none;
  }
  .plumliners .plumliners-nav-menu.btn-icon {
    display: inline-flex; align-items: center; justify-content: center;
    position: fixed; z-index: 60;
    top: 0.7rem; right: 20px;
    width: 2.1rem; height: 2.1rem; padding: 0;
  }
  .plumliners .plumliners-nav-menu.btn-icon svg { width: 1.35rem; height: 1.35rem; }
  .plumliners-nav-places { display: none; }
  .plumliners-nav.is-open .plumliners-nav-places {
    display: flex; flex-direction: column; position: fixed; z-index: 40;
    top: var(--plumliners-bar); right: 0; bottom: 0; left: 0;
    min-height: 0; overflow: hidden; padding: 1rem 0 0;
    background: var(--rail);
  }
  .plumliners-nav.is-open .plumliners-nav-links {
    flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  }
  .plumliners-nav.is-open .plumliners-nav-foot { flex-shrink: 0; margin-top: 0; padding-bottom: 1.1rem; }
}

/* ---- the page's head -----------------------------------------
   The same head as a public page, with less room above it: these
   pages are worked in, not arrived at. The line under the title stays
   a size up and quieter here; on the public side, Sign In and a sangha
   contact's pages included, it is body text. */
.plumliners .hero { padding-block: clamp(1.6rem, 4vw, 2.4rem) 0.4rem; }
html:not(.warm) body.plumliners:not(.sign-in-page) .lede { font-size: clamp(1.05rem, 2.3vw, 1.3rem); color: var(--muted); max-width: 48ch; text-wrap: balance; }
/* On a page with the rail, the head (title, the line under it, and any
   button) sits on a band of the rail's colour raised to a middle lightness,
   as the footer does, with the rail's light words on both and a line a
   little darker under the head. The title is 1.65rem, the line under it the
   page's own size. Its words keep the left edge of what follows. */
body.plumliners.has-rail main > .hero {
  max-width: none; margin: 0 0 1.5rem;
  padding: 1.25rem max(20px, calc((100% - var(--maxw)) / 2 + 20px)) 1.1rem;
  background: var(--band); border-bottom: 1px solid var(--band-line); color: var(--rail-text);
}
body.plumliners.has-rail main > .hero h1 { font-size: 1.6rem; line-height: 1.25; letter-spacing: -0.01em; }
body.plumliners.has-rail main > .hero :is(.lede, .lead-line) { font-size: 1rem; margin-bottom: 0; }
body.plumliners.has-rail main > .hero :is(h1, p, strong, a:not(.btn), span, .kicker, .lede, .lead-line),
body.plumliners.has-rail > .site-footer :is(p, a, nav a, .fine) { color: var(--rail-text); }
body.plumliners.has-rail main > .hero a:not(.btn) { text-decoration: var(--link-underline); text-underline-offset: var(--link-offset); }
/* Every button on a dark ground is a dark button (tokens.css): in a
   page's head, in a box's head, and on the rail (Alipasha, 16 Oct 2026).
   Save and Delete in a box's head are dark buttons too, Delete's words a
   light red, pale enough to read on it. Its edge and the shadow under its
   words are the band's and the rail's own colours, darker, not black
   (Alipasha, 16 Oct 2026). */
:is(body.plumliners.has-rail main > .hero, .plumliners .lightbox-head, .plumliners-nav) .btn {
  background: var(--dark-button); color: var(--rail-bright);
  border: 1px solid oklch(from var(--band) calc(l - 0.2) c h); box-shadow: var(--dark-button-lines);
  text-shadow: 0 1px 1px oklch(from var(--rail) calc(l - 0.2) c h);
}
:is(body.plumliners.has-rail main > .hero, .plumliners .lightbox-head, .plumliners-nav) .btn:hover { background: var(--dark-button-hover); }
:is(body.plumliners.has-rail main > .hero, .plumliners .lightbox-head, .plumliners-nav) .btn.btn-danger { color: oklch(from var(--unwhole-soft) 0.94 calc(c * 2) h); }
/* The act in a box that asks first, Delete or Throw Away, is the one
   button on a dark ground that is not dark. It is filled with the red, as
   Delete Sangha is, because it is the press that cannot be taken back (Dan
   and Alipasha, 29 Oct 2026). Written out in full to outrank the dark
   button. */
body.plumliners dialog.lightbox > .lightbox-head > button.btn.btn-danger {
  background: var(--unwhole); color: var(--on-accent);
  border-color: var(--unwhole-text); box-shadow: inset 0 1px oklch(from var(--unwhole) calc(l + 0.12) c h);
  text-shadow: none;
}
body.plumliners dialog.lightbox > .lightbox-head > button.btn.btn-danger:hover { background: var(--unwhole-text); }
/* A form's Required fields mark, light enough to read on the band. */
body.plumliners.has-rail main > .hero .required-marker { color: var(--unwhole-soft); }
body.plumliners.has-rail main > .hero :focus-visible,
body.plumliners.has-rail > .site-footer :focus-visible { outline-color: var(--rail-text); }
/* On the plumliners' pages the footer is a band as the page's head is, with
   the head's room above and below its words (Alipasha, 16 Oct 2026). */
body.plumliners.has-rail > .site-footer { background: var(--band); border-top-color: var(--band-line); color: var(--rail-text); padding-block: 1.25rem 1.1rem; }
/* The note on who makes the site, quieter than the footer's places: the
   band's colour raised to a lightness of 0.91, with a touch more colour.
   4.6:1 on the band, about as faint as words this small can go and still
   be read easily. */
body.plumliners.has-rail > .site-footer :is(.fine, .fine a) { color: oklch(from var(--band) 0.91 calc(c + 0.02) h); }
body.plumliners.has-rail main > .hero .hero-art { width: 6.5rem; }
.plumliners main { padding-bottom: clamp(2rem, 5vw, 3rem); }

/* ---- a card that holds a form --------------------------------
   On the public side a card goes somewhere, so it rises under the
   pointer. Here a card holds a form or a choice, and nothing that
   holds a form moves. */
.plumliners .card { transition: none; }
.plumliners .card:hover { transform: none; box-shadow: none; border-color: var(--rule); }
.plumliners .card p { margin-bottom: 0.9rem; }
.plumliners .card .form { margin: 0; max-width: none; }
.plumliners .card .field { margin-bottom: 0.9rem; }
.plumliners .card > .btn { align-self: flex-start; margin-top: auto; }

/* ---- a drawing beside the heading ------------------------------
   One quiet line drawing on the pages where someone pauses: signing in,
   waiting for the email, the account. Not on the pages where people work
   through a table. It sits to the right of the heading where there is
   room, and steps aside on a phone. It says nothing the words do not, so
   its alt is empty and screen readers pass it by. */
.plumliners .hero.has-art { position: relative; }
.plumliners .hero-art {
  position: absolute; right: 20px; top: 50%; transform: translateY(-42%);
  width: clamp(10rem, 20vw, 14rem); height: auto; pointer-events: none;
}
@media (max-width: 760px) { .plumliners .hero-art { display: none; } }

/* ---- home ------------------------------------------------------
   Where signing in lands. The band holds the greeting and what this
   plumliner looks after, as every other page's head holds its title and
   its line. Below, as the public pages lay out theirs (Alipasha, 15 Oct
   2026), each thing has a section of its own under a heading: what is
   waiting for them, the next plumliners meeting, a new update. Each is a
   card like the Builders events: a tile at its left, its words, and the
   way on at its right. The drawing sits beside them in its own colours,
   where the light page lets it be seen. */
.plumliners .home-body {
  display: flex; align-items: flex-start; justify-content: space-between; gap: clamp(1.5rem, 5vw, 4rem);
  padding-block: clamp(0.5rem, 3vw, 1.5rem) 1rem;
}
.plumliners .home-main { flex: 1; min-width: 0; max-width: 40rem; }
.plumliners .home-main > .section { margin: 0 0 2rem; }
.plumliners .home-main > .section > h2 { margin-bottom: 0.7rem; }
.plumliners .home-cards { margin-top: 0; max-width: none; }
.plumliners .home-card {
  display: grid; grid-template-columns: 4rem 1fr auto; gap: 0.15rem 1rem; align-items: center;
  padding: 0.8rem 0.9rem 0.8rem 0.8rem; color: inherit; text-decoration: none;
}
/* The tile stands level with the top of the words, however many lines the
   title runs to (Alipasha, 17 Oct 2026); the way on stays in the middle. */
.plumliners .home-card > .when { align-self: start; }
.plumliners a.home-card:hover { text-decoration: none; }
.plumliners .home-card .session-title { font-size: 1rem; }
.plumliners .home-card .session-who { font-style: normal; }
/* A count in its tile, red as the marks it counts: their red's darker
   text shade, as the mark's own red is too pale to read on the tile. */
.plumliners .home-card .when .count { display: block; font-size: 1.2rem; font-weight: 700; line-height: 1.1; color: var(--unwhole-text); }
/* A figure that is as it should be, on a Website Status card, in ink. */
.plumliners .home-card .when .count.well { color: var(--ink); }
/* The way on: a chevron on its small raised disc, as the Builders events
   and the updates have, pointing right where the card leads to another
   page, and down where it would open on this one (Alipasha, 15 Oct 2026). */
.plumliners .home-go { position: relative; width: 2rem; height: 2rem; border-radius: var(--radius-pill);
  background: var(--white-knob);
  box-shadow: var(--white-face-lines);
}
.plumliners .home-go::after {
  content: ""; position: absolute; inset: 0; background: var(--sect-text);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6.5l4 4 4-4'/%3E%3C/svg%3E") center / 55% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6.5l4 4 4-4'/%3E%3C/svg%3E") center / 55% no-repeat;
  transform: rotate(-90deg);
}
.plumliners .home-menu-note { margin: 0; color: var(--muted); }
/* The drawing, and under it, for the Admins and the Developers team, the
   website at a glance in little room (Alipasha, 21 Oct 2026): a line for
   each figure, the figures in a column of their own, red only when one
   wants looking at, each line leading to its part of Website Status. */
.plumliners .home-side { flex: none; width: clamp(10rem, 18vw, 13rem); }
.plumliners .home-art { display: block; width: 100%; height: auto; margin-top: -2.4rem; }
.plumliners .home-side > .home-status { margin: 1rem 0 0; }
.plumliners .home-status > h2 { margin-bottom: 0.1rem; }
.plumliners .status-window { margin: 0 0 0.4rem; font-size: 0.85rem; color: var(--muted); }
.plumliners .status-list { display: grid; grid-template-columns: max-content 1fr; margin: 0; padding: 0; list-style: none; }
.plumliners .status-list li { display: contents; }
.plumliners .status-list a {
  display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; column-gap: 0.6rem; align-items: baseline;
  margin-inline: -0.4rem; padding: 0.35rem 0.4rem; border-radius: var(--radius-xs);
  color: inherit; text-decoration: none;
}
.plumliners .status-list a:hover { background: var(--accent-soft); text-decoration: none; }
.plumliners .status-figure { justify-self: end; font-size: 1.1rem; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ink); }
.plumliners .status-figure.alarm { color: var(--unwhole-text); }
.plumliners .status-words { font-size: 0.85rem; line-height: 1.3; color: var(--muted); }
@media (max-width: 760px) {
  .plumliners .home-body { flex-direction: column; align-items: stretch; gap: 0; }
  .plumliners .home-side { width: auto; }
  .plumliners .home-art { width: 8rem; margin: 0; }
}
/* On a phone a button goes under the words, where it has room. */
@media (max-width: 480px) {
  .plumliners .home-card { grid-template-columns: 3.4rem 1fr auto; }
  .plumliners .home-card > .btn.home-card-end { grid-column: 2 / -1; justify-self: start; margin-top: 0.4rem; }
}

/* ---- a notice ------------------------------------------------
   One line that says what happened. Green when it went well, red
   when it did not; the script toggles the class. */
.plumliners .notice {
  margin: 1rem 0 0; padding: 0.6rem 0.9rem; max-width: 52rem;
  border-radius: var(--radius-xs); font-size: 0.95rem;
  background: var(--whole-soft); color: var(--whole-text);
}
.plumliners .notice.error-notice { background: var(--unwhole-soft); color: var(--unwhole-text); }
/* A link in a notice, such as the way back to sign in, reads as part of
   the sentence, so it takes the notice's colour and an underline. */
.plumliners .notice a { color: inherit; font-weight: 600; text-decoration: var(--link-underline); text-underline-offset: var(--link-offset); }
/* A notice that stands on the page rather than in a section, above what it
   is about: the room goes under it. */
.plumliners .page-notice { margin: 0 0 1rem; }

/* ---- signing in ----------------------------------------------
   A line said in the ink, so it is read: what to do if the link does
   not come. */
.sign-in-note { margin: 0 0 1rem; max-width: 54rem; font-weight: 500; }
/* The privacy line under the ways in: there for anyone who looks, not
   standing out (Alipasha, 13 Oct 2026). */
.sign-in-note.sign-in-privacy { margin-top: 0.75rem; color: var(--muted); font-size: 0.85rem; font-weight: 400; }
/* Once the link is sent the reader is moved to the heading, which says so.
   It is not a control, so it takes no ring. */
.plumliners h1[tabindex="-1"]:focus { outline: none; }

/* ---- the box beside the ways in --------------------------------
   For plumliners, the way across for someone who came about their own
   sangha; for someone who came to add or update their sangha, the four
   steps to the Sangha Finder, each a line beside its number in the
   highlight's soft wash. One sentence to a line. */
.sign-in-box {
  margin-top: 1.5rem; padding: 1.2rem 1.4rem 0.6rem;
  background: var(--card); border: 1px solid var(--rule); border-radius: var(--radius-xs);
}
.sign-in-box h2 { font-size: 1.2rem; margin: 0 0 0.8rem; }
.sign-in-box p { margin: 0 0 0.6rem; }
.sign-in-box a { text-decoration: var(--link-underline); text-underline-offset: var(--link-offset); }
/* Check your email: what to do if the link does not come. */
.sign-in-box.check-email-box { margin-top: 0; padding-bottom: 1.3rem; max-width: 40rem; }
.check-email-box .btn { margin-top: 0.6rem; }
/* One kind of box on the sign-in pages: the two ways in, the box beside
   them and Check Your Email's are each a panel in the page's darker band,
   with a hairline, small corners and no highlight along the top. The small
   corners are Alipasha's choice for these pages, calmer than a panel's.
   Fields and the numbered steps keep the lighter surface, so they stand
   out from it. */
.sign-in-layout .card,
.sign-in-box { background: var(--ground-2); border: 1px solid var(--rule); border-radius: var(--radius-xs); }
.sign-in-layout .card.sect { border-top: 1px solid var(--rule); }
.sangha-steps li::before { background: var(--card); }
/* Beside the ways in on a wider screen: the ways in stacked in a column
   of their own, a sign-in form's width, and the box in the rest, so
   each line reads on a line. On a phone the box follows the ways in. */
@media (min-width: 761px) {
  .sign-in-layout {
    display: grid; grid-template-columns: minmax(0, 25rem) minmax(0, 1fr);
    column-gap: 1.5rem; align-items: start;
  }
  .sign-in-layout .cards { grid-template-columns: 1fr; }
  .sign-in-layout .sign-in-box { margin-top: 0; }
  /* Once the link is sent the box beside the ways in has gone, so Check
     Your Email's box may take the room, wide enough that each line reads
     on a line. */
  .sign-in-layout:has(#check-email:not([hidden])) .sign-in-main { grid-column: 1 / -1; }
}
.sign-in-layout .card > .btn { margin-top: 0.4rem; }
.sangha-steps ol { list-style: none; counter-reset: sangha-step; padding: 0; margin: 0 0 0.9rem; max-width: 40rem; }
.sangha-steps li { counter-increment: sangha-step; display: flex; gap: 0.75rem; align-items: flex-start; margin-bottom: 0.6rem; }
.sangha-steps li::before {
  content: counter(sangha-step); flex: none; display: inline-grid; place-items: center;
  width: 1.6rem; height: 1.6rem; margin-top: 0.05rem; border-radius: var(--radius-pill);
  background: var(--sect-soft); color: var(--sect-text); font-size: 0.85rem; font-weight: 600;
}
.sangha-steps .sign-in-note { color: var(--muted); font-weight: 400; }

/* ---- signed in -----------------------------------------------
   The plumliners' own page: the places they can go, and a way out. */
/* The two sign-in cards are the page's sections, so their headings are
   h2s for anyone reading by heading; they are drawn at the card size. */
.plumliners .card h2 { font-size: 1.2rem; margin: 0 0 0.3rem; }
/* The places this account can go, in one row across the page. Each takes
   an equal share of the width and no more than a card's worth, so two of
   them do not sprawl and six of them still fit at the content width. On a
   phone the row wraps. */
.account-actions { display: flex; flex-wrap: wrap; gap: 0.7rem; margin: 1.4rem 0 1rem; }
/* On My Sanghas, for someone who comes about their own sangha: a line
   and a button to add one, beneath the list when there is one. */
.my-sanghas-add > p:not(.my-sanghas-add-actions) { max-width: 40rem; }
#my-sanghas-panel:not([hidden]) ~ .my-sanghas-add { margin-top: 1.6rem; }
/* Beside a contact's list the drawing reaches down past the line under
   the heading, so the table starts a little lower to leave it room. On a
   phone the drawing steps aside, and so does the room. */
@media (min-width: 761px) {
  .plumliners main:has(#my-sanghas-art:not([hidden])) #my-sanghas-panel { margin-top: 2.5rem; }
}
/* Sign Out sits beside the button to add one. */
.my-sanghas-add-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; }
/* For someone whose sangha may be listed under another address: its way
   on is a button that reads as a link, like the links around it. */
.my-sanghas-aside { margin-top: 1.2rem; }
.my-sanghas-aside button { font: inherit; color: var(--sect-text); background: none; border: 0; padding: 0; cursor: pointer; }
.my-sanghas-aside button:hover { text-decoration: underline; }
.my-sanghas-help { margin-top: 1.6rem; max-width: 40rem; }
.my-sanghas-cell-label { display: none; }
.my-sanghas-table .to-be-assigned { color: var(--muted); }
/* A thing to open. It is pressed, so it stands out of the page like
   any other control, and takes the highlight under the pointer. */
.account-action {
  flex: 1 1 10rem; max-width: 18rem;
  display: flex; flex-direction: column; gap: 0.2rem; padding: 0.9rem 1rem;
  background: var(--card); border: 1px solid var(--rule);
  border-radius: var(--radius-xs); box-shadow: var(--lift); color: var(--ink);
}
/* On a phone there is room for one across, so each takes the width rather
   than leaving an odd one wider than the rest. */
@media (max-width: 480px) { .account-action { flex-basis: 100%; max-width: none; } }
.account-action:hover { text-decoration: none; border-color: var(--sect); }
.account-action strong { font-weight: 600; }
.account-action:hover strong { color: var(--sect-text); }
.account-action span { color: var(--muted); font-size: 0.9rem; line-height: 1.45; }

/* ---- a section of a page -------------------------------------
   The admin pages are a run of sections, each a heading with a
   table under it. The headings are a step down from the page's,
   and a count beside one is said quietly. */
.plumliners .section { margin-top: 2rem; }
.plumliners .section h2, .plumliners .card h2 { font-size: 1.2rem; margin: 0 0 0.3rem; }
.plumliners .section > p { color: var(--muted); margin: 0 0 0.8rem; max-width: 64ch; }
.plumliners .count { color: var(--muted); font-size: 0.95rem; font-weight: 500; }
/* A heading with the one thing to do beside it. */
.plumliners .section-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin-bottom: 0.7rem;
}
.plumliners .section-head p { margin: 0; color: var(--muted); }
/* ---- a page in parts -----------------------------------------
   A page of several lists has a link for each under its head, in a pale
   band with a shadow falling from it, as the public site's bar has
   (Alipasha, 16 Oct 2026). The links are tabs: plain words, the list shown
   in the plumliners' indigo with an indigo line under it along the band's
   foot (Dan's review, 16 Oct 2026). Beside each name, quietly, how many it
   holds. The list shown has its tools, its filter and Columns, at the
   right of the band. On a laptop or wider the band stays at the top of the
   window while a long list scrolls, with the list's headings under it. */
.plumliners .part-links { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.6rem 1.25rem; }
.plumliners .part-links.band {
  align-items: stretch;
  margin: 0 0 1.5rem; min-height: 3.1rem;
  padding: 0 max(20px, calc((100% - var(--maxw)) / 2 + 20px));
  background: var(--ground-2); border-bottom: 1px solid var(--rule);
  box-shadow: 0 1px 4px oklch(from var(--charcoal) l c h / 14%);
}
.plumliners .part-links.band .part-tools { align-items: center; padding-block: 0.55rem; }
body.plumliners.has-rail main > .hero:has(+ .part-links:not([hidden])) { margin-bottom: 0; }
/* On a sangha's own page, between its head and its details, on the page's
   ground, the tabs standing on a line. */
.plumliners .part-links.inline { margin: 1.1rem 0 1.25rem; border-bottom: 1px solid var(--rule); }
.plumliners .part-links-list { display: flex; flex-wrap: wrap; align-items: stretch; gap: 0 0.25rem; max-width: 100%; margin-left: -0.75rem; }
.plumliners .part-links-list a {
  display: inline-flex; align-items: center; gap: 0.4em;
  padding: 0.75rem 0.75rem 0.6rem; margin-bottom: -1px;
  border-bottom: 3px solid transparent;
  font-size: 0.95rem; white-space: nowrap; text-decoration: none;
  color: var(--ink);
}
/* A tab, so no link's underline under the pointer (site.css nav a:hover); a
   faint line under it instead. */
.plumliners .part-links-list a:hover { text-decoration: none; }
.plumliners .part-links-list a:hover:not([aria-current]) { border-bottom-color: var(--rule); }
.plumliners .part-links-list a[aria-current] { color: var(--accent-strong); border-bottom-color: var(--accent-strong); }
.plumliners .part-links-list a:focus-visible { outline: var(--focus-ring); outline-offset: -3px; border-radius: var(--radius-xs); }
/* On a phone the tabs take the band's width, each list an equal share of
   it, a long name going onto a second line in its own tab. Five tabs or
   more, as on the Audit Log, go three to a row. */
@media (max-width: 760px) {
  .plumliners .part-links-list { width: calc(100% + 1.5rem); margin-inline: -0.75rem; gap: 0; }
  .plumliners .part-links-list a {
    flex: 1 1 0; min-width: 0; justify-content: center; flex-wrap: wrap; gap: 0 0.3em;
    padding: 0.65rem 0.35rem 0.5rem; white-space: normal; text-align: center; line-height: 1.2;
  }
  .plumliners .part-links-list:has(> a:nth-of-type(5)) a { flex: 1 0 33%; }
}
.plumliners .part-count { color: var(--muted); font-size: 0.88em; font-variant-numeric: tabular-nums; }
.plumliners .part-count:empty { display: none; }
.plumliners .part-tools { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.6rem; }
.plumliners .part-off { display: none !important; }
.plumliners .part:is(.section, .card) { margin-top: 0; }
/* Read from top to bottom, as Website Status is, each part keeps its room above it. */
.plumliners main:has(> .part-links[data-mode="scroll"]) .part:is(.section, .card) { margin-top: 2rem; }
@media (min-width: 761px) {
  .plumliners .part-links.band { position: sticky; top: 0; z-index: 6; }
  /* The rows run the page's length, so a table's box no longer scrolls;
     cut at its corners rather than scrolling, its headings can stay under
     the band. One too wide for the page scrolls sideways in its box again.
     Only under the band: on a sangha's own page the lists' links sit in
     the page and do not stay. */
  .plumliners main:has(> .part-links.band) .part .table-box:not(.too-wide):has(> table) { overflow: clip; }
  .plumliners main:has(> .part-links.band) .part .table-box:not(.too-wide) > table > thead th { position: sticky; top: var(--part-links-height, 0px); z-index: 2; }
  .plumliners .part .table-box > .list-more { position: static; }
}

/* What a page is for, kept out of the way: one "?" beside its title,
   dressed as the band's other button and at least 24px across, and, once
   it is pressed, one note under the title for the whole page, list by
   list, over what follows rather than pushing it down (Alipasha, 16 Oct
   2026). Hovering shows nothing; a press again, Escape, or a press
   elsewhere puts it away. */
.plumliners .page-help-toggle {
  display: inline-grid; place-items: center; width: 1.6rem; height: 1.6rem; min-height: 0;
  margin-left: 0.35rem; padding: 0; vertical-align: 0.33em;
  border-radius: var(--radius-pill); font-size: 0.95rem; font-weight: 600; line-height: 1;
}
.plumliners .page-help {
  position: absolute; z-index: 10;
  width: max-content; max-width: min(36rem, calc(100vw - 2rem));
  padding: 0.65rem 0.9rem; border: 1px solid var(--rule); border-radius: var(--radius-xs);
  background: var(--card); box-shadow: var(--shadow); color: var(--muted); font-size: 0.95rem;
}
.plumliners .page-help p { margin: 0; }
.plumliners .page-help p + p, .plumliners .page-help p + .page-help-more { margin-top: 0.3rem; }
.plumliners .page-help-more > p + p { margin-top: 0.3rem; }
.plumliners .page-help strong, .plumliners .page-help .page-help-name { color: var(--ink); font-weight: 600; }
.plumliners .page-help-part + .page-help-part { margin-top: 0.85rem; padding-top: 0.75rem; border-top: 1px solid var(--rule); }
/* Beside the menu, the note keeps inside the page's own column: the window
   less the menu and the page's two 20px margins. Measured against the
   window alone, it ran past the right edge and the page scrolled sideways. */
@media (min-width: 761px) {
  body.plumliners.has-rail .page-help { max-width: min(36rem, calc(100vw - var(--plumliners-rail) - 40px)); }
}
/* A card that is a section of the page keeps its distance from the next. */
.plumliners section.card { margin: 1.5rem 0; }
/* A card whose words sit beside its control rather than above it. */
.plumliners #application-settings-panel { display: flex; flex-direction: column; gap: 1rem; }
.plumliners .card.row-card { flex-direction: row; align-items: center; justify-content: space-between; gap: 1.5rem; }
.plumliners .card.row-card p { max-width: 60ch; }
.plumliners .card.row-card p:last-child { margin-bottom: 0; }
.plumliners .card.row-card > .btn, .plumliners .card.row-card > .check { flex: 0 0 auto; }

/* ---- a toolbar -----------------------------------------------
   The row above a page's content: the buttons that act on all of
   it, and a line that says how it is getting on, pushed to the
   right. */
.plumliners .toolbar { display: flex; align-items: center; flex-wrap: wrap; gap: 0.6rem; margin: 0 0 1rem; }
.plumliners .toolbar .status { margin-left: auto; color: var(--muted); font-size: 0.9rem; }
/* The one small line of type at the foot of the page: which build this is. */
.plumliners .build-info { margin: 1.6rem 0 0; color: var(--muted); font-size: 0.8rem; text-align: right; }
.plumliners .build-info a { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-weight: 600; }

/* ---- a form with several fields across ------------------------
   The public .field, set side by side where there is room. A
   select is a control you press, so it stands out where a field
   sinks in: the white button, with a small arrow at its right in
   place of the browser's own, as Columns has (Alipasha, 21 Oct 2026). */
.plumliners .fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); gap: 0 1rem; }
.plumliners .field select {
  width: 100%; font: inherit; font-size: var(--control-font); line-height: var(--control-line); color: var(--ink);
  appearance: none; -webkit-appearance: none;
  background: var(--menu-arrow), var(--white-face); border: var(--control-border) solid var(--white-face-edge);
  border-radius: var(--radius-xs); padding: 0 2rem 0 var(--control-pad-x);
  /* A menu takes its own line height, so its height is said outright
     and its words sit in the middle of it. */
  height: var(--control-height);
  box-shadow: var(--white-face-lines);
  cursor: pointer;
}
.plumliners .field select:hover { background: var(--menu-arrow), var(--white-face-hover); }
.plumliners .field select:focus { outline: var(--focus-ring); outline-offset: 2px; }
.plumliners .field :is(input, select, textarea):disabled { opacity: 0.6; cursor: not-allowed; }
.plumliners .check:has(input:disabled) { cursor: not-allowed; }
/* A checkbox and its words, read as one thing. */
.plumliners .check { display: flex; align-items: center; gap: 0.6rem; font-weight: 500; cursor: pointer; }
.plumliners .check input { width: 1.15rem; height: 1.15rem; margin: 0; accent-color: var(--accent-strong); }
/* The buttons that end a form or a dialog: the way out on the left,
   the thing that acts on the right. */
.plumliners .actions { display: flex; justify-content: space-between; align-items: center; gap: 0.8rem; margin-top: 1rem; }
/* The one button that undoes or removes. Not filled: nothing on
   this side is filled but the button that acts. */
.plumliners .btn-danger { color: var(--unwhole-text); border-color: var(--unwhole); }
.plumliners .btn-danger:hover { background: var(--unwhole-soft); border-color: var(--unwhole); }
.plumliners .btn:disabled, .plumliners .btn[disabled] { opacity: 0.6; cursor: default; box-shadow: none; }
/* A key shown once, to be copied. */
.plumliners .secret {
  display: block; padding: 0.9rem 1rem; overflow-wrap: anywhere; -webkit-user-select: all; user-select: all;
  background: var(--ground-2); border: 1px solid var(--rule); border-radius: var(--radius-xs);
  font-size: 0.95rem;
}

/* ---- a lightbox on the plumliners' side ------------------------
   The public lightbox, with a line under its heading and room
   for a table instead of a form. Its head is drawn like a page's
   head: the band, with the rail's light words on it. The title sits
   in the middle, any way out on the left, and what acts on the right
   (Alipasha, 10 Oct 2026). Its buttons give it height enough, so it has
   less room above and below than the public one (11 Oct 2026). */
.plumliners .lightbox-head {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  padding-block: 0.6rem;
  background: var(--band); border-bottom-color: var(--band-line); color: var(--rail-text);
  text-align: center;
}
.plumliners .lightbox-head > * { grid-row: 1; grid-column: 2; }
.plumliners .lightbox-head > :is(button, form, .lightbox-head-end) { grid-column: 3; justify-self: end; }
.plumliners .lightbox-head > .lightbox-head-start { grid-column: 1; justify-self: start; }
.plumliners .lightbox-head-end { display: flex; gap: 0.6rem; }
/* Back in a head a page in the layer draws itself shows only once there
   is a page to go back to (in-layer.js). */
html:not(.layer-can-go-back) .layer-back { display: none; }
.plumliners .lightbox-head :is(h1, h2) { margin: 0; font-size: 1.35rem; color: var(--rail-text); }
.plumliners .lightbox-head p { margin: 0.25rem 0 0; color: var(--rail-text); font-size: 0.95rem; }
.plumliners .lightbox-head :focus-visible { outline-color: var(--rail-text); }
/* Its buttons are dark buttons, as a page head's are (above). */
.plumliners .lightbox-head .btn { white-space: nowrap; }
.plumliners .lightbox-body > p:last-child { margin-bottom: 0; }
/* On a phone the title takes the room its buttons leave, and with buttons
   on both sides it goes on a line of its own under them, and those on the
   right take the room it leaves. Too many for one line, as an affinity's
   four are, they go onto a second. */
@media (max-width: 760px) {
  .plumliners .lightbox-head { grid-template-columns: auto minmax(0, 1fr) auto; row-gap: 0.8rem; }
  .plumliners .lightbox-head-end { flex-wrap: wrap; justify-content: flex-end; }
  .plumliners .lightbox-head:has(> .lightbox-head-start:not([hidden])) > .lightbox-head-end { grid-column: 2 / -1; }
  .plumliners .lightbox-head:has(> .lightbox-head-start:not([hidden])) > :not(.lightbox-head-start, .lightbox-head-end, button, form) { grid-row: 2; grid-column: 1 / -1; }
}
.plumliners .lightbox-head form { margin: 0; }
.plumliners .lightbox.wide { width: min(64rem, calc(100vw - 2rem)); }
/* An affinity's box has four buttons in its head and its name between them. */
.plumliners #affinity-dialog { width: min(42rem, calc(100vw - 2rem)); }
/* A box's note, under its head and over its fields. */
.plumliners .lightbox-body > .field-note:first-child { margin: 0 0 1rem; }
/* A sangha's own page in a layer over the list it was chosen from
   (sangha-layer.js), nearly as big as the window, the page itself in a
   frame that fills it. */
.plumliners .lightbox.layer { width: min(72rem, calc(100vw - 2rem)); height: calc(100dvh - 2rem); max-height: none; overflow: hidden; }
.plumliners .lightbox.layer[open] { display: flex; flex-direction: column; }
.plumliners .lightbox.layer .lightbox-head { align-items: center; }
.plumliners .lightbox.layer .layer-body { flex: 1; min-height: 0; }
.plumliners .lightbox.layer iframe { display: block; width: 100%; height: 100%; border: 0; }
/* The page itself, inside the layer: no menu, no footer, no way back to the
   list it is already over (in-layer.js). */
html.in-layer body.plumliners:has(.plumliners-nav) { display: block; }
html.in-layer :is(.skip, .site-header, .plumliners-nav, .site-footer, .breadcrumbs) { display: none; }
/* A sangha's form, in the layer, draws the layer's head itself, with its
   buttons in it (new-sangha.js), and stands in for the layer's own. The
   head stays at the top as the form moves under it, and takes the place of
   the page's head and of the buttons at its foot. */
.plumliners .layer-head { position: sticky; top: 0; z-index: 3; }
html:has(> body.has-layer-head) { scroll-padding-top: 5.5rem; }
.has-layer-head main > .hero, .has-layer-head .new-sangha-actions { display: none; }
.has-layer-head main { padding-top: 1.5rem; }
.has-layer-head #new-sangha-notice { margin: 0 0 1rem; }
/* On a sangha's own page, a line such as that it was saved sits over the
   sangha's column, with room above it. */
.plumliners main > .wrap:has(> #sangha-notice) { max-width: 56rem; }
.plumliners #sangha-notice { margin: 1.5rem 0 0; }
.plumliners .lightbox .fields { margin-bottom: 0.2rem; }
.plumliners .lightbox .form-status { margin-top: 0.6rem; }

/* ---- a table -------------------------------------------------
   Read, not pressed: the card surface in a hairline box with the
   controls' corner, and flat. The head is a narrow band of the
   second ground, set small and quiet, so the rows carry the words.
   The rows take turns between the card and a breath of the band
   rather than each having a line under it, so the eye follows a
   row across without stepping over lines. A row a filter has
   hidden, or a change's own detail opened under it, does not
   count, so the turns stay even. On a phone the box scrolls
   sideways rather than breaking its rows. */
.plumliners .table-box {
  overflow-x: auto; max-width: 60rem;
  background: var(--card); border: 1px solid var(--rule); border-radius: var(--radius-xs);
}
.plumliners table { width: 100%; border-collapse: collapse; font-size: 0.95rem; }
.plumliners th, .plumliners td {
  text-align: left; vertical-align: top; padding: 0.5rem 0.9rem;
}
.plumliners table:not(.change-values) > tbody > tr { background: var(--card); }
.plumliners table:not(.change-values) > tbody > tr:nth-child(even of :not([hidden], .change-detail)) {
  background: color-mix(in srgb, var(--ground-2) 70%, var(--card));
}
.plumliners thead th {
  padding-block: 0.3rem;
  background: var(--ground-2); color: var(--muted); white-space: nowrap;
  border-bottom: 1px solid var(--rule);
  font-size: 0.75rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
}
.my-sanghas-table th:last-child,
.my-sanghas-table td:last-child { width: 1%; white-space: nowrap; }
/* Recently Deleted, on Sanghas and on Groups: each row's words level with its Recover button. */
.plumliners :is(.removed-sanghas-table, .deleted-groups-table) td { vertical-align: middle; }
.plumliners :is(.removed-sanghas-table, .deleted-groups-table) td:last-child { width: 1%; white-space: nowrap; }
/* A table with many columns takes the page's whole width and fits in
   it: its headings and cells wrap, a little closer together, and on a
   narrower page its row's buttons stack, so the whole table shows
   without scrolling on a laptop or wider. Only on a phone does the box
   scroll sideways (below). */
.plumliners .table-box.wide { max-width: none; }
.plumliners .api-client-table thead th { white-space: normal; }
.plumliners .api-client-table :is(th, td) { padding-inline: 0.65rem; }
/* An email address has no spaces to wrap at, so it may break anywhere,
   though not into a sliver; a key, a limit or a count keeps to one line. */
.plumliners .api-client-table td:nth-child(2) { overflow-wrap: anywhere; min-width: 10rem; }
.plumliners .api-client-table td:nth-child(3), .plumliners .api-client-table td:nth-child(4), .plumliners .api-client-table td:nth-child(6),
.plumliners .api-client-table td:nth-child(7), .plumliners .api-client-table td:nth-child(8) { white-space: nowrap; }
/* The Plumliners page: each team and who is in it, each role and who holds
   it (the two lists look alike); then everyone, with the name they go by,
   their email, their teams and every role they hold, the roles with the
   most room. Too long for its column, anything wraps, and the row grows to
   hold it. An admin's rows open a person's box, and light up under the
   pointer. */
.plumliners :is(.plumliners-table, .plumliner-roles-table, .plumliner-changes-table) { table-layout: fixed; }
.plumliners .plumliner-changes-table .col-when { width: 16%; }
.plumliners .plumliner-changes-table .col-who { width: 13%; }
.plumliners .plumliners-table .col-name { width: 14%; }
.plumliners .plumliners-table .col-teams { width: 20%; }
.plumliners .plumliners-table .col-email { width: 30%; }
.plumliners .plumliner-roles-table .col-role { width: 16%; }
.plumliners .plumliner-roles-table .col-email { width: 30%; }
/* Beside the Plumliners heading, the group's own address, in the page's
   own words rather than a link's colour; it still opens an email. */
.plumliners .part-tools .group-address { align-self: center; color: var(--ink); font-weight: 400; text-decoration: none; }
.plumliners .part-tools .group-address:hover { text-decoration: underline; }
.plumliners :is(.plumliners-table, .plumliner-roles-table, .plumliner-changes-table) td,
.plumliners .plumliners-table .email-line .cut { white-space: normal; overflow-wrap: anywhere; }
.plumliners :is(.plumliners-table, .plumliner-roles-table) tr.row-link { cursor: pointer; }
.plumliners :is(.plumliners-table, .plumliner-roles-table) tbody tr:is(.row-link:hover, .row-link:focus-visible, .is-chosen) > td { background: var(--accent-soft); }
/* A press on a role keeps it lit, and Plumliners says whose rows it shows. */
.plumliners .plumliner-roles-table tr.is-chosen > td:first-child { font-weight: 600; }
/* In a plumliner's box, a tick for each role, in columns; in a sangha's
   box on a group's page, the same for each group it could be in. */
.plumliners .roles-field { border: 0; margin: 0; padding: 0; min-width: 0; }
/* The roles to tick, down one column and then the next, two at most. */
.plumliners .roles-ticks { columns: 10rem 2; column-gap: 1rem; margin: 0.3rem 0 0.5rem; }
.plumliners .roles-ticks .check { font-weight: 400; break-inside: avoid; margin-bottom: 0.4rem; }
/* The Google Groups to change by hand: a part for each thing to do, the
   address with the button that copies it, then the groups, each a link to
   its members. One press chooses the whole address, to copy by hand. */
.plumliners .group-change + .group-change { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--rule); }
.plumliners .group-change h3 { margin: 0 0 0.5rem; font-size: 1rem; }
.plumliners .group-change-email { display: flex; align-items: center; margin: 0 0 0.3rem; }
.plumliners .group-change-label { flex: none; width: 2.6rem; color: var(--muted); }
.plumliners .group-change-address { min-width: 0; overflow-wrap: anywhere; user-select: all; }
.plumliners .group-change-email .copy-button { flex: none; margin-block: 0; }
.plumliners .group-change-links { margin: 0.5rem 0 0; padding-left: 1.2rem; }
.plumliners .group-change-links li + li { margin-top: 0.2rem; }
/* What the scripts write into a cell: a row with nothing in it, and a
   value that is only there for completeness. */
.plumliners .empty-cell, .plumliners .muted-cell { color: var(--muted); }
/* Affinities, laid out as Groups is (Alipasha, 16 Oct 2026): the mark in
   a narrow column, the name with the room, and how many sanghas list it.
   Named with Groups' own class, so these widths win over Groups'. */
.plumliners .sangha-groups-table.affinities-table .col-name { width: auto; }
.plumliners .sangha-groups-table.affinities-table .col-count { width: 10%; }
/* The buttons in a row's last cell, side by side. Not a flex box: it is
   the cell itself, and a cell that stops being a cell loses its place in
   the row. */
.plumliners .api-client-actions { white-space: nowrap; }
.plumliners .api-client-actions > * + * { margin-left: 0.4rem; }
/* Where the page is narrower than a laptop's, they stack, so the table
   still fits across it. */
@media (max-width: 1100px) {
  .plumliners td.api-client-actions > .compact-button { display: flex; width: max-content; }
  .plumliners td.api-client-actions > .compact-button + .compact-button { margin: 0.35rem 0 0; }
}

/* The small buttons the sangha form, My Sanghas and Settings write,
   still under the class names they had under styles.css. They are the
   public side's white button (site.css .btn-ghost), a size down, as
   every other button on a light ground is: on the plumliners' side since
   16 Oct 2026, and on a sangha contact's pages too since 21 Oct, where
   they had stayed the older flat ones beside the white (Alipasha). A
   meeting's Remove keeps its red edge and red words. */
.plumliners .secondary-button.compact-button {
  display: inline-flex; align-items: center;
  font-family: var(--font); font-size-adjust: var(--x-height); font-weight: 400; font-size: 0.85rem; line-height: 1.2;
  padding: 0.35em 0.8em; border-radius: var(--radius-xs);
  border: 1.5px solid var(--white-face-edge); background: var(--white-face); color: var(--ink);
  box-shadow: var(--white-face-lines); text-decoration: none;
}
.plumliners .secondary-button.compact-button:hover { background: var(--white-face-hover); text-decoration: none; }
.plumliners .secondary-button.danger-button { border-color: var(--unwhole); color: var(--unwhole-text); }

/* ---- smaller buttons -----------------------------------------
   The same button, a size down, for the ones that sit in a table
   row or beside a count; and one that is only an icon, square. */
.plumliners .btn-small { font-size: 0.85rem; padding: 0.35em 0.8em; }
.plumliners .btn-icon { padding: 0.45em; line-height: 0; }
.plumliners .btn-icon svg { width: 1rem; height: 1rem; }

/* ---- Manage Sanghas ---------------------------------------------
   The list of sangha groups, a group's own page, and the page for
   adding sanghas to it. Each is a run of sections, a heading and a
   table, like the rest of this side. */
/* A heading with a small button beside it, such as the pencil that
   renames a group. */
.plumliners .title-row { display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap; margin-bottom: clamp(0.95rem, 2.5vw, 1.5rem); }
.plumliners .title-row h1 { margin: 0; overflow-wrap: anywhere; }
/* Where a table would be a single empty row, a sentence instead. */
.plumliners .empty-note {
  margin: 0; padding: 0.9rem 1rem; max-width: 60rem;
  background: var(--card); border: 1px dashed var(--rule); border-radius: var(--radius-xs);
  color: var(--muted);
}
.plumliners .empty-note p { margin: 0; }
.plumliners .empty-note p + p { margin-top: 0.5rem; }
.plumliners .empty-note strong { color: var(--ink); font-weight: 600; }
/* A note with a table after it, as when someone looks after no groups but
   is the contact for a sangha, keeps its distance from the table. */
.plumliners .empty-note:not([hidden]) + .table-box { margin-top: 0.8rem; }
/* In a muted sentence the highlight alone is not enough to say "press
   here", so a link in one is underlined as well. */
.plumliners .empty-note a { text-decoration: var(--link-underline); text-underline-offset: var(--link-offset); font-weight: 500; }
/* The buttons beside a section's heading. */
.plumliners .head-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; }
/* A search that narrows the table under it. */
.plumliners .list-search { margin: 0 0 0.8rem; max-width: 22rem; }
.plumliners .list-search .field { margin: 0; }
/* Beside the heading, or in the band of a page's lists, on the right, the
   search costs the page no height of its own: its words sit in the box,
   and its label is for screen readers. On a narrow screen it drops under
   the heading or the links, full width. */
.plumliners .section-head:has(.list-search) { align-items: center; }
.plumliners :is(.section-head, .part-tools) .list-search { flex: 0 1 18rem; width: 18rem; margin: 0; }
.plumliners :is(.section-head, .part-tools) .list-search input { padding-block: var(--control-pad-y); line-height: var(--control-line); }
.plumliners .list-search input::placeholder { color: var(--muted); opacity: 1; }
@media (max-width: 700px) {
  .plumliners :is(.section-head, .part-tools) .head-actions,
  .plumliners :is(.section-head, .part-tools) .list-search { flex: 1 1 100%; width: 100%; max-width: none; }
}
/* A column heading is a button that sorts the table by its column, with an
   arrow for which way once pressed. It keeps the heading's own small type. */
.plumliners .sort-button {
  padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
}
.plumliners .sort-button:hover, .plumliners th[aria-sort] .sort-button { color: var(--ink); }
/* A finger's worth of room to press round its small words, out into the
   heading's own padding, without making the heading any bigger. */
.plumliners .sort-button { padding: 0.3rem 0.35rem; margin: -0.3rem -0.35rem; }
.plumliners .sort-button:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
/* The arrow first on its own, for a browser that cannot yet be told to
   leave it unread (Safari before 17.4). */
.plumliners th[aria-sort="ascending"] .sort-button::after { content: " ↑"; content: " ↑" / ""; }
.plumliners th[aria-sort="descending"] .sort-button::after { content: " ↓"; content: " ↓" / ""; }
/* A page whose few buttons sit at the right of its title, level with it,
   instead of on a row of their own; under it on a phone. */
.plumliners .page-title-row { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem 1.5rem; flex-wrap: wrap; }
.plumliners .page-title-row h1 { margin: 0; }
.plumliners .page-title-row .toolbar { margin: 0; }
/* A coordinator's lead, or a plumliner's own groups, under the page's title. */
.plumliners .lead-line { margin: 0.6rem 0 0.4rem; color: var(--muted); }
.plumliners .lead-line strong { color: var(--ink); font-weight: 600; }
/* A small button beside an email address that copies it, and one on the
   Email heading that copies them all; a tick for a moment once copied.
   The pencil beside Private Notes, which opens them for writing, is drawn
   the same way. */
.plumliners :is(.copy-button, .icon-button) {
  display: inline-grid; place-items: center; width: 1.5rem; height: 1.5rem;
  margin: -0.35rem 0 -0.15rem 0.3rem; padding: 0; vertical-align: middle;
  border: 0; border-radius: var(--radius-xs); background: none; color: var(--muted); cursor: pointer;
}
.plumliners :is(.email-line, .phone-line) { display: flex; align-items: center; min-width: 0; }
.plumliners :is(.email-line, .phone-line) .cut { flex: 0 1 auto; min-width: 0; }
.plumliners :is(.email-line, .phone-line) .copy-button { flex: none; }
.plumliners :is(.copy-button, .icon-button) svg {
  width: 0.95rem; height: 0.95rem; fill: none; stroke: currentColor; stroke-width: 1.4;
  stroke-linecap: round; stroke-linejoin: round;
}
.plumliners :is(.copy-button, .icon-button):hover { color: var(--ink); background: var(--ground-2); }
.plumliners :is(.copy-button, .icon-button):focus-visible { outline: var(--focus-ring); outline-offset: 1px; }
.plumliners .copy-button.copied { color: var(--whole-text); }
/* At the foot of a list, inside its box as the table's last line: a button
   for more, at the right (Alipasha, 10 and 12 Oct 2026; how many there are
   is said above the list since 16 Oct). It wears the head's band, and
   stays in view while a wide table scrolls sideways. */
.plumliners .list-more { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 0.5rem 0.6rem; }
.plumliners .table-box > .list-more {
  position: sticky; left: 0; bottom: 0; z-index: 1;
  margin: 0; padding: 0.35rem 0.9rem;
  background: var(--ground-2); border-top: 1px solid var(--rule);
}
/* The tables: a count and the row's buttons take only the room they
   need, and the sanghas' table, with its many columns, scrolls
   sideways in its box rather than squeezing them. */
/* A column of numbers sits in the middle of its column, in the typeface's
   own figures of one width where it has them. */
.plumliners .sangha-groups-table :is(th.count-col, td.count-cell) {
  width: 1%; white-space: nowrap; text-align: center; font-variant-numeric: tabular-nums;
}
.plumliners .sangha-group-sanghas-table th:last-child { width: 1%; }
/* Your Sanghas and All Sanghas line up, column over column.
   The names are kept narrow so the notes have the room; a long
   name, note or anything else too long for its column ends in an
   ellipsis on one line, and shows whole on hover. */
.plumliners .aligned-table, .plumliners .sangha-groups-table { table-layout: fixed; }
/* A list of sanghas shows the columns chosen under Columns, and hides the
   rest. The script sets --share, how many times the usual table's width
   the columns now need; past the usual, the table scrolls sideways in its
   box. Wider than a phone, the marks and names stay at the left, with a
   hairline, and the columns after them scroll. The script measures the marks' column, as --marks-width, so the
   names stand just past it. */
.plumliners .aligned-table.hide-country .cell-country,
.plumliners .aligned-table.hide-region .cell-region,
.plumliners .aligned-table.hide-languages .cell-languages,
.plumliners .aligned-table.hide-affinities .cell-affinities,
.plumliners .aligned-table.hide-type .cell-type,
.plumliners .aligned-table.hide-group .cell-group,
.plumliners .aligned-table.hide-groups .cell-groups,
.plumliners .aligned-table.hide-contact .cell-contact,
.plumliners .aligned-table.hide-coordinator .cell-coordinator,
.plumliners .aligned-table.hide-email .cell-email,
.plumliners .aligned-table.hide-notes .cell-notes,
.plumliners .aligned-table.hide-confirmed .cell-confirmed { display: none; }
.plumliners .aligned-table { min-width: calc(var(--share, 1) * 100%); }
@media (min-width: 701px) {
  .plumliners .aligned-table.wider :is(th, td):first-child { position: sticky; left: 0; z-index: 1; }
  .plumliners .aligned-table.wider :is(th, td):nth-child(2) {
    position: sticky; left: var(--marks-width, 0); z-index: 1; box-shadow: inset -1px 0 0 var(--rule);
  }
  /* The row's own tone, so a held column takes its turn with the rest. */
  .plumliners .aligned-table.wider :is(td:first-child, td:nth-child(2)) { background: inherit; }
}
/* Columns sits beside the filter, as tall as it, and opens to its left. */
.plumliners .columns-menu > summary { padding-block: var(--control-pad-y); line-height: var(--control-line); }
.plumliners .columns-menu .excel-filter-menu { left: auto; right: 0; width: 12rem; }
.plumliners .columns-menu .excel-filter-options { padding-top: 0; }
.plumliners .aligned-table .col-status { width: 3%; }
.plumliners .aligned-table .col-name { width: 22%; }
/* Groups gives its names the room the Open buttons had; a longer one still
   ends in an ellipsis and shows whole on hover, as on Sanghas. */
.plumliners .sangha-groups-table .col-status { width: 4%; }
.plumliners .sangha-groups-table .col-name { width: 36%; }
/* Before the script gives each column its share, the same shares as
   sangha-groups.js's: Notes wide, a first name and a few months narrow
   (Alipasha, 16 Oct 2026). */
.plumliners .aligned-table .col-contact { width: 8%; }
.plumliners .sangha-groups-table .col-count { width: 9%; }
.plumliners .aligned-table .col-email { width: 20%; }
.plumliners .aligned-table .col-notes { width: 40%; }
.plumliners .aligned-table .col-confirmed { width: 8%; }
/* Months since confirmed, a small number under its heading, both centred. */
.plumliners .aligned-table .cell-confirmed { text-align: center; white-space: nowrap; }
.plumliners .sangha-groups-table .col-people { width: 51%; }
/* In a list of sanghas or groups each mark has a narrow column of its own,
   its heading a quiet mark of the same kind, so the column can be sorted. */
.plumliners :is(.aligned-table, .sangha-groups-table) :is(th.status-col, td.status-cell) { padding-inline: 0.2rem; text-align: center; }
.plumliners :is(.aligned-table, .sangha-groups-table) td.status-cell .status-mark { vertical-align: 0.17em; }
.plumliners .status-mark.label { background: none; color: var(--muted); box-shadow: inset 0 0 0 1px currentColor; }
/* Sorted by the marks, the heading's arrow hangs just beside its mark, so
   the mark stays over the middle of the column, above the marks below. */
.plumliners :is(.aligned-table, .sangha-groups-table) th.status-col .sort-button { position: relative; }
.plumliners :is(.aligned-table, .sangha-groups-table) th.status-col .sort-button::after { position: absolute; top: 50%; left: 100%; margin-left: -0.25rem; transform: translateY(-50%); }
/* Groups' Coordinators: a short name, Email with its copy button, Groups
   with the most room, and how many sanghas in the middle of the last
   column. */
.plumliners .people-table .col-name { width: 16%; }
.plumliners .people-table .col-email { width: 28%; }
.plumliners .people-table .col-groups { width: 47%; }
.plumliners .people-table .col-count { width: 9%; }
/* On a phone, Groups' two tables fit the screen rather than slide
   sideways (Alipasha, 10 Oct 2026). Each row becomes a short block, as on
   My Sanghas, with how many sanghas kept on the right: a group's name, and
   under it who looks after it; a coordinator's name, and under it their
   email and their groups. The headings stay, to sort by. */
@media (max-width: 700px) {
  .plumliners .sangha-groups-table, .plumliners .sangha-groups-table :is(thead, tbody) { display: block; }
  .plumliners .sangha-groups-table colgroup { display: none; }
  .plumliners .sangha-groups-table tr { display: grid; align-items: start; border-bottom: 1px solid var(--rule); }
  .plumliners .sangha-groups-table tbody tr { padding-block: 0.35rem; }
  .plumliners .sangha-groups-table tbody tr:last-child { border-bottom: 0; }
  .plumliners .sangha-groups-table tbody tr.row-link:hover { background: var(--accent-soft); }
  .plumliners .sangha-groups-table :is(th, td) { padding: 0.15rem 0.6rem; border-bottom: 0; }
  .plumliners .sangha-groups-table th { padding-block: 0.5rem; }
  .plumliners .sangha-groups-table td.empty-cell { grid-column: 1 / -1; }
  .plumliners .sangha-groups-table :is(th.count-col, td.count-cell) { grid-area: count; width: auto; }
  .plumliners .sangha-groups-table td .row-name { white-space: normal; }
  .plumliners .groups-table tr {
    grid-template-columns: 2rem minmax(0, 1fr) 5.5rem;
    grid-template-areas: "mark name count" ". people count";
  }
  .plumliners .groups-table :is(th, td):nth-child(1) { grid-area: mark; }
  .plumliners .groups-table :is(th, td):nth-child(2) { grid-area: name; }
  .plumliners .groups-table td:nth-child(3) { grid-area: people; color: var(--muted); white-space: normal; }
  .plumliners .groups-table th:nth-child(3), .plumliners .groups-table td.is-empty { display: none; }
  /* An affinity's mark, its name, and how many sanghas list it, on one line. */
  .plumliners .affinities-table tr { grid-template-columns: 2rem minmax(0, 1fr) 5.5rem; grid-template-areas: "mark name count"; }
  .plumliners .affinities-table :is(th, td):nth-child(1) { grid-area: mark; }
  .plumliners .affinities-table :is(th, td):nth-child(2) { grid-area: name; }
  .plumliners .people-table tr {
    grid-template-columns: minmax(0, 1fr) 5.5rem;
    grid-template-areas: "name count" "email count" "groups count";
  }
  .plumliners .people-table thead tr { grid-template-columns: auto minmax(0, 1fr) 5.5rem; grid-template-areas: "name email count"; }
  .plumliners .people-table :is(th, td):nth-child(1) { grid-area: name; }
  .plumliners .people-table :is(th, td):nth-child(2) { grid-area: email; }
  .plumliners .people-table td:nth-child(2) { color: var(--muted); }
  .plumliners .people-table td:nth-child(3) { grid-area: groups; white-space: normal; }
  .plumliners .people-table th:nth-child(3) { display: none; }
}
.plumliners :is(.aligned-table, .sangha-groups-table) td {
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.plumliners td .cut { display: block; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

/* A sangha's recent changes, below its page and as wide as it. Its rows
   wrap rather than cut, and a row opens onto what it changed, before and
   after, on the page's ground. */
.plumliners .sangha-changes { max-width: 56rem; margin-bottom: 2.5rem; }
.plumliners .sangha-changes > p { margin: 0 0 0.8rem; color: var(--muted); }
/* A date and a first name need little; what changed takes the rest. The
   date keeps to one line, as long as "28 Sept 2026, 10:38 pm". */
.plumliners .changes-table .col-when { width: 12rem; }
.plumliners .changes-table .col-who { width: 13%; }
.plumliners .changes-table .col-change { width: auto; }
.plumliners .aligned-table.changes-table td { white-space: normal; overflow-wrap: anywhere; }
.plumliners .changes-table tr.change-detail > td { padding: 0.8rem 1rem 1rem; }
/* An opened change and what it changed read as one (Alipasha, 17 Oct
   2026): both in the colour a pressed row takes, apart from the stripes
   of the rows round them, with a line of the accent down their left. */
.plumliners .changes-table > tbody > tr:is(.row-link[aria-expanded="true"], .change-detail) > td { background: var(--accent-soft); }
.plumliners .changes-table > tbody > tr.row-link[aria-expanded="true"] > td:first-child,
.plumliners .changes-table > tbody > tr.change-detail > td { box-shadow: inset 3px 0 0 var(--accent); }
.plumliners .change-values thead th { background: none; border-bottom: 0; }
.plumliners .change-detail p { margin: 0 0 0.5rem; }
.plumliners .change-values { width: 100%; border-collapse: collapse; table-layout: fixed; }
.plumliners .change-values :is(th, td) { padding: 0.3rem 0.8rem 0.3rem 0; border: 0; text-align: left; vertical-align: top; }
.plumliners .change-values tbody th { width: 28%; font-weight: 500; }
.plumliners .change-actions { margin: 0.6rem 0 0; }
/* On the Audit Log, what changed too, between when and who: a sangha, a group or a licence. */
.plumliners .log-table .col-subject { width: 30%; }
/* How far back the Audit Log looks, beside its filter, as wide as its
   words; the filter a little narrower than elsewhere, so both sit beside
   six tabs on a laptop. */
.plumliners .part-tools .log-days { flex: 0 0 auto; margin: 0; }
.plumliners .part-tools .log-days .field { margin: 0; }
.plumliners .part-tools .log-days select { width: auto; }
.plumliners .part-tools .log-days ~ .list-search { flex-basis: 14rem; width: 14rem; }
/* On a phone, each change is a short block, as Groups' rows are, rather
   than four columns too narrow for a word: on the Audit Log the sangha,
   group or licence, then what changed, and under it, quieter, when and
   who. The Audit Log's headings stay in a line above, to sort by; a
   sangha's own, which do not sort, go. */
@media (max-width: 700px) {
  .plumliners .changes-table, .plumliners .changes-table > tbody { display: block; }
  .plumliners .changes-table > colgroup, .plumliners .changes-table:not(.log-table) > thead { display: none; }
  .plumliners .log-table > thead, .plumliners .log-table > thead > tr { display: flex; }
  .plumliners .log-table > thead > tr { flex: 1; flex-wrap: wrap; background: var(--ground-2); border-bottom: 1px solid var(--rule); }
  .plumliners .log-table > thead th { border-bottom: 0; padding-inline: 0.8rem 0.4rem; }
  .plumliners .changes-table tr.row-link {
    display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 0.8rem; padding-block: 0.45rem;
    grid-template-areas: "change change" "when who";
  }
  .plumliners .changes-table tr.row-link > td { padding: 0.1rem 0.8rem; border-bottom: 0; }
  .plumliners .changes-table tr.row-link > td:nth-child(1) { grid-area: when; padding-right: 0; }
  .plumliners .changes-table tr.row-link > td:nth-child(2) { grid-area: who; padding-left: 0; }
  .plumliners .changes-table tr.row-link > td:nth-child(3) { grid-area: change; }
  .plumliners .changes-table tr.row-link > td:is(:nth-child(1), :nth-child(2)) { color: var(--muted); font-size: 0.9rem; }
  .plumliners .log-table tr.row-link { grid-template-areas: "subject subject" "change change" "when who"; }
  .plumliners .log-table tr.row-link > td:nth-child(2) { grid-area: subject; padding-left: 0.8rem; color: var(--ink); font-size: inherit; font-weight: 500; }
  .plumliners .log-table tr.row-link > td:nth-child(3) { grid-area: who; padding-left: 0; color: var(--muted); font-size: 0.9rem; }
  .plumliners .log-table tr.row-link > td:nth-child(4) { grid-area: change; }
  .plumliners .changes-table > tbody > tr.change-detail, .plumliners .changes-table > tbody > tr.change-detail > td { display: block; }
  /* Opened, the block itself takes the colour and the line, as its cells no longer reach its left edge. */
  .plumliners .changes-table > tbody > tr.row-link[aria-expanded="true"] { background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); }
  .plumliners .changes-table > tbody > tr.row-link[aria-expanded="true"] > td { background: none; box-shadow: none; }
}

.plumliners .row-actions { white-space: nowrap; }
.plumliners .row-actions > * + * { margin-left: 0.4rem; }
/* Whether a sangha or a group needs attention: a small red dot with a
   white "!", an amber one with a white dash while we wait to hear back,
   or a green one with a white tick. The marks differ as well as the
   colours, so none rests on colour alone. */
.plumliners .status-mark {
  flex: none; display: inline-grid; place-items: center; width: 0.85rem; height: 0.85rem;
  border-radius: var(--radius-pill); color: var(--mark-on); font: 700 0.56rem/1 var(--font); font-size-adjust: var(--x-height);
}
.plumliners .status-mark.needs { background: var(--mark-needs); }
.plumliners .status-mark.fine { background: var(--mark-fine); }
.plumliners .status-mark.waiting { background: var(--mark-waiting); }
/* A row's button sits within the line of text, so it does not make the
   row taller than its words. */
/* On Sanghas and Groups a whole row opens its page: it lights up under the
   pointer, and its name, still a link for the keyboard, reads as words. */
.plumliners tr.row-link { cursor: pointer; }
/* Except the cell with an email address, which is for copying it. */
.plumliners tr.row-link > td.email-cell { cursor: auto; }
.plumliners :is(.aligned-table, .sangha-groups-table) tbody tr.row-link:hover > td { background: var(--accent-soft); }
.plumliners :is(.aligned-table, .sangha-groups-table) a.row-name { color: var(--ink); }
.plumliners :is(.aligned-table, .sangha-groups-table) a.row-name:hover { text-decoration: none; }

/* ---- one sangha, in full -----------------------------------------
   A sangha's own page on this side is its public page itself, laid out by
   sanghas.css in this side's colours. What follows is only what the
   public page has no need of: the band at the foot of the sheet, where
   the public page asks visitors to write, holding all that is not
   published, in parts under small headings; an email with its copy
   button; and an empty field, a quiet dash, so it reads as empty, not as
   missing. */
/* The globe in this side's colours too: its ground and rim in indigo. */
.plumliners .sangha-picture .globe { background: var(--sect-soft); }
.plumliners .globe-edge { stroke: var(--sect); }
.plumliners .unpublished h3 { margin: 1.4rem 0 0.6rem; font-size: 1rem; }
.plumliners .unpublished h2 + h3 { margin-top: 0.9rem; }
.plumliners .unpublished .person-name { display: block; }
/* The notes, as written, and the box in their place while it is open. */
.plumliners .sangha-notes { max-width: 40rem; }
.plumliners .sangha-notes #detail-notes { margin: 0; overflow-wrap: anywhere; }
.plumliners .sangha-notes .field { margin: 0; }
.plumliners .sangha-notes .actions { margin-top: 0.6rem; }
/* Each fact on a line of its own, its heading in the first column and its
   value beside it, rather than the browser's own list, with each value
   indented on the line below. On a phone, the value goes under its
   heading. A mark beside a value, Needs Attention's, hangs just left of
   its heading, so every heading stays in line (Alipasha, 9 Oct 2026). */
.plumliners .unpublished .profile-facts { margin: 0; }
.plumliners .unpublished .profile-facts > div:not([hidden]) {
  position: relative;
  display: grid; grid-template-columns: 13rem minmax(0, 1fr); column-gap: 1.2rem;
  padding: 0.3rem 0;
}
.plumliners .unpublished .profile-facts dt { color: var(--muted); }
.plumliners .unpublished .profile-facts dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
/* Zoom: a line for each meeting that holds a licence. */
.plumliners .unpublished .zoom-line { display: block; }
.plumliners .unpublished .profile-facts .mark-line .status-mark { position: absolute; right: 100%; top: 0.62rem; margin-right: 0.5rem; }
@media (max-width: 620px) {
  .plumliners .unpublished .profile-facts > div:not([hidden]) { grid-template-columns: minmax(0, 1fr); }
}
.plumliners .profile-facts :is(.email-line, .phone-line) .copy-button { margin-block: 0; }
.plumliners .empty-value { color: var(--muted); }
.plumliners .mark-line .status-mark { margin-right: 0.45rem; vertical-align: 0.12em; }

/* ---- one group, in full -------------------------------------------
   A group's own page is laid out as a sangha's is (Alipasha, 10 Oct 2026),
   from the same rules in sanghas.css: the name large, a line of what it
   holds, and its pencil; then one sheet with its coordinators and its
   sanghas. It has no picture, so its head is one column. */
.plumliners .group-profile .profile-head { grid-template-columns: minmax(0, 1fr); }
.plumliners .group-profile .title-row { margin-bottom: 0; }
.plumliners .group-profile .title-row .icon-button { align-self: center; }
.plumliners .group-profile > .notice { margin: 1.5rem 0 0; }
/* Delete Group, under the sheet on a group's page of its own, at the right
   (in the layer, it is in the layer's head). */
.plumliners .group-foot { display: flex; justify-content: flex-end; margin-top: 1.5rem; }
/* The name, written where it shows: as large as the heading it replaces. */
.plumliners .group-name-form { max-width: 40rem; }
.plumliners .group-name-form input {
  width: 100%; font: inherit; font-size: 1.6rem; font-weight: 600; color: var(--ink);
  padding: 0.35rem 0.6rem; background: var(--card);
  border: 1px solid var(--field-edge); border-radius: var(--radius-xs);
}
.plumliners .group-name-form .notice { margin: 0.6rem 0 0; }
.plumliners .group-name-form .actions { margin-top: 0.7rem; }
/* In the layer over Groups, the group's page draws the layer's head
   itself (sangha-group-detail.js; Alipasha, 12 Oct 2026): its name with
   the pencil in the middle, and under it, small, how many sanghas and
   coordinators, in the band's light words. While the name is written the
   box takes its place, the size of the name, with Cancel on the left and
   Save on the right where Close was. */
.plumliners .group-layer-head .layer-head-middle { min-width: 0; }
.plumliners .group-layer-head .title-row { justify-content: center; gap: 0.3rem; margin: 0; }
.plumliners .group-layer-head .title-row .icon-button { margin: 0; color: var(--rail-text); }
.plumliners .group-layer-head .title-row .icon-button:hover { color: var(--rail-bright); background: var(--dark-button); }
.plumliners .group-layer-head .profile-key { justify-content: center; margin: 0.15rem 0 0; color: var(--rail-text); font-size: 0.95rem; }
.plumliners .group-layer-head .group-name-form { width: min(30rem, 60vw); max-width: none; }
.plumliners .group-layer-head .group-name-form input { font-size: 1.35rem; padding: 0.15rem 0.6rem; text-align: center; }
.plumliners .group-layer-head .group-name-form .actions { display: none; }
html.in-layer .group-profile { padding-top: 1.5rem; }
html.in-layer .group-profile .profile-sheet { margin-top: 0; }
html.in-layer .group-profile > .notice { margin: 0 0 1rem; }

/* Each coordinator on a line: name, and email with its copy button. */
.plumliners .profile-section .group-people { margin: 0; padding: 0; list-style: none; }
.plumliners .group-people li {
  display: grid; grid-template-columns: 12rem minmax(0, 1fr) auto; align-items: center;
  column-gap: 1rem; padding: 0.35rem 0;
}
.plumliners .group-people li + li { border-top: 1px solid var(--rule); }
.plumliners .group-people .email-line { color: var(--muted); }
.plumliners .group-people .cut { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
/* The names to choose from, opened by the pencil: one tick each, in as
   many columns as the sheet holds. */
.plumliners .group-profile h2 .icon-button { margin-left: 0.4rem; }
.plumliners .group-choices { columns: 13rem auto; column-gap: 1.5rem; }
.plumliners .group-choices label { display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0; break-inside: avoid; cursor: pointer; }
.plumliners .group-choices-form .notice { margin: 0.6rem 0 0; }
.plumliners .group-choices-form .actions { margin-top: 0.8rem; }
/* The box the pencil beside Sanghas opens: the field to find sanghas,
   how many, the list of ticks, and under it what Save will do, each as
   quiet as the Zoom box's. */
.plumliners #group-sanghas-status { margin: 0.4rem 0 0.8rem; color: var(--muted); font-size: 0.9rem; }
.plumliners .group-sanghas-picker { table-layout: fixed; }
.plumliners .group-sanghas-picker th:nth-child(2) { width: 20%; }
.plumliners .group-sanghas-picker th:nth-child(3) { width: 32%; }
.plumliners .group-sanghas-picker th:nth-child(4) { width: 20%; }
/* At the top of the box, a menu for each thing sanghas are allocated by,
   side by side where there is room; under them the filter by name and
   Clear. Its lists hang over the box below them, as on a page, rather
   than opening in place as a box's menus do. */
.plumliners .group-sanghas-filters { display: grid; grid-template-columns: repeat(auto-fill, minmax(10.5rem, 1fr)); gap: 0.6rem 0.8rem; }
.plumliners #group-sanghas-dialog .excel-filter-menu { position: absolute; width: max(100%, 17rem); margin-top: 0; }
/* One height, whatever its list holds, so choosing in a menu never moves
   the box (Alipasha, 18 Oct 2026): the list takes the room the menus and
   words leave, and scrolls within it. Tall enough for an open menu to
   hang in full. */
.plumliners #group-sanghas-dialog { height: min(44rem, calc(100dvh - 3rem)); }
.plumliners #group-sanghas-dialog[open] { display: flex; flex-direction: column; }
.plumliners #group-sanghas-dialog > .lightbox-head { flex: 0 0 auto; }
/* A box that asks in itself takes the size of its question, as a box
   that only asks would be (Alipasha, 18 Oct 2026). */
.plumliners .lightbox.wide.asking { width: min(34rem, calc(100vw - 2rem)); }
.plumliners #group-sanghas-dialog.asking { height: fit-content; }
.plumliners #group-sanghas-form { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.plumliners #group-sanghas-form > * { flex: 0 0 auto; }
.plumliners #group-sanghas-form > .results-box { flex: 1 1 auto; min-height: 6rem; max-height: none; }
.plumliners .group-sanghas-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; margin-top: 0.8rem; }
.plumliners .group-sanghas-tools .field { margin: 0; flex: 0 1 18rem; }
.plumliners .group-sanghas-changes { margin-top: 0.8rem; font-size: 0.9rem; }
.plumliners .group-sanghas-changes p { margin: 0 0 0.25rem; }
/* New, beside a sangha not yet published, on a group's page and in its
   box: a quiet word, not a red flag, as a new sangha given a group needs
   nothing more from Groups (Alipasha, 18 Oct 2026). */
.plumliners .new-tag {
  display: inline-block; margin-left: 0.5rem; padding: 0.1em 0.6em; border-radius: var(--radius-pill);
  background: var(--sect-soft); color: var(--sect-text); font-size: 0.8rem; font-weight: 600;
}
/* Sanghas, with the filter on the heading's line once the list is long. */
.plumliners .group-section-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.6rem 1rem; margin-bottom: 0.6rem; }
.plumliners .group-section-head h2 { margin: 0; }
/* The filter and Columns side by side: a width in percent, inside a row
   as wide as what it holds, left Columns wrapping under the filter. */
.plumliners .group-section-head .head-actions { flex-wrap: nowrap; }
.plumliners .group-section-head .list-search { margin: 0; flex: 0 1 16rem; width: 16rem; min-width: 0; }
/* The sangha list sits on the sheet itself, ruled, with no box of its own;
   a long name or place ends in an ellipsis. */
.plumliners .group-sanghas-table { table-layout: fixed; }
.plumliners .group-sanghas-table :is(th, td) { padding-inline: 0 0.9rem; }
.plumliners .group-sanghas-table :is(th, td):last-child { padding-right: 0; }
.plumliners .group-sanghas-table thead th { background: none; }
/* The names give up some of their width as more columns are chosen. */
.plumliners .group-sanghas-table th.cell-name { width: 40%; }
.plumliners .group-sanghas-table:is([data-columns="2"], [data-columns="3"]) th.cell-name { width: 34%; }
.plumliners .group-sanghas-table th.cell-country { width: 15%; }
.plumliners .group-sanghas-table th.cell-region { width: 12%; }
.plumliners .group-sanghas-table th.cell-languages { width: 14%; }
/* At the row's end, Groups, the small button that opens the box choosing
   the sangha's groups (Alipasha, 25 Oct 2026): room for its word, at the right. */
.plumliners .group-sanghas-table th.cell-actions { width: 5.5rem; }
.plumliners .group-sanghas-table td.cell-actions { text-align: right; overflow: visible; }
/* The columns not ticked under Columns are hidden. */
.plumliners .group-sanghas-table.hide-country .cell-country,
.plumliners .group-sanghas-table.hide-region .cell-region,
.plumliners .group-sanghas-table.hide-languages .cell-languages { display: none; }
.plumliners .group-sanghas-table td { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.plumliners .group-sanghas-table tbody tr:last-child td { border-bottom: 1px solid var(--rule); }
.plumliners .group-sanghas-table tbody tr.row-link:hover > td { background: var(--accent-soft); }
.plumliners .group-sanghas-table a.row-name { color: var(--ink); }
.plumliners .group-sanghas-table a.row-name:hover { text-decoration: none; }
/* On a phone, each coordinator's line stacks, and the list keeps only the
   sangha's name; its page has the rest, so Columns goes too. In the box of
   the group's sanghas, Place and Languages give their room to the name. */
@media (max-width: 700px) {
  .plumliners .group-people li { grid-template-columns: minmax(0, 1fr) auto; }
  .plumliners .group-people .person-name { grid-column: 1; }
  .plumliners .group-people .email-line { grid-column: 1; grid-row: 2; }
  .plumliners .group-sanghas-table :is(.cell-country, .cell-region, .cell-languages) { display: none; }
  .plumliners .group-sanghas-table th.cell-name { width: auto; }
  .plumliners .group-section-head .columns-menu { display: none; }
  .plumliners .group-sanghas-picker :is(th, td):is(:nth-child(4), :nth-child(5)) { display: none; }
  .plumliners .group-sanghas-picker th:nth-child(2) { width: 35%; }
  .plumliners .group-sanghas-picker th:nth-child(3) { width: auto; }
}

/* ---- choosing from a list ---------------------------------------
   A field that opens into a list of ticks: the assignees of a new
   group, and each field sanghas are found by. Shut, it is drawn as
   a control you press, like a select; open, the list hangs under it
   on the panel's shadow. The class names are the ones the scripts
   have always written. */
.plumliners .field-label { display: block; font-weight: 600; font-size: 0.95rem; margin-bottom: 0.35rem; }
.plumliners .excel-filter { position: relative; min-width: 0; }
.plumliners .excel-filter > summary {
  position: relative; display: block; list-style: none; cursor: pointer;
  padding: var(--control-pad-y) 2rem var(--control-pad-y) var(--control-pad-x); font-weight: 400;
  font-size: var(--control-font); line-height: var(--control-line);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--ink);
  background: var(--white-face); border: var(--control-border) solid var(--white-face-edge); border-radius: var(--radius-xs);
  box-shadow: var(--white-face-lines);
}
.plumliners .excel-filter > summary::-webkit-details-marker { display: none; }
.plumliners .excel-filter > summary::after {
  content: '▾'; position: absolute; top: 50%; right: 0.75rem;
  transform: translateY(-50%); color: var(--muted);
}
.plumliners .excel-filter > summary:hover { background: var(--white-face-hover); }
.plumliners .excel-filter > summary:focus-visible,
.plumliners .excel-filter[open] > summary { outline: var(--focus-ring); outline-offset: 2px; }
.plumliners .excel-filter-menu {
  position: absolute; top: calc(100% + 0.35rem); left: 0; z-index: 30;
  width: max(100%, 17rem); padding: 0.7rem;
  background: var(--card); border: 1px solid var(--rule); border-radius: var(--radius-xs);
  box-shadow: var(--shadow);
}
/* In a lightbox there is nothing under the field to hang over, so the
   list opens in place and the lightbox grows to hold it. */
.plumliners .lightbox .excel-filter-menu { position: static; width: 100%; margin-top: 0.35rem; }
.plumliners .excel-filter-search {
  width: 100%; font: inherit; font-size: 0.95rem; color: var(--ink);
  padding: 0.45rem 0.6rem; background: var(--card);
  border: 1px solid var(--field-edge); border-radius: var(--radius-xs); box-shadow: var(--sink);
}
/* At 16px on a phone, or an iPhone zooms the page in when it is tapped. */
@media (max-width: 760px) { .plumliners .excel-filter-search { font-size: var(--control-font); } }
.plumliners .excel-filter-search:focus { outline: var(--focus-ring); outline-offset: 2px; }
.plumliners .excel-filter-actions {
  display: flex; gap: 0.9rem; padding: 0.5rem 0 0.4rem; border-bottom: 1px solid var(--rule);
}
.plumliners .excel-filter-action {
  appearance: none; background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; font-size: 0.85rem; color: var(--sect-text);
  text-decoration: var(--link-underline); text-underline-offset: var(--link-offset);
}
.plumliners .excel-filter-options { display: grid; gap: 0.35rem; max-height: 16rem; overflow: auto; padding-top: 0.5rem; }
/* A tick and its words, read as one line. The list can sit inside a
   .field, so its labels and ticks undo what a field does to its own. */
.plumliners .excel-filter-options label {
  display: flex; align-items: flex-start; gap: 0.5rem; min-width: 0; margin: 0;
  font-size: 0.9rem; font-weight: 400; overflow-wrap: anywhere; cursor: pointer;
}
.plumliners .excel-filter-options input {
  flex: 0 0 auto; width: 1.15rem; height: 1.15rem; margin: 0.2rem 0 0; padding: 0;
  box-shadow: none; accent-color: var(--accent-strong);
}

/* A table of ticks, whether of people or of sanghas. The whole row
   takes the tick, so it answers the pointer, and a ticked row keeps
   the highlight's pale tone. Its head stays in view as the box
   scrolls. */
.plumliners .results-box { max-height: min(65vh, 44rem); overflow: auto; }
.plumliners .picker-table thead th { position: sticky; top: 0; z-index: 1; }
.plumliners .picker-table .picker-check-col { width: 2.8rem; text-align: center; }
.plumliners .picker-table input[type="checkbox"] { width: 1.15rem; height: 1.15rem; margin: 0; accent-color: var(--accent-strong); }
.plumliners .picker-row { cursor: pointer; }
.plumliners .picker-row:hover td { background: color-mix(in srgb, var(--sect-soft) 45%, var(--card)); }
.plumliners .picker-row.is-selected td { background: var(--sect-soft); }
/* The buttons that end a lightbox with nothing to cancel: one, on the right. */
.plumliners .actions.end { justify-content: flex-end; }
.plumliners .lightbox .notice { margin: 0 0 0.8rem; }

/* ---- on a phone -----------------------------------------------
   The status line takes the whole row under the buttons, words
   and control stack, and a form's fields go one under another. */
@media (max-width: 700px) {
  .plumliners .toolbar .status { width: 100%; margin-left: 0; }
  .plumliners .card.row-card { flex-direction: column; align-items: flex-start; }
  .plumliners .fields { grid-template-columns: 1fr; }
  /* Wide enough on a phone that a name or a team keeps to its words; the
     box scrolls sideways for the rest. */
  .plumliners .plumliners-table { min-width: 46rem; }
  .plumliners .api-client-table { min-width: 60rem; }
  .plumliners .sangha-group-sanghas-table { min-width: 48rem; }
  .plumliners .aligned-table.sangha-group-sanghas-table { min-width: calc(var(--share, 1) * 48rem); }
  /* My Sanghas is where a sangha contact starts, so its rows don't
     scroll out of sight: each sangha is a short block, its name, where
     it is, who looks after it, and Edit beside them. */
  .my-sanghas-table thead { display: none; }
  .my-sanghas-table, .my-sanghas-table tbody { display: block; }
  .my-sanghas-table tr {
    display: grid; grid-template-columns: auto 1fr auto; align-items: center;
    grid-template-areas: "name name edit" "country state edit" "coordinator coordinator edit";
    padding: 0.75rem 0.9rem;
  }
  .my-sanghas-table td { padding: 0; border: 0; }
  .my-sanghas-table td:empty { display: none; }
  .my-sanghas-table td:first-child { grid-area: name; font-weight: 500; }
  .my-sanghas-table :is(.my-sanghas-country, .my-sanghas-state, .my-sanghas-coordinator) { color: var(--muted); font-size: 0.9rem; }
  .my-sanghas-table .my-sanghas-coordinator { grid-area: coordinator; }
  .my-sanghas-table .my-sanghas-cell-label { display: inline; }
  .my-sanghas-table .my-sanghas-country { grid-area: country; }
  .my-sanghas-table .my-sanghas-state { grid-area: state; }
  .my-sanghas-table .my-sanghas-country:not(:empty) + .my-sanghas-state::before { content: ', '; }
  .my-sanghas-table td:last-child { grid-area: edit; width: auto; padding-left: 0.8rem; }
  .my-sanghas-table td:only-child { grid-area: name; padding-left: 0; font-weight: 400; }
}

/* ---- the Zoom page -------------------------------------------
   plumline's Zoom licences (Alipasha, 14 Oct 2026): their links, opened
   from the toolbar; the meetings on each; and a week of them on a
   calendar. Each licence has a colour of its own, from the palette's
   quieter ones, the same in the calendar and its key. */
.plumliners .zoom-1 { --zoom: var(--indigo); --zoom-soft: var(--indigo-soft); --zoom-text: var(--indigo-text); }
.plumliners .zoom-2 { --zoom: var(--clay); --zoom-soft: var(--clay-soft); --zoom-text: var(--clay-text); }
.plumliners .zoom-3 { --zoom: var(--sage); --zoom-soft: var(--sage-soft); --zoom-text: var(--sage-text); }
.plumliners :is(.zoom-links-table, .zoom-meetings-table, .zoom-bookings-table) { table-layout: fixed; }
/* A licence is [1], [2] or [3], so its column needs only its heading's
   room; the sangha's own time, which can run to a sentence, takes what
   the others leave (Alipasha, 15 Oct 2026). */
.plumliners :is(.zoom-links-table, .zoom-meetings-table, .zoom-bookings-table) .col-licence { width: 5rem; }
.plumliners .zoom-links-table .col-id { width: 10rem; }
.plumliners .zoom-links-table .col-passcode { width: 8rem; }
/* Room for Change and Remove, as wide as the buttons are. */
.plumliners :is(.zoom-links-table .col-change, .zoom-meetings-table .col-remove, .zoom-bookings-table .col-remove) { width: 7rem; }
.plumliners .zoom-meetings-table .col-sangha { width: 27%; }
.plumliners .zoom-meetings-table .col-yours { width: 8.5rem; }
/* A booking is whose, what for and when: what for takes the most room,
   as the booker's words can run on. */
.plumliners .zoom-bookings-table .col-who { width: 18%; }
.plumliners .zoom-bookings-table .col-yours { width: 14rem; }
/* The meetings asking for a licence: whose, when, which licences are free
   then, when they asked, and Give Zoom and Clear at the right. */
.plumliners .zoom-requests-table { table-layout: fixed; }
.plumliners .zoom-requests-table .col-sangha { width: 27%; }
.plumliners .zoom-requests-table :is(.col-free, .col-asked) { width: 8rem; }
.plumliners .zoom-requests-table .col-act { width: 12rem; }
.plumliners .zoom-requests-table td { overflow-wrap: anywhere; }
.plumliners .zoom-requests-table td:last-child { text-align: right; }
.plumliners :is(.zoom-links-table, .zoom-meetings-table, .zoom-bookings-table) td { overflow-wrap: anywhere; }
.plumliners :is(.zoom-links-table td:first-child, .zoom-meetings-table td:nth-child(2), .zoom-bookings-table td:nth-child(2)) { white-space: nowrap; }
.plumliners :is(.zoom-links-table, .zoom-meetings-table, .zoom-bookings-table) td:last-child { text-align: right; }
/* The mark comes first, in a narrow column, as on Sanghas. */
.plumliners :is(.zoom-meetings-table, .zoom-bookings-table) .col-status { width: 4%; }
.plumliners :is(.zoom-meetings-table, .zoom-bookings-table) :is(th.status-col, td.status-cell) { padding-inline: 0.2rem; text-align: center; }
.plumliners :is(.zoom-meetings-table, .zoom-bookings-table) td.status-cell .status-mark { vertical-align: 0.17em; }
.plumliners .zoom-meetings-table th.status-col .sort-button { position: relative; }
.plumliners .zoom-meetings-table th.status-col .sort-button::after { position: absolute; top: 50%; left: 100%; margin-left: -0.25rem; transform: translateY(-50%); }
/* The last heading's hidden word stays inside the box that scrolls, not
   out past the edge of a phone's screen. */
.plumliners :is(.zoom-links-table, .zoom-meetings-table, .zoom-bookings-table) th:last-child { position: relative; }

/* Add Zoom: for a sangha's meeting or a one-off booking; the search and
   the meetings found, or the booking's day and time; and a licence to
   choose, each saying whether it is free then. */
.plumliners .kind-field { border: 0; margin: 0 0 1rem; padding: 0; min-width: 0; }
.plumliners .kind-choices { display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; }
.plumliners #zoom-search-status { margin: 0.4rem 0 0.8rem; color: var(--muted); font-size: 0.9rem; }
.plumliners .zoom-results-table .col-pick { width: 2.8rem; }
.plumliners .zoom-results-table .col-licence { width: 6rem; }
.plumliners .zoom-results-table input[type="radio"] { width: 1.05rem; height: 1.05rem; margin: 0; accent-color: var(--accent-strong); }
.plumliners .licence-field { border: 0; margin: 1.1rem 0 0; padding: 0; min-width: 0; }
.plumliners .licence-help { margin: 0.2rem 0 0.6rem; color: var(--muted); font-size: 0.9rem; }
.plumliners .licence-choices { display: grid; gap: 0.55rem; }
.plumliners .licence-choice { align-items: flex-start; font-weight: 400; }
.plumliners .licence-choice input { margin-top: 0.3rem; accent-color: var(--accent-strong); }
.plumliners .licence-choice > span { display: flex; flex-wrap: wrap; column-gap: 0.6rem; }
.plumliners .licence-standing { color: var(--muted); }
.plumliners .licence-standing.is-clash { color: var(--unwhole-text); }

/* The calendar: a week in the reader's own time, the hours down the side.
   A meeting runs from its start to its end in its licence's colour, with
   the licence's number, and two at once stand side by side. One whose
   weeks are not known is striped; two on one licence that surely meet at
   the same time have a red edge. Wider than a phone, it scrolls sideways
   in its box. */
.plumliners .week-actions { gap: 0.4rem; }
.plumliners .week-words { margin: 0 0 0.5rem; color: var(--muted); }
.plumliners .calendar-key { display: flex; flex-wrap: wrap; gap: 0.4rem 1.2rem; margin: 0 0 0.8rem; padding: 0; list-style: none; font-size: 0.9rem; }
.plumliners .calendar-key li { display: flex; align-items: center; gap: 0.45rem; }
.plumliners .key-swatch {
  flex: none; width: 0.95rem; height: 0.95rem; box-sizing: border-box; border-radius: var(--radius-xs);
  border: 1px solid var(--zoom, var(--muted)); background-color: var(--zoom-soft, var(--card));
}
.plumliners .calendar-box { overflow-x: auto; }
.plumliners .zoom-calendar {
  display: grid; grid-template-columns: 3.8rem repeat(7, minmax(5.5rem, 1fr)); grid-template-rows: auto 48rem;
  min-width: 44rem; background: var(--card);
}
.plumliners :is(.cal-corner, .cal-day-head) { border-bottom: 1px solid var(--rule); }
.plumliners .cal-day-head { padding: 0.55rem 0.3rem; border-left: 1px solid var(--rule); text-align: center; font-size: 0.95rem; font-weight: 600; }
.plumliners .cal-hours { position: relative; }
.plumliners .cal-hour { position: absolute; right: 0.45rem; transform: translateY(-50%); color: var(--muted); font-size: 0.75rem; white-space: nowrap; }
.plumliners .cal-hour:first-child { transform: none; }
.plumliners .cal-day {
  position: relative; border-left: 1px solid var(--rule);
  background-image: repeating-linear-gradient(to bottom, var(--rule) 0 1px, transparent 1px calc(100% / 12));
}
.plumliners .cal-block {
  position: absolute; z-index: 1; box-sizing: border-box; overflow: hidden;
  left: calc(var(--part, 0) * 100% / var(--parts, 1) + 1px); width: calc(100% / var(--parts, 1) - 2px); min-height: 1.1rem;
  padding: 0.1rem 0.2rem; border: 1px solid var(--zoom); border-radius: var(--radius-xs);
  background-color: var(--zoom-soft); color: var(--zoom-text);
  font-size: 0.75rem; line-height: 1.15; overflow-wrap: anywhere; text-decoration: none;
}
.plumliners .cal-block:is(:hover, :focus-visible) { z-index: 2; background-color: var(--card); box-shadow: var(--lift); }
.plumliners :is(.cal-block, .key-swatch).is-unsure {
  background-image: repeating-linear-gradient(135deg, transparent 0 4px, color-mix(in srgb, var(--zoom, var(--muted)) 30%, transparent) 4px 7px);
}
.plumliners :is(.cal-block, .key-swatch).is-clash { border: 2px solid var(--mark-needs); }
@media (max-width: 700px) {
  .plumliners .zoom-meetings-table { min-width: 40rem; }
  .plumliners .zoom-bookings-table { min-width: 46rem; }
  .plumliners .zoom-requests-table { min-width: 44rem; }
  .plumliners .zoom-links-table { min-width: 52rem; }
}

/* ---- Updates ---------------------------------------------
   The next plumliners meeting first and large: when it is, and
   the way in beside it. Then the updates as the Builders events
   are, cards that open, their words in the ink, a topic in bold
   as the updates by email set it. */
/* One right edge: each section's button over the end of its cards. */
.plumliners #updates-panel .section-head { max-width: 52rem; }
/* The next meeting is one card, as on Home (Alipasha, 16 Oct 2026): the
   Zoom's details and Add to Calendar in a quiet line under when it is. */
.plumliners .next-meeting { max-width: 52rem; margin-top: 0; }
.plumliners .next-card .next-more { display: block; margin-top: 0.25rem; color: var(--muted); font-size: 0.85rem; overflow-wrap: anywhere; }
.plumliners .next-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 0.9rem; }
.plumliners :is(.next-later, .next-none) { margin: 0; color: var(--muted); }
.plumliners .next-later { font-size: 0.95rem; overflow-wrap: anywhere; }
.plumliners .next-last { margin: 0.3rem 0 0; color: var(--muted); }
/* A draft, which only those who write the updates see, is drawn dashed. */
.plumliners .updates .session.is-draft { border-style: dashed; }
.plumliners .update-draft-field { margin-top: 0.9rem; }
/* An update's words, on Updates and opened on Home alike. */
.plumliners .update-words :is(p, li) { color: var(--ink); font-size: 0.95rem; }
.plumliners .update-words p { margin: 0 0 0.6rem; }
.plumliners .update-words .update-topic { margin: 0.9rem 0 0.2rem; font-size: 0.95rem; font-weight: 600; color: var(--ink); }
.plumliners .update-words .update-topic:first-child { margin-top: 0; }
.plumliners .update-words ul { margin: 0.15rem 0 0.7rem; padding-left: 1.2rem; }
.plumliners .update-words ul ul { margin-bottom: 0.2rem; }
.plumliners .update-words li + li { margin-top: 0.25rem; }
.plumliners .update-words strong { font-weight: 600; }
.plumliners .update-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 0.9rem; }
.plumliners .updates > .updates-none { margin: 0; color: var(--muted); }
.plumliners .update-month-field { max-width: 14rem; }

/* ---- small type ---------------------------------------
   Everything this sheet sets at 0.9rem or smaller, apart from
   small capitals, is set a little apart (--tracking-small in
   tokens.css). Kept in one list rather than beside each size,
   at no weight of its own, so a rule that sets its own spacing
   still has the last word. A new small size belongs here too. */
:where(
  .plumliners-nav-who #plumliners-nav-email,
  .plumliners-nav-foot #plumliners-nav-logout,
  .account-action span,
  .plumliners .toolbar .status,
  .plumliners .build-info,
  .plumliners .secondary-button.compact-button,
  .plumliners .btn-small,
  .plumliners .excel-filter-action,
  .plumliners .excel-filter-options label,
  .sign-in-note.sign-in-privacy,
  .plumliners #zoom-search-status,
  .plumliners #group-sanghas-status,
  .plumliners .group-sanghas-changes,
  .plumliners .new-tag,
  .plumliners .licence-help,
  .plumliners .calendar-key,
  .plumliners .cal-hour,
  .plumliners .cal-block
) { letter-spacing: var(--tracking-small); }
:where(.sangha-steps li)::before { letter-spacing: var(--tracking-small); }
@media (max-width: 700px) {
  :where(.my-sanghas-table :is(.my-sanghas-country, .my-sanghas-state, .my-sanghas-coordinator)) { letter-spacing: var(--tracking-small); }
}
