/* ============================================================
   Shared component layer for manage.
   Loaded by header.php after the base sheets, so it can build on
   the brand tokens in styles.css (--green-light/medium/dark, --text-gray).
   The admin is a fixed light UI — no dark theme here by design.

   Goal: pages stop hand-inlining cards, dividers, grids and pills.
   Convert pages onto these classes one at a time.
   ============================================================ */

:root {
  /* Action gold (the canonical .custom-button color, tokenized) */
  --gold: #EFC234;
  --gold-hover: #F7D159;

  /* Green gradient underline (was hardcoded ~17x inline) */
  --underline-a: #137752;
  --underline-b: #ADDC91;

  /* Neutrals / lines */
  --ink: #212529;
  --ink-mid: #4b4b4b;
  --ink-soft: #6c757d;
  --line: #dee2e6;
  --line-strong: #ced4da;
  --surface: #ffffff;

  /* FS-037 — the type scale's colours.
     --label-green is the colour of an H3 or H4, which are the portal's two
     ALL-CAPS heading levels. Pete, 2026-09-17, having seen three greens side by
     side at 11px: the lighter one, which is what the instrument already used.
     ⚠ It is 3.14:1 on white, below WCAG AA's 4.5:1 for text under 18.66px. That
     is a recorded product decision (FS-037 §3.3), not an oversight.

     The three zone colours are the instrument's own and they carry DATA — which
     side of the scale a reading falls on — so they beat the label green wherever
     a heading contains a reading. */
  --label-green: #66a12f;
  --zone-acc:  #a07c0e;
  --zone-bal:  #66a12f;
  --zone-asrt: #3d8cc7;

  /* FS-037 — TWO TEXT SIZES. Not three, and not a page's own.
     Pete, 2026-09-17, after reviewing the built pages with Tracey: "we need one
     standard text size for our base font — not multiple that grow and shrink."
     14px was too small for her; 16px was too big for him; 15px is the answer, and
     everything that is read — body copy, a lede under a heading, a question's
     stem, a tile's meta — is that one size.

     --text-micro is the only smaller tier, for what is genuinely a caption: a
     pill, a bar's pole labels, an over-line. It went 12px → 13px in the same pass,
     because the pole labels under the question bars were the one thing on the
     report Pete still could not read comfortably.

     ⚠ THE OLD .text-sm (14px) IS GONE. It was the "multiple that grow and shrink"
     problem in one class: reading text at 14px beside reading text at 16px. */
  --text-base:  0.9375rem;   /* 15px */
  --text-micro: 0.8125rem;   /* 13px */

  /* Semantic (consolidated from scattered inline usage) */
  --ok: #28A745;   --ok-bg: #D4EDDA;  --ok-ink: #155724;
  --danger: #DC3545; --danger-bg: #F8D7DA; --danger-ink: #721C24;
  --muted: #6C757D;
}

/* ---- White panel (design-system "card"; named .panel to avoid
   colliding with Bootstrap's .card, which forces flex-column) ---- */
.panel {
  background: var(--surface);
  border: 1px solid #e9ecef;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  padding: 1.5rem;
}

/* ---- Responsive auto-fit grid of panels. No per-page @media needed:
   columns collapse to one on narrow screens automatically. ---- */
.panel-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 2rem;
}

/* ---- Green gradient underline under section/card titles ---- */
.section-divider {
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(to right, var(--underline-a), var(--underline-b));
  margin: 0.5rem 0 1rem;
}

/* ---- Sort / selection pill row (promoted from assessments.php).
   Active pill is brand green per the approved design review. ---- */
.sort-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  align-items: center;
}

.sort-label {
  display: flex;
  align-items: center;
  font-size: 1rem;
  color: var(--muted);
  margin-right: 0.5rem;
  white-space: nowrap;
}

.sort-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  padding: 0.35rem 0.85rem;
  background-color: var(--surface);
  border: 1px solid var(--line);
  border-radius: 20px;
  font-size: 1rem;
  color: var(--muted);
  cursor: pointer;
  transition: all 0.2s ease;
  white-space: nowrap;
}

.sort-pill:hover {
  background-color: #f8f9fa;
  border-color: var(--line-strong);
}

.sort-pill.active {
  background-color: var(--green-dark);
  border-color: var(--green-dark);
  color: #fff;
  font-weight: 500;
}

.sort-pill i {
  font-size: 0.8rem;
}

/* On phones the pill row scrolls horizontally and the "Sort by:" label hides. */
@media (max-width: 768px) {
  .sort-controls {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  .sort-controls::-webkit-scrollbar { display: none; }
  .sort-label { display: none; }
  .sort-pill { flex-shrink: 0; }
}

/* ---- Status tile (LIST pages: assessments, users). A clickable colored
   tile whose background encodes status. This is deliberately NOT .panel —
   list tiles are color-coded, detail pages use the white .panel box. ---- */
.status-tile {
  background-color: var(--surface);
  border-radius: 8px;
  /* Anchor for the absolutely-positioned entity label/watermark (and the
     templates page's hover actions). Without it those escape the card. */
  position: relative;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  padding: 0.75rem;
  cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.status-tile:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.15);
}

/* Cards are white. Status used to be a background tint, which meant it could
   only ever be a hint — you had to know the colour code to read it. It is now
   stated outright by .status-pill in the top-right corner, which frees the fill
   and lets the three list pages look like one family. */

/* A tile's title. FS-037: on a converted page this is an <h3 class="is-name"> —
   level 3 in its sentence-case form, because a tile's title NAMES something and
   the caps-green form is for labels. The font-size below is the LEGACY one, for
   the list pages not yet converted; `.portal-type h3.is-name` (typography.css,
   (0,2,1)) beats it on a converted page. It did not until REL-017's regression
   run caught tiles at 16.8px: `.portal-type h3` alone TIES with this rule. */
.status-tile h3 {
  margin: 0 0 0.35rem 0;
  font-weight: bold;
  font-size: 1.05rem;
  padding-right: 6rem;   /* clear of the corner pill(s) */
}

.status-tile .meta {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  /* FS-037 — the base. It was 0.9rem / 14.4px, which is exactly the kind of
     nearly-but-not-quite size the one-base rule exists to remove. */
  font-size: var(--text-base);
  color: #6b6e70;
}

.status-tile .meta span {
  display: flex;
  align-items: center;
  gap: 0.7rem;
}

.status-tile .meta i {
  width: 14px;
  text-align: center;
}

/* ---- Card identity. The three list pages share .status-tile, and its FILL is
   already spoken for — it encodes status. So "what kind of thing is this" is
   carried on other channels instead: a coloured left rail, a matching type
   label top-right, and an oversized watermark glyph in the bottom-right corner.
   Each page sets --entity to its own hue; label and watermark both render that
   hue at 20% so they read as a family rather than as content. ---- */
.status-tile--entity {
  border-left: 5px solid var(--entity);
  padding-left: 0.85rem;
  overflow: hidden;
}

