@charset "UTF-8";
/*
 *  help.css — the help module's stylesheet
 *  Copyright © 2021-26 FlyingSkySeeds LLC
 *
 *  ⚠️ A SHARED FILE. Do not edit it to brand one host — that edit is lost the next
 *  time the module is copied. Brand through help_config.php's 'theme' key, which
 *  help_theme_css() prints AFTER this sheet as --help-* properties on :root.
 */

/*
 *  THEME TOKENS
 *
 *  --help-* is the public API: help_config.php 'theme' => ['accent' => '#…'] sets
 *  --help-accent, and so on. The --color-* names are this sheet's internal aliases,
 *  and every one of them now DERIVES from a --help-* token.
 *
 *  Until 2.1.0 it ran the other way — --help-* derived from --color-*, and the
 *  --color-* values were literals — so a theme could reach only the rules written
 *  against --help-*, about half of them. (It reached none in practice: nothing
 *  printed help_theme_css() at all.)
 *
 *  With no theme configured, every value below is exactly what rendered before.
 *  border, text and bg deliberately have NO --help-* default here: rules written as
 *  var(--help-border, #CFD6E6) keep their own fallback, which is what they showed,
 *  while --color-border keeps #E2E8F0. A configured value unifies both.
 *
 *    theme key       property               used for
 *    primary         --help-primary         nav + footer background, headings
 *    primary_hover   --help-primary-hover   button/link hover
 *    accent          --help-accent          buttons, links, active states
 *    text            --help-text            body text
 *    muted           --help-muted           secondary text
 *    bg              --help-bg              page background
 *    bg_soft         --help-bg-soft         tinted panels
 *    border          --help-border          borders, dividers
 *    badge_bg        --help-badge-bg        the badge_text pill beside the logo
 *    badge_fg        --help-badge-fg        its text
 */