/* Status / attribute pills, top-right. One pill on assessments and users; a
   template can show up to two (a non-English language, and a deprecated type).
   They occupy the slot the entity type label used to hold — the rail and the
   watermark still carry identity, and stating status is the better use of the
   corner. */
.status-pills {
  position: absolute;
  top: 0.6rem;
  right: 0.75rem;
  display: flex;
  gap: 0.3rem;
  z-index: 2;
}

.status-pill {
  display: inline-block;
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  padding: 0.08rem 0.55rem;
  border-radius: 10px;
  white-space: nowrap;
}

/* Assessment lifecycle */
.st--testing   { background: #fdf2d6; color: #8a6212; }
.st--published { background: #e4f0db; color: #3c7422; }
.st--closed    { background: #fbe0e0; color: #a33a3a; }
.st--archived  { background: #eef1f4; color: #5a6672; }
/* Users: shown only when the account is deactivated (FS-012 renamed the label;
   the stored tr_users.deleted column is unchanged) */
.st--deactivated { background: #fbe0e0; color: #a33a3a; }
/* Templates: language (only when it isn't English) and deprecated question type */
.st--lang      { background: #eef1f4; color: #5a6672; }
.st--dep       { background: #fde9d9; color: #b3541a; }

.entity-mark {
  position: absolute;
  right: -6px;
  bottom: -14px;
  font-size: 3.6rem;
  color: var(--entity);
  opacity: 0.2;
  pointer-events: none;
  z-index: 0;
}

/* The watermark is the tile's last child, so without this it would paint OVER
   a long name or meta line and tint the text. Content stays above it. */
.status-tile--entity h3,
.status-tile--entity .meta,
.status-tile--entity .tile-tags {
  position: relative;
  z-index: 1;
}

/* Entity hues. Deliberately NOT the status palette — these say what a record
   is, the background says how it is doing. */
.entity--assessment { --entity: #4C8D2B; }
.entity--user       { --entity: #2b6ea8; }
.entity--template   { --entity: #7a4ca8; }
/* FS-024 — Power Style. Amber, because green, blue and purple are taken and the
   instrument's own palette runs yellow-to-blue.
   ⚠ Lightened from #b5820c (Pete): that was a dark ochre that read as brown
   beside the other three rails rather than as the yellow end of the dial. This
   is closer to the instrument's own accommodative #efc234, kept just dark enough
   that the watermark at 20% opacity is still visible on white. */
.entity--powerstyle { --entity: #d9a227; }

/* .danger-button moved to button-styles.css (REL-024), beside the other weights it is documented with. */

/* ---- Edit pencil (fa-pencil-alt). One look everywhere; behavior stays on the
   element's own onclick handler — this class is styling only. ---- */
.edit-icon {
  cursor: pointer;
  color: #666;
  margin-left: 5px;
}

.edit-icon:hover {
  color: #333;
}

/* Disabled state for the canonical .custom-button (e.g. "Assign License" when
   the user has none available). */
.custom-button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ---- Shared single-select picker popup (js/picker.js openPicker()).
   Click an option to select + close; click the backdrop or Esc to dismiss.
   One system for group/status/template/guide/... popups. ---- */
.picker-backdrop {
  position: fixed;
  inset: 0;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 999;
}

.picker-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: var(--surface);
  padding: 1.5rem;
  border-radius: 0.5rem;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
  z-index: 1000;
  min-width: 300px;
  max-width: 90vw;
  max-height: 80vh;
  display: flex;
  flex-direction: column;
}

.picker-title {
  margin: 0 0 1rem 0;
  font-size: 1.25rem;
  font-weight: 500;
}

.picker-options {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  overflow-y: auto;
}

.picker-option {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--line);
  border-radius: 0.25rem;
  cursor: pointer;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}

.picker-option:hover {
  background-color: #f8f9fa;
}

/* An option that is present but unavailable, with its reason (FS-010). Greyed
   rather than hidden, so the absence never has to be guessed at. */
.picker-option.disabled {
  cursor: not-allowed;
  background-color: #fbfcfc;
  border-color: #eceff1;
  color: #adb5bd;
}

.picker-option.disabled:hover {
  background-color: #fbfcfc;
}

/* FS-037 — the dialog's own sentence, under its title: what picking one of these
   will do. Not .picker-note, which belongs to a single option. */
.picker-subnote {
  margin: -0.35rem 0 0.75rem;
  font-size: 0.875rem;
  line-height: 1.45;
  color: var(--ink-mid);
}

.picker-note {
  font-size: 0.78rem;
  color: #9aa4ac;
  text-align: right;
  flex-shrink: 1;
}

/* Multi-select check (shown only when the option is selected) */
.picker-check {
  color: var(--green-medium);
  font-weight: 700;
  opacity: 0;
  flex-shrink: 0;
}

.picker-option.selected .picker-check {
  opacity: 1;
}

.picker-footer {
  display: flex;
  justify-content: flex-end;
  margin-top: 1rem;
}

/* ---- Filter chip: a pill button that opens the shared picker and shows the
   current selection (used by the comment filters; reusable elsewhere). ---- */
.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.8rem;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  cursor: pointer;
  font: inherit;
  font-size: 0.9rem;
  color: #495057;
  white-space: nowrap;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}

.filter-chip:hover {
  border-color: var(--green-medium);
}

/* FS-023 — a facet the list will filter by, but cannot yet. Organizations do
   not exist until their own feature spec. Shown rather than omitted so the bar
   does not have to be re-laid-out when they arrive, and dimmed so it reads as
   "not ready" instead of "no matches". Carries a title attribute saying which
   spec it is waiting for. */
.filter-chip--pending {
  opacity: 0.45;
  cursor: not-allowed;
  border-style: dashed;
}
.filter-chip--pending:hover {
  border-color: var(--line-strong);
}

.filter-chip-value {
  font-weight: 500;
  max-width: 16rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.filter-chip i {
  font-size: 0.7rem;
  color: var(--muted);
}

.picker-option.selected {
  border-color: var(--green-medium);
  background-color: #f0f9f0;
  font-weight: 500;
}

.picker-option:focus-visible {
  outline: 2px solid var(--green-medium);
  outline-offset: 1px;
}

/* ---- List controls row (assessments.php, users.php): sort pills + filter
   chips + search, grouped so each group wraps to a new line as one block on
   narrow screens (label stays with its controls). Replaces the old
   .controls-row / bottom Show-More/Archived toggles. ---- */
.list-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem 1.25rem;
  margin-bottom: 0.75rem;
}

.control-group {
  display: inline-flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: 0.35rem;
}

/* Several chips in one group (the Response Data and comment filters carry one
   per category) need to wrap, or they run off a narrow screen. The list pages
   keep the default nowrap: one or two short chips are better kept together. */
.control-group--wrap { flex-wrap: wrap; }

/* Group label ("Sort by:", "Filter:", "Search:"). Unlike .sort-label this stays
   visible on mobile — the groups wrap instead of scrolling. */
.control-label {
  font-size: 1rem;
  color: var(--muted);
  margin-right: 0.15rem;
  white-space: nowrap;
}

/* The search group grows to take remaining width. */
.control-group--search { flex: 1 1 260px; min-width: 200px; }

/* ---- Live search box (client-side filter on list pages) ---- */
.list-search {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  flex: 1;
  padding: 0.3rem 0.75rem;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: 20px;
  transition: border-color 0.2s ease;
}

.list-search:focus-within { border-color: var(--green-medium); }

.list-search > i { color: var(--muted); font-size: 0.85rem; }

.list-search input {
  border: none;
  outline: none;
  background: transparent;
  font: inherit;
  font-size: 0.95rem;
  width: 100%;
  color: var(--ink);
}

.list-search .list-search-clear {
  cursor: pointer;
  color: var(--muted);
  font-size: 0.85rem;
  display: none;
}

.list-search.has-text .list-search-clear { display: inline; }

/* ---- Toolbar under .list-controls: the result count with the page's actions on
   the right (responses.php, comments.php, comments-multi.php). The list pages
   use a bare .list-count instead, having nothing to export. ---- */
.list-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 0.75rem;
}

.list-toolbar .list-count { margin: 0; }

.list-actions {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.list-actions .custom-button {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

/* Matches the .response-nav treatment: an <a> can't carry :disabled. */
.list-actions .custom-button.disabled {
  opacity: 0.45;
  pointer-events: none;
}

@media (max-width: 768px) {
  .list-toolbar {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* Result count under the controls. */
.list-count {
  font-size: 0.85rem;
  color: var(--muted);
  margin: 0 0 0.75rem;
}

.list-empty {
  padding: 2rem;
  text-align: center;
  color: var(--muted);
}

/* ---------------------------------------------------------------------------
   Danger zone — the permanent-delete block. Shared by the assessment page and
   the user page (FS-012). Always the LAST thing on a page, visually separated,
   so it is never adjacent to a routine control.
   --------------------------------------------------------------------------- */
.danger-zone {
    max-width: 1400px;
    margin: 3rem auto 2rem;
    padding: 1rem 1.25rem;
    display: flex;
    align-items: center;
    gap: 1.25rem;
    flex-wrap: wrap;
    border: 1px solid #f0c9c4;
    border-left: 5px solid #c0392b;
    border-radius: 8px;
    background: #fdf6f5;
}

.danger-zone-text {
    flex: 1 1 22rem;
    font-size: 0.9rem;
    color: #7a5c58;
    line-height: 1.45;
}

.danger-zone-text strong {
    display: block;
    font-weight: 500;
    color: #8c2f22;
    margin-bottom: 0.15rem;
}

/* Two actions side by side (FS-012): Reassign is an ordinary button, Delete is
   the destructive one. They wrap together rather than separating on a narrow
   screen. */
.danger-zone-actions {
    display: flex;
    gap: 0.6rem;
    flex-wrap: wrap;
    align-items: center;
}

/* What is blocking a delete, itemised. An unexplained disabled button is worse
   than no button, so this list is the point of the whole block. */
.purge-blockers {
    margin: 0.5rem 0 0;
    padding-left: 1.1rem;
    font-size: 0.88rem;
    line-height: 1.6;
}

.purge-blockers li { color: #8c2f22; }

@media (max-width: 768px) {
    .danger-zone { margin: 2rem 1rem; }
}

/* ---------------------------------------------------------------------------
   Feedback — the toast and the inline message (REL-009 R5/R6).

   Two components, because there are two situations, and the difference is
   whether the reader has to do something. A confirmation is ambient and goes
   away; anything they must act on stays until they act. See js/notify.js for
   the reasoning, including why an error is never on a timer.

   These replace four separate implementations: .detail-flash (assessment page),
   .te-flash (template editor), the box template-editor.js injected by hand, and
   ~41 browser alert() calls.
--------------------------------------------------------------------------- */

.notify-toast {
    position: fixed;
    left: 50%;
    bottom: 24px;
    transform: translateX(-50%);
    background: #2f3b45;
    color: #fff;
    padding: 0.5rem 1rem;
    border-radius: 20px;
    font-size: 0.85rem;
    max-width: min(640px, 92vw);
    text-align: center;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s ease;
    z-index: 1200;
}

.notify-toast.on { opacity: 1; }

/* The inline message. Deliberately NOT a floating pill: it sits in the layout,
   above the thing that failed, and pushes content down — so it cannot be missed
   and cannot cover anything. */
.notify-error {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    background: #f8d7da;
    color: #721c24;
    border: 1px solid #f1b7bc;
    border-radius: 6px;
    padding: 0.7rem 0.9rem;
    margin: 0 0 1rem;
    font-size: 0.92rem;
    line-height: 1.5;
}

.notify-error-text { flex: 1; }

/* A real dismiss control, because the reader — not a timer — decides when they
   have finished with it. */
.notify-error-close {
    flex: none;
    background: none;
    border: 0;
    color: #721c24;
    font-size: 1.25rem;
    line-height: 1;
    padding: 0 0.15rem;
    cursor: pointer;
    opacity: 0.65;
}

.notify-error-close:hover { opacity: 1; }

@media print {
    .notify-toast { display: none !important; }
}

/* ---------------------------------------------------------------------------
   Personalization slots (FS-014).

   <personalized-welcome> and <personalized-thanks> are stored INSIDE the page
   text the assessment already owns. The survey loads none of this stylesheet, so
   a participant sees an ordinary paragraph and never learns a tag was involved.
   /manage loads it, so the same stored string is visibly the owner's own words.

   That is the whole mechanism for "flag it when displaying and editing, but not
   when running the survey": one string, two stylesheets. No duplicate storage,
   no flag column, and nothing to keep in step.

   Same idea as <current> / <desired>, which the survey styles for the rating
   pages — this codebase already had the pattern.
--------------------------------------------------------------------------- */

personalized-welcome,
personalized-thanks {
    display: block;
    background: #fdf3e5;
    border-left: 3px solid #A9641B;
    border-radius: 0 4px 4px 0;
    padding: 0.5rem 0.7rem;
    margin: 0 0 0.7rem;
    color: #2f3437;
}

/* An empty slot is a slot the owner has not used. Showing an empty amber box on
   every page they look at would be noise, so it collapses — but only where it is
   genuinely empty, not merely whitespace-wrapped. */
personalized-welcome:empty,
personalized-thanks:empty {
    display: none;
}

/* In a preview, say whose words these are. The label rides on the container so
   it never becomes part of the text that gets saved back. */
.shows-personalization personalized-welcome::before,
.shows-personalization personalized-thanks::before {
    content: "Your words";
    display: block;
    font-size: 0.68rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #A9641B;
    margin-bottom: 0.2rem;
}

/* FS-014 — the template new assessments start from, for its language. Brand
   green rather than a warning colour: it is a statement of fact about which
   template is standard, not something to act on. */
.status-pill.st--default {
    background: #eef5e8;
    color: #3c7422;
    border: 1px solid #cfe3c2;
}

/* ---- List-page shell. FS-024.
   .users-container / .page-header / .user-grid have carried these three jobs
   since the portal was written, but they live in users.css and are named after
   one page. A second module wanting the same list needed either to load that
   sheet — bringing the user list's own rules with it — or to invent a fourth
   name. These are the generic ones; users.css keeps its own for now, and the
   list pages can converge on these whenever one of them is next touched. ---- */
.list-page {
  max-width: 1200px;
  margin: 0.5rem auto;
  padding: 0 0.5rem;
}

.list-page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 1rem;
}
/* h1 as well as h2: FS-037 makes the page title a real <h1>, and pages convert
   one at a time, so for a while both are page titles. */
.list-page-header h1,
.list-page-header h2 { margin: 0; }

/* ⚠ FS-037 — THE HEAD WRAPS; IT DOES NOT SQUEEZE, AND IT NEVER REVERSES.
   It was a flex row that could not wrap, so on a phone the title was crushed into
   whatever width the right-hand link or button left it — "Power Style Report: Pete
   Behrens" on three lines beside a one-line "← Back to…". The feedback pages had
   worked around that by flipping the head into a reversed column, which put the way
   back ABOVE the title (Pete, 2026-09-18). Now the title keeps its line and whatever
   sits on the right drops beneath it, still right-aligned, when there is no room.
   On a wide screen nothing moves. */
.list-page-header { flex-wrap: wrap; gap: 0.5rem 1rem; }
.list-page-header > :last-child:not(:first-child) { margin-left: auto; }

/* ===========================================================================
   FS-037 — THE WAY BACK. One link style for every page that has one: green,
   weight 600, the base size, "← Back to …", right-justified in the page head.
   Pete, 2026-09-18, of the feedback pages: "Back to feedback … isn't standard
   style." It was .fbp-back there (grey, its own size) and .ps-back on the Power
   Style pages; .page-back is the name to use, and .ps-back wears the same rule
   until those pages are renamed.
   =========================================================================== */
.page-back,
.ps-back {
  flex: none;
  font-size: var(--text-base);
  font-weight: 600;
  color: var(--label-green, #66a12f);
  text-decoration: none;
  white-space: nowrap;
}
.page-back:hover,
.ps-back:hover { color: var(--label-green, #66a12f); text-decoration: underline; }

.list-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 0.75rem;
  margin-bottom: 1rem;
}

@media (max-width: 768px) {
  .list-grid { grid-template-columns: 1fr; }
}

/* A tile's separator, and a value the system will HAVE but does not yet — an
   organization, a Power Style profile. Deliberately still legible rather than
   hidden: "no organization" is information, an empty gap is not. */
.list-grid .status-tile .meta .meta-sep { color: var(--line-strong); margin: 0 0.15rem; }
.list-grid .status-tile .meta .meta-pending { font-style: italic; opacity: 0.65; }

/* FS-024 — an account whose owner never entered the emailed code. The same
   orange on every list that shows one: users, and Power Style Users. */
.status-pill.st--unverified { background: #fde9d9; color: #b3541a; }
/* Several Power Style reports — the templates purple, since "how many" is not a
   reading and must not wear a reading's colour. */
.status-pill.st--reports { background: #efe7fb; color: #7a4ca8; }

/* ---- FS-026 — the language switcher (portalLanguageSwitcher()). A <details>
   menu, so it needs no JavaScript: the sign-in pages load none for a dropdown.
   In the header it sits before your name; on the sign-in pages, top right. ---- */
.lang-switch { position: relative; }
.lang-switch > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.45rem 0.6rem;
  border-radius: 6px;
  color: #53565A;
  font: 500 13px/1 'Roboto', sans-serif;
  letter-spacing: 0.06em;
  user-select: none;
}
.lang-switch > summary::-webkit-details-marker { display: none; }
.lang-switch > summary:hover, .lang-switch[open] > summary { color: #4C8D2B; background: #f5faf2; }
.lang-switch > summary:focus-visible { outline: 2px solid #6CC24A; outline-offset: 2px; }
.lang-switch-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  min-width: 10rem;
  list-style: none;
  margin: 0;
  padding: 0.35rem 0;
  background: #fff;
  border: 1px solid #E8E8E8;
  border-radius: 8px;
  box-shadow: 0 12px 28px -12px rgba(17, 21, 18, 0.35);
  z-index: 1001;
}
.lang-switch-menu a { display: block; padding: 0.45rem 1rem; color: #333; font-size: 14px; text-decoration: none; }
.lang-switch-menu a:hover { background: #f5faf2; color: #2f5d1a; }
.lang-switch-menu a.is-current { font-weight: 600; color: #4C8D2B; }
@media (min-width: 992px) {
  .navbar .nav-item.nav-lang { display: flex; align-items: center; margin-left: 0.25rem; }
}
@media (max-width: 991px) {
  .navbar .nav-item.nav-lang { padding: 0.35rem 1rem; }
  .navbar .nav-lang .lang-switch-menu { position: static; box-shadow: none; border: 0; padding: 0; }
}

/* The five Power Style readings, in the dial's own palette so the pill and the
   needle agree about which zone somebody is in. Text darkened for contrast — the
   arc colours are chosen to be read as a band, not as type. Here, not in
   power/css/profiles.css, since REL-013: report tiles on three pages use them. */
.status-pill.ps-zone--1 { background: #fdf3d5; color: #8a6212; }
.status-pill.ps-zone--2 { background: #fdf7e4; color: #8a6212; }
.status-pill.ps-zone--3 { background: #e7f1d8; color: #43701c; }
.status-pill.ps-zone--4 { background: #eaf2f9; color: #23628f; }
.status-pill.ps-zone--5 { background: #ddebf6; color: #1d5a85; }
/* FS-037 (Pete, 2026-09-18) — a two-word reading wraps to two lines, centred:
   "Highly / Accommodative" rather than one pill as wide as the tile's corner.
   `min-content` makes each word its own line, so "Balanced" stays one. The
   radius drops so a two-line pill is a rounded box, not a lozenge. */
.status-pill[class*="ps-zone--"] {
  width: min-content;
  white-space: normal;
  text-align: center;
  line-height: 1.25;
  border-radius: 8px;
  padding-top: 0.15rem;
  padding-bottom: 0.15rem;
}

/* ---- REL-013 — a list page's heading stays put; the tiles scroll under it.
   Pete: "I'd like the tiles to scroll, but not the header." The menu sticks to
   the top and the page heading + filter bar stick beneath it.

   OPT-IN: only a page carrying .list-sticky does this, so a long report or an
   assessment page keeps the menu that scrolls away as it always has.

   --nav-h is the menu's REAL height, measured in header.php — it is not a
   constant: the menu wraps, and on a phone it opens downward.

   z-index sits BELOW the picker's backdrop (999), so a chooser opened from the
   bar still covers the bar.

   ⚠ NOT ON A PHONE. There the bar wraps to four rows and, with the menu, pinned
   283px of an 812px screen — over a third of it, permanently. Measured, not
   guessed (REL-013 build). From a tablet up it is ~190px of 800+. ---- */
/* REL-013 (Pete) — "the menu stays on top for the rest of the pages in the
   portal." EVERY page that wears the portal header, at every width: a 58px menu
   is worth its room even on a phone, where the list heading below is not. The
   survey instruments (Alignment's survey.php, Power Style's walk) draw their
   own shells and never load this header, so they scroll as before. */
.navbar {
  position: sticky;
  top: 0;
  z-index: 990;
}
/* 🔴 A PHONE'S OPENED MENU SCROLLS INSIDE ITSELF, AND NEVER SCROLLS THE PAGE.
   (Pete, 2026-09-17: as an admin "it takes up the whole screen and more and I
   can't get to the logout, because if I try to scroll to it, it collapses.")

   Both halves of that were one bug, and 100vh was it:

   1. ⚠ 100vh ON iOS SAFARI IS THE *LARGE* VIEWPORT — the height with the address
      bar hidden, 60-100px more than what is actually on screen. So the cap was
      bigger than the screen, the sheet never became scrollable, and its last
      item — Logout — simply sat below the fold with no way to reach it. 100dvh
      is the visible viewport and shrinks when the address bar comes back.
      The 100vh line stays first as the fallback for anything without dvh.

   2. With the sheet not scrollable, the swipe went to the PAGE instead — and a
      page that moves is exactly what REL-016's auto-collapse watches for, so
      reaching for Logout closed the menu. overscroll-behavior: contain keeps the
      gesture inside the sheet even at its ends, so from now on the page moving
      really does mean "I am done with the menu" and closing it is right.

   The bottom padding is so the last item is not flush against the cut. */
@media (max-width: 991px) {
  .navbar .navbar-collapse {
    max-height: calc(100vh - var(--nav-h, 58px));
    max-height: calc(100dvh - var(--nav-h, 58px));
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 0.75rem;
  }
}

/* Anything that scrolls itself into view must clear the pinned bar. Without this
   a notification that scrolls into view (manage/js/notify.js) lands at viewport
   top — which is BEHIND the bar, since the bar is sticky and paints over it.
   One line, every page, every jump: an anchor, a focused field, scrollIntoView. */
html { scroll-padding-top: calc(var(--nav-h, 58px) + 8px); }
@media (min-width: 768px) {
  .list-sticky {
    position: sticky;
    top: var(--nav-h, 56px);
    z-index: 980;
    background: #f8f9fa;      /* the page ground, so tiles vanish beneath it */
    padding-top: 0.5rem;
    margin-top: -0.5rem;
  }
}

/* ============================================================
   FS-033 — FEEDBACK: the edge tab and the form it opens (REL-016)

   ⚠ The tab is position: fixed and outside the navigation, on purpose. REL-016's
   flicker fix turns on --nav-h being measured from the bar and nothing else
   (manage/includes/header.php), so nothing here may add height to a page or take
   part in that measurement.

   It sits on the RIGHT. The local-mail badge is bottom-left, so the two never meet.
   ============================================================ */
.fb-tab {
  position: fixed;
  right: 0;
  top: 40%;
  z-index: 995;                      /* under the picker's backdrop (999), over a page */
  background: #4C8D2B;
  color: #fff;
  /* FS-037 — the caption size and the H4's tracking; it was 10.5px, a seventh size. */
  font: 700 var(--text-micro)/1 'Roboto', system-ui, sans-serif;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.8rem 0.45rem;
  border-radius: 6px 0 0 6px;
  text-decoration: none;
  box-shadow: 0 2px 10px -4px rgba(17, 21, 18, 0.5);
  writing-mode: vertical-rl;
}
.fb-tab:hover, .fb-tab:focus { background: #3f7a22; color: #fff; }
@media print { .fb-tab { display: none; } }

/* ⚠ FS-037 — THE DIALOG IS ON THE SCALE, and it opts in the way a page does: the
   modal carries .portal-type, so its title is a real <h2> at the H2 size (24 / 20px)
   whichever page it opens over — converted or not. Every other word in it is one of
   the two text sizes: the base (15px) for anything read or typed, the caption (13px)
   for hints, the kinds' sub-lines and the technical details. It had nine sizes of
   its own, from 11.5px to 20px. Its buttons are the portal's primary and secondary
   (.custom-button / .secondary-button), not a set of its own. */
.fb-backdrop { position: fixed; inset: 0; background: rgba(17, 21, 18, 0.45); z-index: 998; }
.fb-modal {
  position: fixed;
  z-index: 999;
  top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: min(640px, calc(100vw - 2rem));
  max-height: calc(100vh - 2rem);
  overflow-y: auto;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 24px 60px -20px rgba(17, 21, 18, 0.5);
  padding: 1.35rem 1.4rem 1.2rem;
  font-size: var(--text-base);
  color: var(--ink);
}
/* The title is not the modal's first element (the hidden inputs are), so the H2's
   2rem top margin is taken off here rather than by :first-child. */
.fb-modal h2.fb-h { margin: 0 0 0.25rem; }
.fb-intro { margin: 0 0 1rem; line-height: 1.3; color: var(--ink-mid); }   /* .page-lede */
.fb-form { display: grid; gap: 1rem; }
.fb-field { display: grid; gap: 0.35rem; }
/* A field's label: the base size, bold. Not an H4 — it names a control, and the
   group page's tabs are the guide's only control allowed a heading's look. */
.fb-label { font-size: var(--text-base); font-weight: 700; color: var(--ink); }
.fb-hint { font-size: var(--text-micro); color: var(--ink-soft); line-height: 1.45; }
.fb-input {
  border: 1px solid #cfd3cd; border-radius: 6px; padding: 0.5rem 0.65rem;
  font: inherit; font-size: var(--text-base); font-weight: 400; background: #fff; width: 100%; color: var(--ink);
}
.fb-input:focus { outline: none; border-color: #66a12f; box-shadow: 0 0 0 3px #e7f1d8; }
.fb-textarea { min-height: 110px; resize: vertical; line-height: 1.5; }

/* The three kinds: one choice, made by pressing the thing that describes it. */
.fb-kinds { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0.55rem; }
.fb-kind {
  border: 1px solid #cfd3cd; background: #fff; border-radius: 8px;
  padding: 0.7rem 0.75rem; text-align: left; cursor: pointer; display: grid; gap: 0.15rem;
  font: inherit;
}
.fb-kind:hover { border-color: #c6dfa8; background: #f4f8ef; }
.fb-kind.is-on { border-color: #4C8D2B; background: #eaf3e4; box-shadow: 0 0 0 2px #e7f1d8; }
.fb-kind b { font-size: var(--text-base); font-weight: 700; color: var(--ink); }
.fb-kind.is-on b { color: #3f7a1c; }
.fb-kind span { font-size: var(--text-micro); color: var(--ink-mid); line-height: 1.4; }

.fb-picture { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.fb-picture label.custom-button { cursor: pointer; margin: 0; }
.fb-thumb { display: flex; align-items: center; gap: 0.7rem; margin-top: 0.4rem; }
.fb-thumb img { width: 92px; height: 62px; object-fit: cover; border: 1px solid #e3e5e1; border-radius: 6px; }
.fb-remove { background: none; border: 0; color: #a33a2d; font-size: var(--text-micro); cursor: pointer; text-decoration: underline; }

.fb-context summary { font-size: var(--text-micro); color: var(--ink-mid); cursor: pointer; }
.fb-context dl { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 0.2rem 0.8rem; margin: 0.5rem 0 0; }
.fb-context dt { font-size: var(--text-micro); color: var(--ink-soft); }
.fb-context dd { margin: 0; font-size: var(--text-micro); color: var(--ink-mid); overflow-wrap: anywhere; }

.fb-error {
  margin: 0; padding: 0.55rem 0.7rem; border-radius: 6px;
  background: #fbeeec; border-left: 3px solid #a33a2d; color: #5d3a34;
}
.fb-actions { display: flex; justify-content: flex-end; gap: 0.6rem; flex-wrap: wrap; }
.fb-actions--center { justify-content: center; }

.fb-sent { display: grid; gap: 0.6rem; justify-items: center; text-align: center; padding: 0.6rem 0 0.2rem; }
.fb-sent p { margin: 0; color: var(--ink-mid); max-width: 44ch; }
.fb-tick {
  width: 44px; height: 44px; border-radius: 50%; background: #eaf3e4; color: #3f7a1c;
  display: grid; place-items: center; font-size: 1.25rem;
}

/* FS-033 — the picture did not make it, said on an otherwise successful send.
   Amber rather than red: the words arrived, which is most of what they came for. */
.fb-sent .fb-sent-note {
  padding: 0.55rem 0.7rem; border-radius: 6px;
  background: #fdf6e3; border-left: 3px solid #d9b441; color: #6b5618;
}
/* The picture's own refusal, beside the picture rather than at the foot of the
   form — it is about the thing directly above it. */
.fb-error--image { margin: 0.35rem 0 0; }

/* ===========================================================================
   FS-037 — the text tokens that sit UNDER the four heading levels.
   The levels themselves are in typography.css; these are the three sizes of
   non-heading text, and they replace roughly thirty-five hand-written
   font-sizes across the module.

   .page-lede   the sentence under an H1 or H2 that says what the section is for
   .text-sm     secondary copy — tile meta, table cells, a question's stem
   .text-micro  pills, captions, field notes, and an OVER-LINE

   ⚠ An over-line ("YOUR GROUP" above a group's H1) is .text-micro and NOT an
   H4, even though it looks like a small label: it sits ABOVE its heading, so
   making it a heading would put level 4 above levels 1 and 3. It stays grey
   rather than green, so the green belongs to headings only.
   =========================================================================== */
/* ⚠ NO max-width, and a tight line-height — both Pete, 2026-09-17: "it should
   extend to width", and "can we modify that H2 description text to have a
   tighter row height for when we use it?" It had a 46rem measure, which broke
   the line well before the page's own edge and left the sentence looking like it
   belonged to a narrower column than the heading above it. The page's container
   sets the width; this token does not second-guess it. */
.page-lede {
  font-size: var(--text-base);
  font-weight: 300;
  line-height: 1.3;
  color: var(--ink-mid);
  margin: 0 0 1.25rem;
}

/* ⚠ .text-sm HAS BEEN REMOVED. There is one size for text that is read, and it is
   the base — which body already carries, so a paragraph needs no class at all.
   If you find yourself wanting a "small" reading size, the answer is that the
   thing is either body copy (base) or a caption (.text-micro). */

.text-micro {
  font-size: var(--text-micro);
  line-height: 1.45;
  color: var(--ink-soft);
}


/* ===========================================================================
   FS-037 — THE BOX. `.panel.panel--v2` is the portal's titled box: a head whose
   bottom border IS the divider, and a body. It lived in manage/css/user.css until
   2026-09-18, which meant any other page wanting it had to load the user page's
   stylesheet or reinvent it (manage/profile.php did, with inline padding and a
   gradient .section-divider). Pete: "how we do the boxes on the user detail page,
   that should be a style guide for a box."

   The head holds an H2 on a converted page (`portal-type`) and a legacy <h3> on
   one that is not; both are sized by the type scale, never here.
   =========================================================================== */
.panel--v2 {
  padding: 0;
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 0.9rem;
}
.panel--v2 .panel-head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  padding: 0.5rem 1rem;
  border-bottom: 1px solid #e9ecef;
}
.panel--v2 .panel-head h2,
.panel--v2 .panel-head h3 {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex: 1 1 auto;
  min-width: 0;
}
.panel--v2 .panel-head-actions { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.panel--v2 .panel-body { padding: 0.9rem 1rem; }

/* ===========================================================================
   FS-037 — THE DATA TABLE. The Alignment 360 responses table's look, promoted to
   a component so a second page can have it without copying it (Pete: the admin
   feedback list "should be a table — styled like the alignment 360 responses,
   single line highlighting"). Neutral header band, hairline cell borders, a zebra
   stripe, and the hovered ROW highlighted — every row is one line.

   ⚠ The text is the portal's one base size (15px), where responses.css still
   says 0.85rem. That page is Alignment's and not yet converted; when it is, it
   should drop its own table rules and wear this, and the two will match.
   =========================================================================== */
.data-table-wrap {
  overflow-x: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 6px;
}
.data-table {
  border-collapse: collapse;
  width: 100%;
  color: var(--ink);
}
.data-table th,
.data-table td {
  border: 1px solid #e3e6ea;
  padding: 0.4rem 0.6rem;
  text-align: left;
  vertical-align: middle;
  white-space: nowrap;           /* ONE LINE PER ROW — the point of the layout */
}
.data-table thead th {
  background: #f1f3f5;
  font-family: 'Cabin Condensed', sans-serif;
  font-weight: 700;
  border-bottom: 2px solid var(--line-strong);
}
.data-table tbody tr:nth-child(even) { background: #f6f8f7; }
.data-table tbody tr:hover { background: #eef4f1; }
.data-table tbody tr[data-href] { cursor: pointer; }
/* The identifier column: the one link in the row that looks like one. */
.data-table a.cell-id { color: #137752; font-weight: 600; text-decoration: none; }
.data-table a.cell-id:hover { text-decoration: underline; }
/* A cell that may run long — a title, a name, a page address — is cut with an
   ellipsis rather than being allowed to wrap and break the one-line rule. The full
   value belongs in the cell's title attribute. */
.data-table .cell-trunc {
  max-width: 22rem;
  overflow: hidden;
  text-overflow: ellipsis;
}
.data-table a { color: inherit; text-decoration: none; }

/* ===========================================================================
   FS-037 — THE SINGLE-SELECT FILTER CHIP. The same pill as .filter-chip, with a
   NATIVE <select> inside it instead of a button that opens the picker.

   Pete, 2026-09-18, on the feedback list: the sort / filter / search "should be
   consistent with other sort/filter/search. The one caveat is that I prefer these
   drop downs to our other filter popups — those allow for multi-select, these are
   single select." So the BAR is the shared one (.list-controls, .control-label,
   .list-search) and only the control inside the chip differs.

   Markup:
     <label class="filter-chip filter-chip--select">
       <span>State</span>
       <select name="state">…</select>
       <i class="fas fa-chevron-down"></i>
     </label>
   =========================================================================== */
.filter-chip--select {
  position: relative;
  padding-right: 0.8rem;
}
.filter-chip--select:focus-within { border-color: var(--green-medium); }
.filter-chip--select select {
  -webkit-appearance: none;
  appearance: none;
  border: 0;
  background: transparent;
  font: inherit;
  font-weight: 500;
  color: var(--ink);
  margin: 0;
  /* the clickable area runs under the chevron, so the whole right end opens it */
  padding: 0 1.1rem 0 0;
  cursor: pointer;
  outline: none;
}
.filter-chip--select i {
  position: absolute;
  right: 0.8rem;
  pointer-events: none;
}

/* ===========================================================================
   FS-037 — FEEDBACK ON THE SHARED PILL. Pete, 2026-09-18: "the pill style on all
   feedback pages doesn't match our colored pill styles from other pages." They had
   their own family — a border, sentence case, their own colours. They are
   .status-pill now, like an assessment's status or a user's.

   🔑 COLOUR MEANS STATE, AND ONLY STATE. A kind (idea / problem / question) is a
   category, not a condition, so all three kinds wear the one neutral pill with
   their own icon. Giving them colours too would put two columns of coloured pills
   side by side meaning two different things — the original set did, and it is why
   "planned" and "idea" were the same blue.

   The seven states reuse the shared palette's meanings where one exists:
     received  orange — nobody has answered; the same "follow this up" as unverified
     heard     blue   — somebody is reading it
     planned   purple — later
     building  amber  — in progress; the same as an assessment in Testing
     answered  green  — resolved with a reply; the same as Published
     done      deeper green — resolved and live, the strongest good news
     declined  grey   — closed, quietly
   =========================================================================== */
.status-pill.st--kind         { background: #eef1f4; color: #5a6672; }
.status-pill.st--kind i       { margin-right: 0.3rem; font-size: 0.95em; }
.status-pill.st--fb-received  { background: #fde9d9; color: #b3541a; }
.status-pill.st--fb-heard     { background: #eaf2f9; color: #23628f; }
.status-pill.st--fb-planned   { background: #efe7fb; color: #7a4ca8; }
.status-pill.st--fb-building  { background: #fdf2d6; color: #8a6212; }
.status-pill.st--fb-answered  { background: #e4f0db; color: #3c7422; }
.status-pill.st--fb-done      { background: #cfe6bf; color: #2f5d17; }
.status-pill.st--fb-declined  { background: #f1f2f0; color: #6d716c; }

/* FS-042 — "New here? Start with Getting started": the pointer on an empty page
   (a new Guide's dashboard, an empty Users list). Shared, because both modules draw it. */
.gs-pointer { margin: 0 0 1rem; padding: 0.7rem 1rem; border-left: 3px solid #4C8D2B; background: #f3f8ee; border-radius: 6px; }

/* WHICH ENVIRONMENT (Pete, 2026-09-22; lib/env-tag.php): a yellow LOCAL pill, a red DEV
   pill, beside the brand mark. Production has neither. The portal header and the
   sign-in pages' bar both. REL-022 (Pete): the pill is enough — the light yellow bar
   local had is gone. */
.env-tag {
    display: inline-block; margin-left: 8px; padding: 2px 7px; border-radius: 4px;
    font-family: system-ui, sans-serif; font-size: 0.68rem; font-weight: 700;
    letter-spacing: 0.08em; text-transform: uppercase; vertical-align: middle; line-height: 1.3;
}
.env-tag--local { background: #F2C230; color: #3d3100; }
.env-tag--dev   { background: #C8312B; color: #fff; }
.navbar-brand .env-tag { margin-left: 0; }   /* the brand's own gap spaces it from the mark */
/* A phone has room for the logo, the pill and the menu button and little more: the
   pill shrinks rather than pushing the button onto a new line, and on the narrowest
   (320px) it goes — there it would push the menu button under the logo. REL-022 kept
   that, though the yellow bar that used to say "local" there is gone. */
@media (max-width: 575.98px) {
    .env-tag { padding: 1px 4px; font-size: 0.55rem; letter-spacing: 0.04em; }
}
@media (max-width: 359.98px) {
    .env-tag { display: none; }
}

/* ===== REL-021 — FS-046 / FS-045 ========================================== */
/* The agreement (consent block): drawn on Power Style's account forms and the
 * consent step (power.css carries the same rules for the walk's own sheet). */
.consent-block { display: flex; flex-direction: column; gap: .7rem; margin: 1.1rem 0 .4rem; padding: 1rem 1.1rem;
  border: 1px solid #e3e6df; border-radius: 10px; background: #fbfbf8; font-size: 14.5px; line-height: 1.5; color: #3b3f43; text-align: left; }
.consent-block p { margin: 0; }
.consent-block a, .privacy-body a { color: #3f6f18; text-decoration: underline; }
.consent-check { display: flex; gap: .6rem; align-items: flex-start; cursor: pointer; font-weight: 400; margin: 0; }
.consent-check input { flex: 0 0 auto; width: 18px; height: 18px; margin-top: .15rem; accent-color: #4f8a1f; }
.consent-foot { font-size: 13px; color: #6c757d; }
button[data-consent-submit]:disabled { opacity: .45; cursor: not-allowed; }

/* Footer: Privacy · Terms beside the copyright. */
.foot-links { margin-left: .6rem; white-space: nowrap; }
.foot-links a { color: inherit; text-decoration: underline; }

/* My Account — Your privacy (full width, Tracey). */
#privacyBox { margin-top: 1.25rem; }
.privacy-body p { max-width: none; margin: 0 0 .5rem; }
.privacy-delete { border-top: 1px solid #e3e6df; margin-top: 1rem; padding-top: 1rem; }
.privacy-delete h3 { margin: 0 0 .35rem; }   /* the scale's own h3 (FS-037) */
/* 2026-10-12 (Pete) — the Delete part, and only that part, shaded red with a red button; the privacy statement above
   stays as it is. The button is a link, so the box's green, underlined link style is kept off it. */
.privacy-delete { border: 1px solid #f1c6c1; border-radius: 10px; background: #fdf1f0; padding: 1rem 1.1rem; }
.privacy-delete h3 { color: #b4302a; }
.privacy-delete a.custom-button, .privacy-delete a.custom-button:hover { text-decoration: none; color: #fff; }

/* Delete My Account. */
.delete-prose p { margin: 0 0 .9rem; }   /* the panel's full width (Pete) */
.delete-prose .consent-check { margin: .4rem 0 0; }
.delete-actions { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; margin-top: 1rem; }
.delete-actions .custom-button { margin: 0; }
.delete-narrow .delete-code { max-width: 12ch; }   /* the panel's full width; only the code box is narrow */
.delete-code { font-size: 22px; letter-spacing: .3em; max-width: 12ch; font-variant-numeric: tabular-nums; }
.delete-resend { display: flex; gap: .4rem; align-items: baseline; margin-top: .9rem; }
.link-button { background: none; border: 0; padding: 0; color: #3f6f18; text-decoration: underline; cursor: pointer; font: inherit; }

/* The administrator's Delete Account dialog (FS-045 §4.8). */
.delete-dialog { max-width: 640px; width: calc(100% - 32px); padding: 1.4rem 1.5rem; }
.delete-dialog h2 { margin: 0 0 .8rem; }   /* the scale's own h2 */
.delete-options { display: flex; flex-direction: column; gap: .75rem; margin: 0 0 1rem; }
.delete-option { display: flex; gap: .7rem; align-items: flex-start; padding: .8rem 1rem; border: 1px solid #e3e6df; border-radius: 10px; cursor: pointer; font-weight: 400; }
.delete-option input { margin-top: .25rem; accent-color: #b3261e; }
.delete-option b { display: block; margin-bottom: .2rem; }
.delete-expect { display: block; color: var(--ink-soft, #6c757d); font-size: var(--text-small, 14px); margin: -.1rem 0 .35rem; overflow-wrap: anywhere; }
.delete-error { margin: .6rem 0 0; padding: .55rem .75rem; border-radius: 8px; background: #fdecea; color: #8a1f17; font-size: var(--text-small, 14px); }

/* Outside services — marketing contacts (FS-046 §4.6). */
.push-block + .push-block { border-top: 1px solid #e3e6df; margin-top: 1rem; padding-top: 1rem; }
.push-block h3 { margin: 0 0 .5rem; display: flex; gap: .8rem; align-items: baseline; flex-wrap: wrap; }
.push-counts { display: grid; grid-template-columns: max-content 1fr; gap: .2rem 1rem; margin: 0 0 .6rem; }
.push-counts dt { font-weight: 700; } .push-counts dd { margin: 0; font-variant-numeric: tabular-nums; }
.push-actions { display: flex; gap: .6rem; flex-wrap: wrap; margin-top: .6rem; }
.push-list ul { margin: .4rem 0 0; padding-left: 1.2rem; font-size: 14px; }

/* REL-022 — A PICTURE IN A RICH TEXT (lib/rich-text.php): a Getting Started page,
   an announcement, a welcome — and the editor that writes them. A picture is ON ITS
   OWN, BESIDE TEXT in a two-column block, or ABOVE TEXT in a half-width card (Pete,
   2026-10-02; docs/features/prototypes/REL-022-picture-blocks.html):
     on its own   the column's width, text above and below, everywhere;
     Small        a third of the block; on a phone half, still beside its text;
     Medium       half the block; on a phone stacked — the picture first when it is
                  on the left, after its words when it is on the right;
     Above/Below  a card, half the page, the picture over or under its words; cards in a row sit side by side with a thin
                  line between them, and stack on a phone. */
img.rt-alone { display: block; width: 100%; height: auto; border-radius: 6px; margin: 0.4rem 0 0.9rem; }
.rt-pair { display: grid; gap: 1.25rem; align-items: start; margin: 0.4rem 0 1rem; }
.rt-pair-pic img { display: block; width: 100%; height: auto; border-radius: 6px; }
.rt-pair-text { min-width: 0; }
.rt-pair-text > :first-child { margin-top: 0; }
.rt-pair-text > :last-child { margin-bottom: 0; }
.rt-pair.rt-small  { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); }
.rt-pair.rt-medium { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.rt-pair.rt-right.rt-small { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
.rt-pair.rt-right .rt-pair-pic { order: 2; }
.rt-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); margin: 0.4rem 0 1rem; }
.rt-pair.rt-above, .rt-pair.rt-below,
.rt-pair.rt-above.rt-small, .rt-pair.rt-above.rt-medium,
.rt-pair.rt-below.rt-small, .rt-pair.rt-below.rt-medium { grid-template-columns: minmax(0, 1fr); gap: 0.7rem; margin: 0; }
.rt-pair.rt-below .rt-pair-pic { order: 2; }
.rt-row > .rt-pair:nth-child(odd)  { padding-right: 1.5rem; }
.rt-row > .rt-pair:nth-child(even) { padding-left: 1.5rem; border-left: 1px solid #dfe3df; }
.rt-row > .rt-pair:nth-child(n+3)  { margin-top: 1.5rem; }
@media (max-width: 600px) {
  .rt-pair { gap: 0.8rem; }
  .rt-pair.rt-small, .rt-pair.rt-right.rt-small { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .rt-pair.rt-medium { grid-template-columns: minmax(0, 1fr); }
  .rt-row { grid-template-columns: minmax(0, 1fr); }
  .rt-row > .rt-pair:nth-child(odd), .rt-row > .rt-pair:nth-child(even) { padding: 0; border-left: 0; }
  .rt-row > .rt-pair + .rt-pair { margin-top: 1.1rem; padding-top: 1.1rem; border-top: 1px solid #dfe3df; }
}
/* A horizontal line: thin, grey, three quarters across, centred. */
.gs-body hr, div.ann-body hr, .ps-faq-answer hr, .rte-editor hr {
  width: 75%; margin: 1.4rem auto; border: 0; border-top: 1px solid #d5d9dd; opacity: 1; height: 0;
}

/* REL-022 — a cross-link in a definition or an answer ([[term]], power/lib/strings.php):
   a word that leads to another part of the Field Guide, quieter than an ordinary link. */
a.ps-xlink { color: inherit; text-decoration: underline; text-decoration-style: dotted; text-decoration-color: #2f7cb8; text-underline-offset: 3px; }
a.ps-xlink:hover { color: #2f7cb8; text-decoration-style: solid; }
/* A glossary term's preview (REL-022, js/term-peek.js) — the Field Guide's, and since REL-022
   a report's and an attribute page's (FS-048), where a click keeps it open with the way into
   the Field Guide inside it, so the pointer may go into it. */
.fg-peek { position: absolute; z-index: 1060; display: grid; gap: 0.25rem; background: #fff; border: 1px solid #cfd6cc; border-radius: 10px; box-shadow: 0 10px 28px rgba(0,0,0,.16); padding: 0.65rem 0.8rem; font-size: 14px; line-height: 1.5; color: #4b4b4b; pointer-events: none; text-align: left; }
.fg-peek b { color: #212529; font-weight: 600; }
.fg-peek--report { pointer-events: auto; }
.fg-peek-open { margin-top: 0.2rem; color: #2f7cb8; font-weight: 600; text-decoration: none; }
.fg-peek-open:hover, .fg-peek-open:focus-visible { text-decoration: underline; }

/* REL-023 — a request to delete an account, written on My Account (Tracey's note on REL-021). */
.deletion-request { display: flex; flex-direction: column; gap: .4rem; margin-top: .6rem; max-width: 34rem; }
.deletion-request label { font-weight: 500; }
.deletion-request textarea { font: inherit; padding: .45rem .6rem; border: 1px solid #cfd3cd; border-radius: 6px; }
.deletion-request-acts { display: flex; gap: .5rem; justify-content: flex-end; }