:root {
    --help-primary:       #0B1220;
    --help-primary-hover: #1D4ED8;
    --help-accent:        #2563EB;

    --color-bg:        var(--help-bg, #FFFFFF);
    --color-hero-bg:   var(--help-primary);
    --color-text:      var(--help-text, #1E293B);
    --color-muted:     var(--help-muted, #64748B);
    --color-border:    var(--help-border, #E2E8F0);
    --color-cta:       var(--help-accent);
    --color-cta-h:     var(--help-primary-hover);
    --radius:          12px;
    --max:             1100px;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 16px; -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    background: var(--color-bg);
    color: var(--color-text);
    line-height: 1.7;
}

a { color: var(--color-cta); text-decoration: none; }
a:hover { text-decoration: underline; }


/* ====== PAGE LAYOUT (pin footer) ====== */

.help-page {
    display: flex; flex-direction: column; min-height: 100dvh;
}


/* ====== NAV ====== */

.help-nav {
    background: var(--color-hero-bg);
    padding: .9rem 0;
    position: sticky; top: 0; z-index: 100;
    border-bottom: 1px solid rgba(255,255,255,.06);
}

.help-nav-inner {
    width: 100%; max-width: 1100px; margin: 0 auto; padding: 0 1.25rem;
    display: flex; align-items: center; justify-content: space-between; gap: 1rem;
}

.help-nav-logo {
    display: flex; align-items: center; gap: .45rem;
    text-decoration: none;
}
.help-nav-logo img { height: 28px; width: auto; }

.help-nav-title {
    color: rgba(255,255,255,.7); font-size: .9rem; font-weight: 500;
    margin-left: 8px;
}

.help-nav-right { display: flex; align-items: center; gap: .5rem; margin-left: auto; }

.help-nav-btn {
    display: inline-flex; align-items: center; gap: 6px;
    padding: .5rem 1.1rem; border-radius: 8px;
    font-size: .875rem; font-weight: 600; color: #CBD5E1;
    text-decoration: none; transition: color .15s;
}
.help-nav-btn:hover { color: #fff; text-decoration: none; }
.help-nav-btn svg { width: 14px; height: 14px; }


/* ====== TABS ====== */

.help-tabs {
    background: var(--color-bg);
    border-bottom: 1px solid var(--color-border);
    padding: 0 1.25rem;
}

.help-tabs-inner {
    display: flex; gap: 0; max-width: var(--max); margin: 0 auto;
}

.help-tab {
    padding: 14px 20px;
    font-size: .875rem; font-weight: 600; color: var(--color-muted);
    cursor: pointer; border-bottom: 2px solid transparent;
    transition: color .15s, border-color .15s;
    user-select: none;
}
/*  The tabs' own strip: one row that scrolls sideways when several guides, FAQ
    and Get Help outgrow the width, instead of wrapping or squeezing the search
    box. The scrollbar is hidden — the cut-off last tab says there is more. */
.help-tabs-scroll {
    display: flex; flex: 0 1 auto; min-width: 0;
    overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.help-tabs-scroll::-webkit-scrollbar { display: none; }
.help-tabs-scroll .help-tab { flex: 0 0 auto; white-space: nowrap; }
@media (max-width: 720px) {
    .help-tabs-inner  { flex-wrap: wrap; }
    .help-tabs-scroll { flex: 1 1 100%; }
}
.help-tab:hover { color: var(--color-text); text-decoration: none; }
.help-tab.active { color: var(--color-cta); border-bottom-color: var(--color-cta); }
.help-tab[data-choice="6"] { display: none !important; }


/* ====== CONTENT ====== */

.help-content {
    flex: 1;
    max-width: var(--max); margin: 0 auto; padding: .8rem 1.25rem 4rem;
    width: 100%;
}


/* ====== FAQ LIST (flat outline) ====== */

.help-search-bar {
    display: flex; align-items: center; gap: 10px;
    justify-content: flex-end;
}

.help-search-bar input {
    flex: 1; max-width: 280px;
    padding: 8px 12px; font-size: .875rem;
    border: 1px solid var(--color-border); border-radius: 8px;
    background: var(--color-bg); color: var(--color-text);
    outline: none; transition: border-color .15s;
    font-family: inherit;
}
.help-search-bar input:focus { border-color: var(--color-cta); }
.help-search-bar input::placeholder { color: var(--color-muted); }

.help-search-btn {
    display: flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; border-radius: 8px;
    border: 1px solid var(--color-border); background: var(--color-bg);
    cursor: pointer; transition: border-color .15s;
}
.help-search-btn:hover { border-color: var(--color-cta); }
.help-search-btn svg { fill: var(--color-muted); width: 14px; height: 14px; }
.help-search-btn:hover svg { fill: var(--color-cta); }

#allthefaqs { margin-top: 8px; }

.qa_set { margin: 0; }

.qa_questiongroup {
    padding: 12px 4px; cursor: pointer;
    border-bottom: 1px solid var(--color-border);
    transition: background .1s;
}
.qa_questiongroup:hover { background: #F8FAFC; }

.qa_question {
    font-size: .975rem; line-height: 1.5; font-weight: 700;
    color: var(--color-text); margin: 0; display: flex; align-items: flex-start; gap: 10px;
}
.qa_question svg.svgtoggle {
    flex-shrink: 0; width: 16px; height: 16px; margin-top: 3px; cursor: pointer;
}
.qa_question svg.svgtoggle polygon { fill: var(--color-muted); }

.questiontext { flex: 1; }

.qa_answergroup {
    display: none; padding: 12px 8px 20px 30px;
    font-size: .975rem; line-height: 1.7; color: #374151;
    border-bottom: 1px solid var(--color-border);
}

/* Rich Quill answer content — answers render OUTSIDE .ql-editor scope, so
   quill.snow.css doesn't style them here; these rules cover the authoring
   subset (images inline-base64 or repo-hosted, headers, callouts, lists). */
.qa_answergroup h1, .qa_answergroup h2 { margin: 14px 0 6px; color: #111827; line-height: 1.3; }
.qa_answergroup h1 { font-size: 1.15rem; }
.qa_answergroup h2 { font-size: 1.05rem; }
/*  h3 and h4 are NOT here — they are shared with the guide surface further down,
 *  because they are the two headings a shared body actually uses: h3 an ordinary
 *  sub-heading, h4 the reference-card trigger. h1/h2 stay FAQ-only; an answer has
 *  no outer heading of its own, so it may open at a larger size than a numbered
 *  guide section, which already has one. */
.qa_answergroup ul, .qa_answergroup ol { margin: 4px 0 8px; padding-left: 22px; }
.qa_answergroup li { margin: 3px 0; }

/* ====== EDITOR IMAGE RESIZE (quill_image_resize.js, help_creator only) ====== */

/*  The resize frame is positioned against its editor container, so the container
 *  must BE the containing block. Without this the offsets are measured from
 *  whatever positioned ancestor happens to be further up and the frame lands
 *  somewhere else on the page. Declared for both editors, not just the FAQ one. */
#editor-container, #gedit-editor { position: relative; }

#qir-overlay {
    display: none; position: absolute; z-index: 20;
    border: 1.5px dashed var(--color-cta); pointer-events: none;
}
#qir-overlay .qir-handle {
    position: absolute; width: 11px; height: 11px; pointer-events: auto;
    background: #fff; border: 1.5px solid var(--color-cta); border-radius: 2px;
    touch-action: none;
}
#qir-overlay .qir-nw { left: -6px;  top: -6px;    cursor: nwse-resize; }
#qir-overlay .qir-se { right: -6px; bottom: -6px; cursor: nwse-resize; }
#qir-overlay .qir-ne { right: -6px; top: -6px;    cursor: nesw-resize; }
#qir-overlay .qir-sw { left: -6px;  bottom: -6px; cursor: nesw-resize; }
#qir-label {
    position: absolute; top: -26px; left: 0; padding: 2px 7px; white-space: nowrap;
    background: #111827; color: #fff; font-size: 11px; border-radius: 4px;
    font-family: ui-monospace, monospace;
}

/* Topic ids reached six digits once AUTO_INCREMENT advanced past the seeded
   content, and a 28px column rendered them straight into the edit link:
   "990023edit". Sized to the content with a gap that cannot close. */
.qacode { display: none; min-width: 3.8rem; padding-right: .6rem; text-align: right; flex-shrink: 0; font-size: .75rem; font-weight: 600; color: var(--color-muted); font-variant-numeric: tabular-nums; }
.qa_edit { display: none; min-width: 2.4rem; text-align: center; flex-shrink: 0; font-size: .75rem; font-weight: 600; color: var(--color-cta); cursor: pointer; }
.qa_edit:hover { text-decoration: underline; }
.qordercode { display: none !important; }   /* retired: ▲▼ replaced the number */
.qa_hidden_label { margin-left: 8px; font-size: .7rem; color: #EF4444; font-style: italic; }
/* .qa_question prefix outranks quill.snow.css's .ql-snow a color on the list rows */
.qa_question .qa_show {
    display: inline-block; margin-left: 8px; padding: 1px 10px; flex-shrink: 0;
    font-size: .7rem; font-weight: 700; line-height: 1.5; cursor: pointer;
    color: #EF4444; border: 1px solid #EF4444; border-radius: 999px;
}
.qa_question .qa_show:hover { background: #EF4444; color: #fff; }

/* Never-published entry in the admin FAQ list. Deliberately NOT the red "Show"
   pill: that one is a button that fixes a withdrawal in one click, whereas a
   draft needs publishing in the editor. Same-looking controls that do different
   things is how an editor learns to click the wrong one. */
.qa_question .qa_draft {
    display: inline-block; margin-left: 8px; padding: 1px 10px; flex-shrink: 0;
    font-size: .7rem; font-weight: 700; line-height: 1.5; cursor: default;
    color: #92400E; background: #FEF3C7; border: 1px solid #FCD34D; border-radius: 999px;
}

/* Editor state badges */
.help-state-badge {
    display: inline-block; padding: 2px 9px; margin-right: 6px; flex-shrink: 0;
    font-size: .65rem; font-weight: 800; letter-spacing: .06em; line-height: 1.6;
    border-radius: 999px; white-space: nowrap; user-select: none;
}
/*  ONE state, two values. The old pair (NEVER PUBLISHED / UNPUBLISHED EDITS)
 *  described the draft machinery; these describe the only thing a writer needs
 *  to know — whether a reader can see it. Kept as separate classes rather than
 *  one toggled colour so the two states read differently at a glance. */
.help-state-live        { color: #065F46; background: #D1FAE5; border: 1px solid #6EE7B7; }
.help-state-hidden      { color: #92400E; background: #FEF3C7; border: 1px solid #FCD34D; }

/*  Retained: older content and any host still on the previous markup. */
.help-state-unpublished { color: #92400E; background: #FEF3C7; border: 1px solid #FCD34D; }
.help-state-draft       { color: #9A3412; background: #FFEDD5; border: 1px solid #FDBA74; }

.help-btn.disabled { opacity: .35; pointer-events: none; }

/* ?qa= deep-link landing highlight (index.php live preview) */
.qa_deeplinked { animation: qa-flash 2.4s ease-out; }
@keyframes qa-flash { 0% { background: #FEF3C7; } 100% { background: transparent; } }


/* ====== ADMIN CONTROLS ====== */

.help-admin-controls {
    display: none; margin-bottom: 12px;
}

.help-creator-toolbar {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; margin-bottom: 12px;
}
.help-creator-toolbar .help-search-bar { margin: 0; }

/* Column headers for FAQ list in help_creator */
.qa-column-headers {
    display: none; padding: 6px 4px;
    font-size: .7rem; font-weight: 600; letter-spacing: .06em;
    text-transform: uppercase; color: var(--color-muted);
    border-bottom: 1px solid var(--color-border);
}
body.help-creator-page .qa-column-headers { display: flex; align-items: center; gap: 10px; }
.qa-col-question { flex: 1; padding-left: 26px; }
/* Kept in step with .qacode / .qa_edit above — the header row and the data rows
   are separate elements, so a width change to one silently misaligns the other. */
.qa-col-id { min-width: 3.8rem; padding-right: .6rem; text-align: right; }
.qa-col-edit { min-width: 2.4rem; text-align: center; }
.qa-col-order { display: none; }   /* retired with .qordercode */

/* Force admin elements visible on help_creator */
body.help-creator-page .qa_edit,
body.help-creator-page .qacode {
    display: inline !important;
}

.help-checkbox-label {
    display: inline-flex; align-items: center; gap: 8px;
    font-size: .8rem; font-weight: 500; color: var(--color-muted);
    cursor: pointer; user-select: none;
}
.help-checkbox-label input[type="checkbox"] {
    width: 15px; height: 15px; accent-color: var(--color-cta);
}


/* ====== CONTACT FORM CARD (centers inside .help-content, sheet 8 only) ====== */

.help-form-card {
    max-width: 580px;
    margin: 2rem auto 0;
    padding: 2rem 2.25rem;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: 0 2px 12px rgba(0,0,0,.06);
}

@media (max-width: 640px) {
    .help-form-card { padding: 1.25rem 1rem; margin-top: 1rem; }
}


/* ====== CONTACT FORM ====== */

.help-form-intro {
    margin-bottom: 20px; padding-bottom: 16px;
    border-bottom: 1px solid var(--color-border);
}
.help-form-intro p {
    font-size: .975rem; color: #374151; line-height: 1.7; margin: 0 0 8px;
}

.help-form-section { margin-bottom: 20px; }
.help-form-section h3 {
    font-size: 1rem; font-weight: 700; color: var(--color-text); margin: 0 0 2px;
}
.help-form-section .help-form-subtitle {
    font-size: .82rem; color: var(--color-muted); font-style: italic; margin: 0 0 10px;
}

.help-form-input {
    display: block; width: 100%; max-width: 360px;
    padding: 9px 12px; font-size: .925rem; font-family: inherit;
    border: 1px solid var(--color-border); border-radius: 8px;
    background: var(--color-bg); color: var(--color-text);
    margin-bottom: 6px; outline: none; transition: border-color .15s;
}
.help-form-input:focus { border-color: var(--color-cta); }
.help-form-input::placeholder { color: var(--color-muted); }

.help-form-select {
    padding: 9px 12px; font-size: .925rem; font-family: inherit;
    border: 1px solid var(--color-border); border-radius: 8px;
    background: var(--color-bg); color: var(--color-text);
    outline: none; cursor: pointer; min-width: 200px;
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%2364748B' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 10px center;
    padding-right: 32px;
}

.help-form-textarea {
    display: block; width: 100%;
    padding: 10px 12px; font-size: .925rem; font-family: inherit;
    border: 1px solid var(--color-border); border-radius: 8px;
    background: var(--color-bg); color: var(--color-text);
    outline: none; resize: vertical; min-height: 120px;
    transition: border-color .15s;
}
.help-form-textarea:focus { border-color: var(--color-cta); }
.help-form-textarea::placeholder { color: var(--color-muted); }

.form_error {
    display: none; max-width: 360px; padding: 10px 12px; margin: 6px 0;
    font-size: .82rem; text-align: center;
    background: #FEF2F2; border: 1px solid #EF4444; border-radius: 8px;
    color: #DC2626;
}

.help-form-buttons {
    display: flex; gap: 10px; margin-top: 16px; flex-wrap: wrap;
}
.help-form-card .help-form-buttons { justify-content: space-between; }

.help-btn {
    display: inline-block; padding: .5rem 1.1rem;
    border-radius: 8px; font-size: .875rem; font-weight: 600;
    cursor: pointer; transition: background .15s, color .15s;
    text-decoration: none; border: none; font-family: inherit;
}
.help-btn:hover { text-decoration: none; }

.help-btn-primary { background: var(--color-cta); color: #fff; }
.help-btn-primary:hover { background: var(--color-cta-h); }

.help-btn-secondary { color: var(--color-muted); background: transparent; border: 1px solid var(--color-border); }
.help-btn-secondary:hover { border-color: var(--color-cta); color: var(--color-cta); }

.help-btn-sm { padding: .35rem .8rem; font-size: .78rem; }


/* ====== SPINNER ====== */

.top_async { display: none; }

@keyframes help-spin { to { transform: rotate(360deg); } }
.help-spinner::before {
    content: ''; display: block; width: 18px; height: 18px;
    border: 2px solid var(--color-border); border-top-color: var(--color-cta);
    border-radius: 50%; animation: help-spin .6s linear infinite;
}


/* ====== FOOTER (matches app-footer from page_chrome.php) ====== */

.app-footer {
    background: var(--color-hero-bg); color: rgba(255,255,255,.6);
    padding: 0 0 28px; font-size: .8rem;
    margin-top: auto;
}
.app-footer .foot-bottom {
    width: 100%; max-width: 1100px; margin: 0 auto; padding: 20px 1.25rem 0;
    border-top: 1px solid rgba(255,255,255,.08);
    display: flex; justify-content: space-between; align-items: flex-start;
    flex-wrap: wrap; gap: 16px;
}
.app-footer .foot-left { display: flex; flex-direction: column; gap: 10px; }
.app-footer .foot-links { display: flex; gap: 18px; }
.app-footer .foot-links a { color: rgba(255,255,255,.55); transition: color .15s; text-decoration: none; }
.app-footer .foot-links a:hover { color: var(--color-cta); text-decoration: none; }
.app-footer .legal {
    font-size: .7rem; max-width: 52ch; line-height: 1.5; color: rgba(255,255,255,.4);
    text-align: right;
}
@media (max-width: 640px) { .app-footer .legal { text-align: left; } }


/* ====== QUILL EDITOR (help_creator) ====== */

#editor-container { min-height: 350px; background: var(--color-bg); }
#faq-question {
    display: block; width: 100%; margin: 10px 0;
    padding: 9px 12px; font-size: 1rem; font-weight: 700; font-family: inherit;
    border: 1px solid var(--color-border); border-radius: 8px;
    background: var(--color-bg); color: var(--color-text); outline: none;
}
#faq-question:focus { border-color: var(--color-cta); }
#faq-question::placeholder { color: var(--color-muted); font-weight: 400; }
#editor-container, #toolbar-container { border-color: var(--color-border) !important; }

/* Toolbar hover labels are NOT drawn here. Both Quill toolbars use the module's
   one-second tip (data-tip → #gedit-tip, styled below), set by _helpToolbarTips()
   in help.js. There used to be an instant `[title]:hover::after` bubble here; it
   flashed past as the pointer crossed the toolbar, and on buttons the browser's
   own title tooltip could follow it. Do not bring it back. */

.help-editor-controls {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; flex-wrap: wrap; margin-top: 16px;
}
.help-editor-left { display: flex; align-items: flex-end; gap: 10px; }
.help-editor-right { display: flex; align-items: center; gap: 12px; }

.help-field { display: flex; flex-direction: column; gap: 2px; }
.help-field-label {
    font-size: .6rem; font-weight: 700; letter-spacing: .08em;
    text-transform: uppercase; color: var(--color-muted);
}

.help-editor-input {
    width: 80px; padding: 7px 10px; font-size: .875rem; font-family: inherit;
    border: 1px solid var(--color-border); border-radius: 8px;
    background: var(--color-bg); color: var(--color-text); outline: none;
}
.help-editor-input:focus { border-color: var(--color-cta); }
.help-editor-input::placeholder { color: var(--color-muted); }


/* ====== LEGACY COMPAT (ghost text system) ====== */

.ghostext { color: var(--color-muted) !important; }
.textentry { font-family: inherit; }


/*  iOS AUTO-ZOOM — 16px MINIMUM ON ANYTHING TYPEABLE.
*
*  Safari on iOS zooms the whole viewport when a focused input's font-size is
*  under 16px, and it does NOT zoom back out: the layout stays expanded until a
*  hard reload. The module's own type scale put every field under that line —
*  .help-globalsearch input at .85rem, .help-form-input and .help-form-select at
*  .925rem — so tapping the search box or the contact form broke the page on an
*  iPhone.
*
*  Scoped to `hover: none` rather than a width breakpoint on purpose. The trigger
*  is the BROWSER, not the screen: an iPad at 810px zooms exactly the same way, so
*  a max-width rule would have left tablets broken. This also leaves the desktop
*  type scale alone, which a blanket rule would have visibly changed.
*
*  The stylesheet already uses `hover: none` for the same "is this a touch
*  device" question — see .gedit-moves and .qa_moves.
*/
@media (hover: none) {
    .help-globalsearch input,
    .help-form-input,
    .help-form-select,
    .textentry,
    input[type="text"],
    input[type="search"],
    input[type="email"],
    input[type="password"],
    textarea,
    select {
        font-size: 16px;
    }
}


/* ====== RESPONSIVE ====== */

@media (max-width: 640px) {
    .help-nav-title { display: none; }
    .help-form-input { max-width: 100%; }
}


/* ══════════════════════════════════════════════════════════════════════════
   USER GUIDE  (sheet 9)

   A manual, not an accordion: one scrolling document with a sticky contents
   rail. Ctrl+F works across the whole thing and printing produces something
   worth reading, neither of which is true of a click-to-expand list.
   ══════════════════════════════════════════════════════════════════════════ */

.guide-wrap {
    display: flex;
    align-items: flex-start;
    gap: 2.25rem;
    max-width: 1120px;
    margin: 0 auto;
    padding: 1rem 0 4rem;
}

.guide-toc {
    flex: 0 0 232px;
    position: sticky;
    top: 5.5rem;
    max-height: calc(100vh - 7rem);
    overflow-y: auto;
    font-size: .82rem;
    line-height: 1.45;
}
.guide-toc-heading {
    margin: 0 0 .6rem;
    font-size: .68rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
    color: var(--help-primary, #0A2540); opacity: .55;
}
.guide-toc-list { list-style: none; margin: 0; padding: 0; border-left: 2px solid var(--help-border, #CFD6E6); }
.guide-toc-list li { margin: 0; }
.guide-toc-l1 { padding-left: .85rem; }

/* flex + gap, not a min-width on the number. A min-width sized for "3.1" collides
   the moment numbering reaches "12.14" — which is exactly what happened. */
.guide-toc-link {
    display: flex; gap: .45rem; align-items: baseline;
    padding: .28rem .6rem; margin-left: -2px;
    border-left: 2px solid transparent;
    color: var(--help-text, #333); text-decoration: none;
}
.guide-toc-text {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden;
}
.guide-toc-link:hover { color: var(--help-accent, #2B7BE9); }
.guide-toc-link.active {
    color: var(--help-accent, #2B7BE9); font-weight: 600;
    border-left-color: var(--help-accent, #2B7BE9);
}
.guide-toc-num { flex-shrink: 0; opacity: .6; font-variant-numeric: tabular-nums; }

.guide-content { flex: 1 1 auto; min-width: 0; }   /* min-width:0 lets wide code/tables shrink */

.guide-header { margin-bottom: 2rem; padding-bottom: 1rem; border-bottom: 1px solid var(--help-border, #CFD6E6); }
.guide-header h1 { margin: 0; font-size: 1.9rem; line-height: 1.15; color: var(--help-primary, #0A2540); }
.guide-subtitle { margin: .5rem 0 0; opacity: .7; }

.guide-section { scroll-margin-top: 5.5rem; margin-bottom: 2rem; }
.guide-heading { position: relative; margin: 0 0 .65rem; color: var(--help-primary, #0A2540); line-height: 1.25; }
.guide-depth-0 > .guide-heading { margin-top: 2.5rem; font-size: 1.4rem; }
.guide-depth-1 > .guide-heading { margin-top: 1.75rem; font-size: 1.1rem; }
.guide-depth-2 > .guide-heading { margin-top: 1.25rem; font-size: .98rem; }
.guide-num { opacity: .45; font-variant-numeric: tabular-nums; margin-right: .15em; }

/* Anchor stays hidden until the heading is hovered — present for linking,
   absent from the reading experience. Always visible on touch, where there is
   no hover to reveal it. */
.guide-anchor {
    margin-left: .4rem; opacity: 0; text-decoration: none;
    color: var(--help-accent, #2B7BE9); font-weight: 400;
    transition: opacity .12s ease;
}
.guide-heading:hover .guide-anchor, .guide-anchor:focus { opacity: .65; }
@media (hover: none) { .guide-anchor { opacity: .35; } }

.guide-prose { padding: 0; }
.guide-prose > *:first-child { margin-top: 0; }
.guide-prose p { margin: 0 0 .75rem; }
/*  ONE rule for the two headings shared content uses, on both reader surfaces.
 *  h3 = ordinary sub-heading. h4 = the card trigger (h4 + ul → .ref-card, built
 *  at render by _helpBuildRefGrids), which is why h4 is styled the same as h3
 *  rather than smaller: outside a card it is simply another sub-heading.
 *  Colour and weight are explicit so the two surfaces cannot drift on inherit.
 *
 *  ⚠️ SPECIFICITY — COUNT IT, DO NOT EYEBALL IT. The FAQ answer renders INSIDE
 *  `.ql-snow .ql-editor`, so quill.snow.css styles it, and that sheet loads
 *  AFTER this one. The rule to beat is `.ql-snow .ql-editor h3` = (0,2,1).
 *
 *      .qa_answergroup h3                        (0,1,1)  loses
 *      .help-content .qa_answergroup h3          (0,2,1)  TIES → later sheet wins
 *      .help-page .help-content .qa_answergroup  (0,3,1)  wins
 *
 *  The two-class version was tried first and left font-size at Quill's 1.17em
 *  while margin (whose Quill rule is only (0,1,1)) did change — a half-applied
 *  result that looks like the rule "partly working". Three classes are load-
 *  bearing. Same dance as the steps-list rules further down.
 */
.help-page .help-content .guide-prose h3, .help-page .help-content .guide-prose h4,
.help-page .help-content .qa_answergroup h3, .help-page .help-content .qa_answergroup h4 {
    margin: 1.1rem 0 .4rem;
    font-size: .95rem; font-weight: 700;
    color: #111827; line-height: 1.3;
}

/* ⚠️ Guide prose deliberately does NOT carry .ql-editor.
   quill.snow.css (1.3.6) styles `.ql-editor ol li:before` with
   `content: counter(list-0, decimal) '. '` and resets counters on every li — so
   wrapping this content in .ql-editor stamped a stray "0." in front of every
   numbered step and broke the flex layout of .steps-list. The module's existing
   pattern, already noted above for .qa_answergroup, is that stored content
   renders OUTSIDE Quill's scope with explicit rules. These are those rules. */
.guide-prose ul, .guide-prose ol { margin: .35rem 0 .85rem; padding-left: 1.35rem; }
.guide-prose li { margin: .2rem 0; }
.guide-prose ul { list-style: disc; }
.guide-prose ol { list-style: decimal; }
/*  Screenshots get the same frame on both reader surfaces. */
.guide-prose img,
.qa_answergroup img {
    max-width: 100%; height: auto; margin: 6px 0;
    border: 1px solid var(--color-border); border-radius: 6px;
}

/*  Blockquote — DELIBERATELY the plain grey bar, matching what the author sees
 *  while editing. Mirrors Quill's own `.ql-snow .ql-editor blockquote`
 *  (4px #ccc, 16px indent, NO background), so the reader gets what the editor
 *  showed.
 *
 *  ⚠️ Do NOT give this a tint and an accent border. It was tried on 2026-09-11,
 *  copied from .qa_answergroup blockquote, and it made a blockquote look like a
 *  CALLOUT — erasing the distinction between the ❞ button and the Callout menu
 *  for anyone reading the page. A quote is an aside; a callout is an alert.
 *  They must not converge.
 *
 *  (The FAQ surface still uses the tinted form. That divergence is known.) */
.guide-prose blockquote,
.qa_answergroup blockquote {
    margin: .75rem 0;
    padding-left: 16px;
    border-left: 4px solid #ccc;
}
/* Wide content scrolls inside its own box rather than pushing the page sideways */
.guide-prose table { display: block; width: 100%; overflow-x: auto; border-collapse: collapse; }


/* ══ QUILL UTILITY FORMATS ON THE READER SURFACES ════════════════════════════
 *
 *  Alignment, indent, size, monospace and code are written by Quill as CLASSES
 *  (ql-align-center, ql-indent-1, ql-size-large, ql-font-monospace) — and until
 *  now they were styled ONLY by quill.snow.css.
 *
 *  That sheet reaches the FAQ answer, which renders inside `.ql-snow .ql-editor`,
 *  and does NOT reach `.guide-prose`, which deliberately is not (Quill's
 *  `.ql-editor ol li:before` would wreck the guide's list counters). So a SHARED
 *  topic came out centred/indented in the FAQ and flat in the manual — silently,
 *  because the author saw it correct in the editor and correct in the FAQ.
 *
 *  Values are copied verbatim from quill.snow.css so the two paths cannot drift.
 *  On the FAQ, Quill's own rule still wins on specificity and says the same
 *  thing; on the guide, these are the only rules there are.
 *
 *  ⚠️ NOT ported: Quill's nested-LIST renumbering (ol li.ql-indent-1 switches the
 *  counter to lower-alpha, then lower-roman). Only the indentation is here. An
 *  indented paragraph is what the editor's indent button produces and what the
 *  content actually uses; a nested ordered list renumbering a→i→1 would need the
 *  counter chain, which is exactly the machinery the guide surface avoids.
 */
.guide-prose .ql-align-center,  .qa_answergroup .ql-align-center  { text-align: center; }
.guide-prose .ql-align-right,   .qa_answergroup .ql-align-right   { text-align: right; }
.guide-prose .ql-align-justify, .qa_answergroup .ql-align-justify { text-align: justify; }

.guide-prose .ql-indent-1, .qa_answergroup .ql-indent-1 { padding-left: 3em; }
.guide-prose .ql-indent-2, .qa_answergroup .ql-indent-2 { padding-left: 6em; }
.guide-prose .ql-indent-3, .qa_answergroup .ql-indent-3 { padding-left: 9em; }

.guide-prose .ql-size-small, .qa_answergroup .ql-size-small { font-size: .85em; }
.guide-prose .ql-size-large, .qa_answergroup .ql-size-large { font-size: 1.2em; }
.guide-prose .ql-size-huge,  .qa_answergroup .ql-size-huge  { font-size: 1.5em; }

.guide-prose .ql-font-monospace,
.qa_answergroup .ql-font-monospace { font-family: Monaco, 'Courier New', monospace; }

/*  Code. There is no toolbar button for it — this covers pasted and hand-written
 *  markup, and the monospace font option, so a snippet reads as one on both. */
.guide-prose code, .qa_answergroup code {
    background: #f0f0f0; border-radius: 3px; font-size: 85%; padding: 2px 4px;
    font-family: Monaco, 'Courier New', monospace;
}
.guide-prose pre, .qa_answergroup pre {
    background: #f0f0f0; border-radius: 3px; white-space: pre-wrap;
    margin: .5rem 0; padding: 5px 10px;
    font-family: Monaco, 'Courier New', monospace; font-size: 85%;
}


/*  VIDEO EMBEDS — all three surfaces, including the editor.
 *
 *  Quill stores `<iframe class="ql-video" frameborder="0" allowfullscreen src=…>`
 *  with NO width or height, and its own CSS only says display:block/max-width.
 *  An iframe with no dimensions falls back to the HTML default 300×150, so an
 *  embed looked like a postage stamp everywhere — including in the editor.
 *
 *  aspect-ratio rather than the old padding-top box: the element is a real block
 *  with a real height, so it needs no wrapper, and a wrapper is exactly the kind
 *  of markup Quill would flatten on the next save.
 *
 *  The editor is styled too (one step more specific than Quill's own rule, which
 *  loads later) so the author sees the size readers will get.
 *
 *  ⚠️ An embed is THIRD-PARTY content on a public page. Only admins can author
 *  one, and Quill's handler rewrites YouTube/Vimeo links to their embed form —
 *  but it does not restrict the host, so paste deliberately. */
.guide-prose .ql-video,
.qa_answergroup .ql-video,
.ql-snow .ql-editor .ql-video {
    display: block; width: 100%; max-width: 100%;
    aspect-ratio: 16 / 9; height: auto;
    margin: .75rem 0;
    border: 1px solid var(--color-border); border-radius: 6px;
}
.guide-prose .ql-video.ql-align-center,
.qa_answergroup .ql-video.ql-align-center,
.ql-snow .ql-editor .ql-video.ql-align-center { margin: .75rem auto; }
.guide-prose .ql-video.ql-align-right,
.qa_answergroup .ql-video.ql-align-right,
.ql-snow .ql-editor .ql-video.ql-align-right { margin: .75rem 0 .75rem auto; }
.guide-prose pre   { overflow-x: auto; }

.guide-loading, .guide-empty { padding: 2rem 0; opacity: .6; }

/* Admin-only preview flags. These keys are never sent to a reader, but style
   them unmistakably anyway — an admin previewing a manual must be able to tell
   at a glance which sections the public cannot see. */
.guide-adminflag {
    display: inline-block; margin: 0 0 .6rem; padding: 2px 9px;
    font-size: .65rem; font-weight: 800; letter-spacing: .06em;
    color: #92400E; background: #FEF3C7; border: 1px solid #FCD34D; border-radius: 999px;
}

@media (max-width: 860px) {
    .guide-wrap { flex-direction: column; gap: 1rem; padding-top: .5rem; }
    /* The rail stops being a rail on a narrow screen — pinning it there would
       eat the viewport it is meant to help navigate. */
    .guide-toc {
        position: static; flex: 1 1 auto; width: 100%; max-height: none;
        padding-bottom: 1rem; border-bottom: 1px solid var(--help-border, #CFD6E6);
    }
    .guide-header h1 { font-size: 1.5rem; }
}

@media print {
    .help-nav, .help-tabs, .app-footer, .guide-toc, .guide-anchor { display: none !important; }
    .guide-wrap { display: block; max-width: none; padding: 0; }
    .guide-section { break-inside: avoid-page; }
}


/* ── Content classes carried over from the static guide ────────────────────
   The seeded prose uses these nine classes, which previously existed only in
   frontend/marketing/guide.php's inline <style>. Without them the converted
   manual renders as unstyled paragraphs. Scoped under .guide-prose (and the FAQ
   answer box) so they cannot collide with a host project's own CSS.

   Colours are expressed in --help-* tokens where one fits, so a host that
   rethemes the module gets themed callouts rather than DDQRC's blue.
   ────────────────────────────────────────────────────────────────────────── */

.guide-prose .chip, .qa_answergroup .chip, .guide-heading .chip {
    display: inline-flex; align-items: center; vertical-align: middle;
    font-size: .6rem; font-weight: 700; letter-spacing: .05em;
    text-transform: uppercase; border-radius: .3rem;
    padding: .2rem .45rem; line-height: 1; flex-shrink: 0; margin-left: .35rem;
}
.chip-web { background: #e8f0fe; color: #2d4db3; }
.chip-app { background: #e6f4ea; color: #1e7b34; }

/*  border-left-WIDTH and -STYLE, never the `border-left` shorthand.
*
*  The shorthand also sets border-left-color (to currentColor), and it does so
*  at two-class specificity — which beat the one-class .callout-tip/-warn/-note
*  rules below. The upshot was that every callout rendered with the same near
*  black edge and the blue / amber / grey never appeared at all. Splitting the
*  properties leaves the colour to the variant rules, where it belongs. */
.guide-prose .callout, .qa_answergroup .callout {
    border-left-width: 3px; border-left-style: solid; border-radius: 0 8px 8px 0;
    padding: .8rem 1rem; margin: 1.1rem 0;
    font-size: .875rem; line-height: 1.55;
}
/* `> strong:first-child` matters. A callout opens with a bolded LABEL that wants
   its own line ("Tip", "Important — Regenerating invalidates printed signs"), but
   a <strong> emphasising a term mid-sentence must stay inline. The source guide's
   rule was unscoped, so "Require GPS" and friends were breaking mid-paragraph. */
.guide-prose .callout > strong:first-child,
.qa_answergroup .callout > strong:first-child {
    font-weight: 700; display: block; margin-bottom: .2rem;
}
.guide-prose .callout strong, .qa_answergroup .callout strong { font-weight: 700; }
.callout      { border-color: #aeaeb2; }   /* fallback if no variant class */
.callout-tip  { border-color: #2d4db3; background: #f0f4ff; }
.callout-warn { border-color: #b45309; background: #fffbeb; }
.callout-note { border-color: #aeaeb2; background: #f2f2f7; }

/*  THE SAME CALLOUT, INSIDE THE EDITOR.
*
*  The reader's rules above are scoped to .guide-prose / .qa_answergroup, so the
*  identical markup used to render flat in Quill. Repeating them for .ql-editor
*  is what makes the editor show what the reader will see.
*
*  On its own this would be a LIE — Quill would still flatten the div on save.
*  It is only honest alongside js/quill_callout.js, which registers the blot so
*  the markup actually survives. Do not ship one without the other.
*/
.ql-editor .callout {
	border-left-width: 3px; border-left-style: solid; border-radius: 0 8px 8px 0;
	padding: .8rem 1rem; margin: 1.1rem 0;
	font-size: .875rem; line-height: 1.55;
	}
.ql-editor .callout > strong:first-child {
	font-weight: 700; display: block; margin-bottom: .2rem;
	}
.ql-editor .callout strong { font-weight: 700; }

/*  Quill's own picker labelling (content: attr(data-label)) is hard-scoped to
*  .ql-header / .ql-font / .ql-size, so a custom picker shows an empty box
*  unless it brings its own. */
.ql-snow .ql-picker.ql-callout { width: 92px; }
.ql-snow .ql-picker.ql-callout .ql-picker-label::before { content: 'Callout'; }
.ql-snow .ql-picker.ql-callout .ql-picker-label[data-label]:not([data-label=''])::before,
.ql-snow .ql-picker.ql-callout .ql-picker-item[data-label]:not([data-label=''])::before {
	content: attr(data-label);
	}

/*  NUMBERED STEPS — the circled-number list.
*
*  FLAT markup, deliberately:
*
*      <ol class="steps-list">
*        <li><strong>Title</strong>Body…</li>
*
*  The circle and its number are drawn entirely by CSS from a counter, so there
*  is no badge element to hand-number. The old form nested two divs inside every
*  <li> and typed the number in by hand; that could not be edited in Quill (it
*  flattened each div into its own numbered row) and every insertion meant
*  renumbering the rest by hand. See js/quill_stepslist.js.
*
*  `position: absolute` for the badge rather than flex, so the <li> can hold
*  plain inline content — which is exactly what an editor produces.
*
*  ⚠️ SPECIFICITY: quill.snow.css loads AFTER this file, and it puts its own
*  ::before counter on every `.ql-editor ol li` (0,1,3) plus padding via
*  `.ql-editor ol li:not(.ql-direction-rtl)` (0,2,2). Matching those is not
*  enough — on a tie the later sheet wins — so the editor rules below are
*  deliberately one step more specific, and the padding rule borrows Quill's own
*  :not() to get there.
*/
.guide-prose ol.steps-list,
.qa_answergroup ol.steps-list,
.ql-editor   ol.steps-list {
    list-style: none; padding: 0; margin: .5rem 0;
    counter-reset: step;
}
.guide-prose ol.steps-list > li,
.qa_answergroup ol.steps-list > li,
.ql-editor   ol.steps-list > li {
    counter-increment: step;
    position: relative;
    margin-bottom: 1rem;
    min-height: 28px;
}
/*  Beats .ql-editor ol li:not(.ql-direction-rtl) — see the note above. */
.guide-prose ol.steps-list > li:not(.ql-direction-rtl),
.qa_answergroup ol.steps-list > li:not(.ql-direction-rtl),
.ql-editor   ol.steps-list > li:not(.ql-direction-rtl) {
    padding-left: 2.75rem;
}
.guide-prose ol.steps-list > li::before,
.qa_answergroup ol.steps-list > li::before,
.ql-editor   ol.steps-list > li::before {
    content: counter(step);
    position: absolute; left: 0; top: 0;
    width: 28px; height: 28px; border-radius: 50%;
    background: var(--help-accent, #2B7BE9); color: #fff;
    font-size: .75rem; font-weight: 800;
    display: flex; align-items: center; justify-content: center;
    white-space: normal;

    /*  ⚠️ THE MARGIN RESET IS LOAD-BEARING — do not drop it.
    *
    *  quill.snow.css has:
    *      .ql-editor li:not(.ql-direction-rtl)::before {
    *          margin-left: -1.5em; margin-right: 0.3em; }
    *
    *  That is how Quill hangs its own "1." counter out into the gutter. On an
    *  absolutely positioned badge it does NOT cancel out: `left: 0` resolves to
    *  the li's padding-box edge and THEN the -1.5em margin drags the badge a
    *  further 18px left, off the content edge, where the editor frame clips it.
    *  The 0.3em right margin widened the badge-to-text gap on top of that.
    *
    *  Invisible to getComputedStyle(...).left — that still reports 0px, which is
    *  why comparing position, size and colour showed a perfect match while the
    *  page plainly did not. Compare MARGINS too. */
    margin-left: 0; margin-right: 0;
    text-align: center;
}
/*  The step's TITLE is a direct child and gets its own line; a <strong>
    emphasising a word mid-sentence must stay inline. */
.guide-prose ol.steps-list > li > strong:first-child,
.qa_answergroup ol.steps-list > li > strong:first-child,
.ql-editor   ol.steps-list > li > strong:first-child {
    display: block; margin-bottom: .2rem; font-size: .9375rem;
}

/*  LEGACY nested form — renders IDENTICALLY to the flat one, on purpose.
*
*  testmanny and production share one database but deploy separately, so there
*  is always a window where new CSS meets old markup (or the reverse). Rather
*  than depend on migrating data and shipping CSS in the right order, both forms
*  are made to render the same:
*
*    · the hand-typed <div class="step-badge">3</div> is HIDDEN — the ::before
*      counter above already draws that number, in the same place. Showing both
*      would print it twice.
*    · .step-body stops being a flex child and is simply a block, which is what
*      it looks like once the badge is out of the flow.
*
*  So a nested <li> and a flat <li> are pixel-equivalent, and the migration can
*  run before or after a deploy without ever leaving a broken page. The retired
*  static guide.php still carries this markup and has its own stylesheet, so it
*  is unaffected either way. */
.guide-prose ol.steps-list > li > .step-badge,
.qa_answergroup ol.steps-list > li > .step-badge,
.ql-editor   ol.steps-list > li > .step-badge {
    display: none;
}
.guide-prose ol.steps-list > li > .step-body,
.qa_answergroup ol.steps-list > li > .step-body,
.ql-editor   ol.steps-list > li > .step-body {
    min-width: 0;
}
.guide-prose ol.steps-list > li > .step-body > strong,
.qa_answergroup ol.steps-list > li > .step-body > strong,
.ql-editor   ol.steps-list > li > .step-body > strong {
    display: block; margin-bottom: .2rem; font-size: .9375rem;
}
/* `>` matters: the step's TITLE is a direct child and should be its own line,
   but a <strong> emphasising a word mid-sentence must stay inline. The source
   guide's rule was unscoped and broke those onto their own lines. */
.guide-prose .step-body > strong, .qa_answergroup .step-body > strong { display: block; margin-bottom: .2rem; font-size: .9375rem; }
.guide-prose .step-body p, .guide-prose .step-body span,
.qa_answergroup .step-body p, .qa_answergroup .step-body span { font-size: .875rem; opacity: .8; }

/*  Reference cards. The .ref-grid / .ref-card wrappers are NOT stored — help.js
*  builds them at render time from an <h4> plus the <ul> after it, so the editor
*  only ever holds a flat outline it cannot damage. See _helpBuildRefGrids().
*
*  Mirrored onto .qa_answergroup as well: a shared atom is one body rendered on
*  both surfaces, so a reference list written for the Guide has to survive being
*  read in the FAQ. */
.guide-prose .ref-grid,
.qa_answergroup .ref-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 1rem; margin-top: .75rem;
}
.guide-prose .ref-card,
.qa_answergroup .ref-card {
    border: 1px solid var(--help-border, #CFD6E6); border-radius: 8px;
    padding: 1rem 1.1rem;
}
.guide-prose .ref-card h4,
.qa_answergroup .ref-card h4 {
    font-size: .8rem; font-weight: 700; margin: 0 0 .5rem;
    display: flex; align-items: center; gap: .4rem;
}
.guide-prose .ref-card ul,
.qa_answergroup .ref-card ul { padding-left: 1rem; margin: 0; }
.guide-prose .ref-card li,
.qa_answergroup .ref-card li { font-size: .82rem; opacity: .8; margin-bottom: .2rem; }


/* ══════════════════════════════════════════════════════════════════════════
   GUIDE EDITOR  (sheet 10, help_creator.php)

   Tree left, one section's editor right. The tree is the structural view and
   changes there are immediate; the panel is content and is drafted.
   ══════════════════════════════════════════════════════════════════════════ */

/*  Guide-level bar. Sits ABOVE the two columns and spans both, because what it
 *  controls is the manual rather than the section currently selected. */
.gedit-guidebar { display: flex; justify-content: flex-end; align-items: center; gap: .4rem; padding-top: .75rem; flex-wrap: wrap; }

/*  One chip per guide, in the readers' tab order. The open guide is filled;
    a hidden guide is dimmed and says so, because "why is there no tab for this"
    is the first question about a guide that is still being built. */
.gedit-guides { display: flex; flex-wrap: wrap; gap: .35rem; margin-right: auto; align-items: center; }
.gedit-gchip {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .28rem .7rem; border-radius: 999px; cursor: pointer; user-select: none;
    border: 1px solid var(--color-border); background: var(--color-bg);
    color: var(--color-text); font-size: .8rem; font-weight: 600; text-decoration: none;
    transition: border-color .12s, background-color .12s;
}
.gedit-gchip:hover, .gedit-gchip:focus { border-color: var(--color-cta); outline: none; }
.gedit-gchip.active { background: var(--color-cta); border-color: var(--color-cta); color: #fff; }
.gedit-gchip.is-hidden:not(.active) { opacity: .6; border-style: dashed; }
.gedit-gchip-flag { font-size: .66rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; opacity: .8; }

.gedit-gmove {
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.8rem; height: 1.8rem; border-radius: 7px; cursor: pointer; user-select: none;
    color: var(--color-muted); font-size: .75rem; text-decoration: none;
}
.gedit-gmove:hover, .gedit-gmove:focus { background: var(--help-bg-soft, #F3F6FB); color: var(--color-text); outline: none; }
.gedit-gmove.disabled { opacity: .25; pointer-events: none; }

/*  "+ From another guide…" dialog: the source guide's tree as a checklist. */
.gpull-list {
    /* A FIXED height: the dialog is centred while this still says "Loading…",
       so a list that grew afterwards would push the buttons off-centre. */
    height: min(45vh, 340px); overflow-y: auto; margin: .3rem 0 .6rem;
    border: 1px solid var(--color-border); border-radius: 8px; padding: .3rem .2rem;
}
.gpull-row { display: flex; align-items: baseline; gap: .45rem; padding: .22rem .5rem; font-size: .85rem; cursor: pointer; }
.gpull-row:hover { background: var(--help-bg-soft, #F3F6FB); }
.gpull-row .gedit-num { flex: 0 0 auto; min-width: 2.2rem; color: var(--color-muted); }
.gpull-d1 { padding-left: 1.4rem; }
.gpull-d2 { padding-left: 2.6rem; }
.gset-form select { width: 100%; box-sizing: border-box; }

.gedit-gear {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .3rem .6rem; border-radius: 7px;
    color: var(--help-text, #333); opacity: .72;
    font-size: .82rem; font-weight: 600; cursor: pointer; user-select: none;
    text-decoration: none; transition: opacity .12s, background-color .12s;
}
.gedit-gear:hover, .gedit-gear:focus {
    opacity: 1; background: var(--help-bg-soft, #F3F6FB); outline: none;
}

/*  The gear alone is the target on a phone; the word would wrap the bar. */
@media (max-width: 640px) { .gedit-gear-label { display: none; } }

/*  Guide Settings form, rendered inside the shared choice overlay — so it needs
 *  no overlay of its own, no z-index and no centerPopWindow() branch. */
.gset-form { text-align: left; }
.gset-form .help-field-label { display: block; margin: .6rem 0 .2rem; }
.gset-form input[type="text"] { width: 100%; box-sizing: border-box; }
.gset-check { display: flex; align-items: center; gap: .5rem; margin: .9rem 0 .2rem; font-weight: 600; }
.gset-check input { margin: 0; }

.gedit-wrap { display: flex; align-items: flex-start; gap: 1.5rem; padding-top: .75rem; }

.gedit-tree-col { flex: 0 0 380px; min-width: 0; }
.gedit-panel-col { flex: 1 1 auto; min-width: 0; }

.gedit-tree-head {
    display: flex; align-items: center; justify-content: space-between; gap: .5rem; flex-wrap: wrap;
    padding-bottom: .5rem; margin-bottom: .35rem;
    border-bottom: 1px solid var(--help-border, #CFD6E6);
    font-weight: 700; font-size: .9rem;
}

.gedit-tree { max-height: 68vh; overflow-y: auto; }

.gedit-node {
    display: flex; align-items: flex-start; gap: .4rem;
    padding: .3rem .4rem; border-radius: 6px; cursor: pointer;
    font-size: .82rem; line-height: 1.35;
}
.gedit-node:hover { background: #F8FAFC; }
.gedit-node.selected { background: #EFF6FF; box-shadow: inset 2px 0 0 var(--help-accent, #2B7BE9); }
.gedit-d1 { padding-left: 1.4rem; }
.gedit-d2 { padding-left: 2.6rem; }

.gedit-num  { flex-shrink: 0; opacity: .5; font-variant-numeric: tabular-nums; min-width: 2.6em; }
.gedit-flag, .gedit-moves { margin-top: 1px; }
/* Wrap to two lines rather than ellipsis on one. Single-line truncation left
   "I received a rin…" on the selected row — 110px of a section title is not
   enough to tell which section it is, which defeats the point of the tree. */
.gedit-name {
    flex: 1 1 auto; min-width: 0; overflow: hidden;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}

.gedit-flag {
    flex-shrink: 0; padding: 1px 6px; border-radius: 999px;
    font-size: .6rem; font-weight: 800; letter-spacing: .04em;
}
.gedit-flag-unpub  { color: #92400E; background: #FEF3C7; border: 1px solid #FCD34D; }
.gedit-flag-hidden { color: #9A3412; background: #FFEDD5; border: 1px solid #FDBA74; }
.gedit-flag-shared { color: #1E7B34; background: #E6F4EA; border: 1px solid #A7D8B4; }
.gedit-flag-broken { color: #B91C1C; background: #FEF2F2; border: 1px solid #FCA5A5; }

/* Move controls stay out of the way until the row is hovered — a tree with four
   arrows on every line is unreadable. Always shown on touch, where hover does
   not exist. */
.gedit-moves { flex-shrink: 0; display: flex; gap: .1rem; opacity: 0; transition: opacity .1s; }
.gedit-node:hover .gedit-moves, .gedit-node.selected .gedit-moves { opacity: 1; }
@media (hover: none) { .gedit-moves { opacity: 1; } }

.gedit-mv, .gedit-add {
    display: inline-flex; align-items: center; justify-content: center;
    width: 20px; height: 20px; border-radius: 4px; cursor: pointer;
    font-size: .7rem; color: var(--help-text, #333); text-decoration: none;
    border: 1px solid transparent;
}
.gedit-mv:hover, .gedit-add:hover {
    background: #fff; border-color: var(--help-border, #CFD6E6);
    color: var(--help-accent, #2B7BE9); text-decoration: none;
}
.gedit-add { font-weight: 800; }

.gedit-hint { margin-top: .6rem; font-size: .75rem; opacity: .6; line-height: 1.5; }

.gedit-panel-head { display: flex; align-items: center; gap: .5rem; margin-bottom: .5rem; flex-wrap: wrap; }
.gedit-crumb { font-size: .78rem; opacity: .6; }

.gedit-row {
    display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
    margin: .6rem 0;
}
.gedit-topicrow {
    padding: .5rem .7rem; border-radius: 8px;
    background: #F8FAFC; border: 1px solid var(--help-border, #CFD6E6);
}
.gedit-topic-current { flex: 1 1 auto; min-width: 0; font-size: .8rem; opacity: .75; }
.gedit-topic-note    { opacity: .7; white-space: nowrap; }
.gedit-introhint {
    margin: 0 0 6px; padding: 2px 0 2px 8px;
    border-left: 2px solid var(--color-border);
    font-size: .72rem; line-height: 1.5; color: var(--color-muted);
}
/* A section pointing at an unpublished atom renders an empty heading to readers.
   That is recoverable but invisible from the reader side, so say it loudly here. */
.gedit-topic-warn { color: #B45309; opacity: 1; font-weight: 600; }

.gedit-picker {
    margin: .5rem 0; padding: .6rem; border-radius: 8px;
    border: 1px solid var(--help-border, #CFD6E6);
}
.gedit-picker input { width: 100%; margin-bottom: .4rem; }
.gedit-picker-list { max-height: 220px; overflow-y: auto; }
.gedit-pick {
    display: block; padding: .3rem .45rem; border-radius: 5px;
    font-size: .82rem; color: var(--help-text, #333); text-decoration: none; cursor: pointer;
}
.gedit-pick:hover { background: #EFF6FF; color: var(--help-accent, #2B7BE9); text-decoration: none; }

#gedit-editor { min-height: 300px; }
#gedit-title { width: 100%; }

/*  Self-sufficient, deliberately.
*
*  This used to set only `color` and `border-COLOR`. .help-btn declares
*  `border: none`, so a border-color styles nothing — the button rendered as
*  bare red text with no shape. It looked right only where it happened to be
*  paired with .help-btn-secondary, which supplies the border; on its own, in
*  the FAQ editor, it did not. A variant class should not depend on being
*  combined with another one to have a shape. */
.help-btn-danger {
    color: #B91C1C;
    background: transparent;
    border: 1px solid #FCA5A5;
}
.help-btn-danger:hover { background: #FEF2F2; border-color: #B91C1C; }

@media (max-width: 900px) {
    .gedit-wrap { flex-direction: column; }
    .gedit-tree-col { flex: 1 1 auto; width: 100%; }
    .gedit-tree { max-height: 40vh; }
}


/* ══ UNIFIED SEARCH ═══════════════════════════════════════════════════════ */

.help-globalsearch { display: flex; align-items: center; gap: 6px; margin-left: auto; padding: 8px 0; }
.help-globalsearch input {
    width: 210px; padding: 7px 11px; font-size: .85rem; font-family: inherit;
    border: 1px solid var(--color-border, #E2E8F0); border-radius: 8px; outline: none;
}
.help-globalsearch input:focus { border-color: var(--help-accent, #2B7BE9); }

.gsearch-summary { margin: 1rem 0 .75rem; font-size: .9rem; opacity: .8; }
.gsearch-hit { padding: .8rem .2rem; border-bottom: 1px solid var(--color-border, #E2E8F0); }
.gsearch-title { margin: 0 0 .25rem; font-weight: 700; font-size: .95rem; }
.gsearch-snip  { margin: 0 0 .45rem; font-size: .85rem; line-height: 1.55; opacity: .8; }
.gsearch-snip mark { background: #FEF3C7; color: inherit; padding: 0 1px; border-radius: 2px; }

/* Every place one answer can be read. A shared atom shows two — the visible
   proof that the FAQ and the manual are rendering a single body. */
.gsearch-places { display: flex; flex-wrap: wrap; gap: .4rem; margin: 0; }
.gsearch-place {
    display: inline-flex; align-items: center; padding: 2px 10px;
    font-size: .7rem; font-weight: 700; letter-spacing: .03em;
    border-radius: 999px; cursor: pointer; text-decoration: none;
}
.gsearch-place:hover { text-decoration: none; filter: brightness(.95); }
.gsearch-place-faq   { color: #2d4db3; background: #e8f0fe; }
.gsearch-place-guide { color: #1E7B34; background: #e6f4ea; }

@media (max-width: 720px) {
    .help-globalsearch { width: 100%; order: 99; }
    .help-globalsearch input { width: 100%; }
}


/* ══ WAS THIS HELPFUL + contact context ══════════════════════════════════ */

.help-fb {
    display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
    margin-top: 1.1rem; padding-top: .7rem;
    border-top: 1px dashed var(--help-border, #CFD6E6);
    font-size: .8rem;
}
.help-fb-q { opacity: .65; }
.help-fb-thanks { opacity: .75; }
.help-fb-btn {
    display: inline-flex; align-items: center; padding: 2px 12px;
    border: 1px solid var(--help-border, #CFD6E6); border-radius: 999px;
    font-size: .75rem; font-weight: 600; cursor: pointer;
    color: var(--help-text, #333); text-decoration: none;
}
.help-fb-btn:hover {
    border-color: var(--help-accent, #2B7BE9); color: var(--help-accent, #2B7BE9);
    text-decoration: none;
}
.help-fb-ask { border-color: var(--help-accent, #2B7BE9); color: var(--help-accent, #2B7BE9); }

.help-ctx {
    display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
    margin: 0 0 1rem; padding: .55rem .8rem;
    background: #EFF6FF; border: 1px solid #BFDBFE; border-radius: 8px;
    font-size: .82rem;
}
.help-ctx-clear { font-size: .75rem; opacity: .7; cursor: pointer; text-decoration: underline; }

/* The guide's own sections are wide; keep the widget with the prose, not the page */
.guide-section .help-fb { max-width: 46rem; }


/* ══ GUIDE EDITOR — legend and field hints ═══════════════════════════════
   Added after the editor was (fairly) called cryptic. Glyph-only controls and a
   label reading just "Chips" told an editor nothing about what would happen. */

.gedit-legend { margin-top: .8rem; font-size: .74rem; line-height: 1.6; opacity: .8; }
/*  THE EDITOR SHOULD READ LIKE THE PAGE IT PUBLISHES TO.
*
*  quill.snow.css hard-sets .ql-container to 'Open Sans' 14px, and that cascades
*  into .ql-editor. The reader uses the page's own system stack at 16px/1.7, so
*  the SAME content was 14px/1.42 while being edited and 16px/1.7 once published:
*  identical geometry (the steps and callout rules are paired exactly), but
*  different type — so every line wrapped somewhere else and the spacing between
*  blocks read differently. That is the whole discrepancy.
*
*  Scoped PER EDITOR, because the two reader surfaces are not identical to each
*  other: the Guide renders inside .guide-prose (inherits 1rem) and the FAQ
*  inside .qa_answergroup (.975rem). Each editor is matched to the surface it
*  actually feeds, rather than both to one average that fits neither.
*/
/*  NOTE the selectors: `new Quill('#gedit-editor')` turns THAT element into the
 *  .ql-container — the id is the container, not its parent. So
 *  `#gedit-editor .ql-container` matches nothing; the family has to be set on
 *  .ql-editor, which is the child Quill creates inside it. */
#gedit-editor .ql-editor,
#editor-container .ql-editor {
	font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
	line-height: 1.7;
	}
#gedit-editor .ql-editor    { font-size: 1rem; }
#editor-container .ql-editor { font-size: .975rem; }

/*  Quill zeroes p margins (.ql-editor p { margin:0 }); the reader spaces
 *  paragraphs by .75rem. Every line in Quill is its own <p>, so without this the
 *  editor packs blocks tighter than the published page. */
#gedit-editor .ql-editor p {
	margin: 0 0 .75rem;
	}
#editor-container .ql-editor p {
	margin: 0 0 .6rem;
	}

/*  Tooltip for the row controls (guide tree and FAQ list).
*
*  position:fixed on purpose. .gedit-tree is `overflow-y: auto`, so anything
*  drawn inside a row — a ::after, an absolutely positioned child — is clipped
*  as soon as it reaches the edge of the scroll box, which is exactly where the
*  first and last rows live. Fixed takes it out of the clip entirely; help.js
*  supplies the coordinates and clamps them to the viewport.
*
*  pointer-events:none so the tip can never sit between the pointer and the
*  control it is describing.
*/
#gedit-tip {
	position: fixed; z-index: 9999; display: none;
	max-width: 260px; padding: .35rem .5rem;
	border-radius: 5px;
	background: #1F2937; color: #fff;
	font-size: .72rem; line-height: 1.35;
	box-shadow: 0 2px 8px rgba(0,0,0,.25);
	pointer-events: none;
	}

.gedit-legend p { margin: 0 0 .3rem; }
.gedit-legend-rule {
    padding-top: .4rem; border-top: 1px solid var(--help-border, #CFD6E6);
}

.gedit-fieldhint { font-size: .72rem; opacity: .65; line-height: 1.5; }
.gedit-fieldhint code {
    padding: 0 3px; border-radius: 3px;
    background: rgba(0,0,0,.05); font-size: .95em;
}
.gedit-sharedhint { margin: .35rem 0 0; max-width: 46rem; }


/* ── FAQ row reorder controls (admin) ─────────────────────────────────────
   Deliberately identical in look and gesture to the guide tree's ▲▼: one way to
   reorder anything in this system, rather than a number box here and buttons
   there. Hidden until hover for the same reason — arrows on every row of a long
   list is noise. */
/* visibility, NOT display: the space is reserved whether or not the arrows show,
   so revealing them on hover cannot reflow the row. With display:none they were
   appearing into zero width and shunting the id and edit link sideways at the
   exact moment the pointer arrived. */
/* The server only emits .qa_moves for an admin, so this needs no admin guard —
   a reader never receives the element at all. */
.qa_moves { display: inline-flex; visibility: hidden; flex-shrink: 0; gap: .1rem; margin-right: 6px; }
.qa_questiongroup:hover .qa_moves { visibility: visible; }
@media (hover: none) { .qa_moves { visibility: visible; } }

.qa_question .qa_mv {
    display: inline-flex; align-items: center; justify-content: center;
    width: 20px; height: 20px; border-radius: 4px; cursor: pointer;
    font-size: .65rem; color: var(--color-muted); text-decoration: none;
    border: 1px solid transparent;
}
.qa_question .qa_mv:hover {
    background: #fff; border-color: var(--color-border, #E2E8F0);
    color: var(--color-cta, #2563EB); text-decoration: none;
}


/* ── Guide editor search ──────────────────────────────────────────────────
   Same job as the FAQ list's search box, on the surface that needs it more: a
   manual grows to dozens of sections and scrolling a tree to find one is worse
   than scrolling a flat list of fourteen. */

.gedit-search { position: relative; margin: .5rem 0 .35rem; }
.gedit-search input {
    width: 100%; padding: 7px 26px 7px 11px;
    font-size: .82rem; font-family: inherit;
    border: 1px solid var(--color-border, #E2E8F0); border-radius: 8px; outline: none;
}
.gedit-search input:focus { border-color: var(--help-accent, #2B7BE9); }

.gedit-search-clear {
    display: none; position: absolute; right: 8px; top: 50%;
    transform: translateY(-50%);
    width: 18px; height: 18px; line-height: 17px; text-align: center;
    border-radius: 50%; cursor: pointer;
    font-size: 1rem; color: var(--color-muted, #64748B); text-decoration: none;
}
.gedit-search-clear:hover { background: #E2E8F0; color: var(--color-text); text-decoration: none; }

/*  ONE clear button, not two.
*
*  #gedit-search is type="search", so WebKit paints its own × and it landed
*  right beside the styled .gedit-search-clear — two × in the same box.
*
*  Ours is the one to keep. It is the portable one (Firefox paints no native ×
*  at all), it is what the Esc handler and the show/hide toggle drive, and it
*  matches the rest of the editor's styling.
*
*  Scoped to .gedit-search on purpose: the reader's #gsearchbox has NO custom
*  clear and relies on the native × as its only affordance, so this must never
*  become a bare input[type=search] rule.
*/
.gedit-search input::-webkit-search-cancel-button,
.gedit-search input::-webkit-search-decoration {
	-webkit-appearance: none;
	        appearance: none;
	}
.gedit-search input::-ms-clear { display: none; width: 0; height: 0; }

.gedit-search-count { margin: 0 0 .4rem; font-size: .72rem; opacity: .7; }

/* An ancestor shown only to give a hit its place in the tree — dimmed, so it
   reads as context rather than as another result. */
.gedit-node.gedit-context .gedit-name,
.gedit-node.gedit-context .gedit-num { opacity: .45; }

.gedit-name mark { background: #FEF3C7; color: inherit; padding: 0 1px; border-radius: 2px; }
