/* ============================================================
   Forum Design System — PAGES
   Per-surface layout wrappers for the three designed surfaces,
   plus shared scaffolding (panels, forms, tables, buttons) and
   legacy-class bridges that bring every remaining forum page into
   the system without rewriting all markup. Depends on tokens.css +
   components.css.
   ============================================================ */

/* ── FORUM HOME layout ─────────────────────────────────── */
/* 22px under the title row plus 14px over the meta row put 36px between the
   board name and the date line, across a rule that already separates them. The
   rule is the divider; the space was saying the same thing a second time. */
.forum-header{padding:4px 0 14px;border-bottom:1px solid var(--line-soft);display:grid;grid-template-columns:1fr auto;align-items:end;gap:32px}
.forum-header .eyebrow{margin:0 0 8px;color:var(--nd-gold);font-weight:600}
.forum-title{font-family:var(--font-serif);font-weight:600;font-size:clamp(1.5rem, 2.4vw, 2rem);line-height:1.06;letter-spacing:-.018em;color:var(--nd-navy);margin:0}
.forum-title .sub{font-family:var(--font-sans);font-size:13px;font-weight:500;color:var(--ink-3);letter-spacing:0;display:inline-block;margin-left:10px;vertical-align:middle;position:relative;top:-6px}
.board-switch{display:flex;gap:0;border:1px solid var(--line);border-radius:6px;background:#fff;padding:3px;align-self:end}
.board-switch a{font-family:var(--font-sans);font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-2);padding:8px 14px;border-radius:4px;text-decoration:none;display:inline-flex;align-items:center;gap:6px;line-height:1}
.board-switch a:hover{background:var(--bg-muted);color:var(--nd-navy);text-decoration:none}
.board-switch a[aria-current="page"]{background:var(--nd-navy);color:#fff}
.board-switch a[aria-current="page"]:hover{background:var(--nd-navy-2)}
.board-switch .count{font-family:var(--font-mono);font-size:10px;color:inherit;opacity:.7;font-weight:500}
.forum-meta{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:10px 0 12px}
.forum-meta-left{display:flex;align-items:center;gap:14px;flex-wrap:wrap;font-family:var(--font-sans);font-size:12.5px;color:var(--ink-3)}
.forum-meta-left .stat{display:inline-flex;align-items:center;gap:6px}
.forum-meta-left .stat strong{color:var(--nd-navy);font-weight:600;font-variant-numeric:tabular-nums}
.forum-meta-left .stat .mono{font-family:var(--font-mono);font-size:11px;color:var(--ink-2);font-variant-numeric:tabular-nums}
.forum-meta-left .dot{width:3px;height:3px;border-radius:50%;background:var(--ink-4);flex-shrink:0}
.forum-meta-left .sort{display:inline-flex;align-items:center;gap:6px;cursor:pointer;color:var(--ink-2);padding:4px 8px;border-radius:4px}
.forum-meta-left .sort:hover{background:var(--bg-muted)}
.forum-meta-left .sort .lbl{color:var(--ink-3);font-weight:400}
.forum-meta-left .sort .val{font-weight:600}

/* ── SINGLE POST layout ────────────────────────────────── */
.sp-layout{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:36px;padding:6px 0 56px}
.sp-main{min-width:0}
.sp-rail{min-width:0}
.threaded-toggle{display:inline-flex;align-items:center;gap:8px;font-family:var(--font-sans);font-size:12px;font-weight:600;color:var(--ink-2);letter-spacing:.02em;padding:6px 10px;border-radius:4px;cursor:default;background:color-mix(in srgb, var(--nd-green) 12%, transparent)}
.threaded-toggle .toggle{width:26px;height:14px;border-radius:9999px;background:var(--nd-green);position:relative}
.threaded-toggle .toggle::after{content:"";position:absolute;top:1px;right:1px;width:12px;height:12px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.15)}
.threaded-toggle .lock{font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;color:var(--ink-4);text-transform:uppercase;font-weight:500}

/* ── VIEW ALL layout ───────────────────────────────────── */
.va-layout{max-width:880px;margin:0 auto;padding:6px 0 56px}
.va-back-strip{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:4px 0 18px;flex-wrap:wrap}
.va-back-strip a.back{display:inline-flex;align-items:center;gap:6px;font-family:var(--font-sans);font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--nd-navy)}
.va-back-strip a.back:hover{color:var(--accent-hover);text-decoration:none}
.va-back-strip a.back svg{transition:transform .15s ease}
.va-back-strip a.back:hover svg{transform:translateX(-2px)}
.va-back-strip .view-status{display:inline-flex;align-items:center;gap:8px;font-family:var(--font-mono);font-size:10px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-3)}
.va-back-strip .view-status .pip{width:6px;height:6px;border-radius:50%;background:var(--nd-gold)}
/* View All's focused post is an .op-card with a wider gutter. It restates the
   padding at three widths, each one outranking the plain .op-card rule on
   specificity — which is how this page sat out the whole phone pass. The
   vertical values track .op-card now; the 36px gutter is this surface's own. */
.va-layout .op-card{padding:18px 36px 20px}
.va-layout .op-body{max-width:none}
.va-layout .op-signature{max-width:none}

/* ── RESPONSIVE (surfaces) ─────────────────────────────── */
/* Indent plateau — stop adding indent past a set number of levels, so the row
   keeps a width floor no matter how deep the thread runs
   (docs/forum-deep-thread-navigation.md).

   Where the level is has been a server decision since reply_indent_max_depth:
   thread_tree.twig marks the first <ul> that no longer earns a step, and every
   deeper one, with .is-flat. This replaces three hardcoded descendant chains —
   nine deep on desktop, seven at 980px, five at 640px — which could only ever
   count levels, so the setting had no way to reach them and the narrow ones
   plateaued well above anything an admin could ask for.

   It applies at every width on purpose. Narrow screens absorb the indent by
   compressing the step below, the way the index already does, rather than by
   plateauing earlier — a width-keyed plateau silently overrides the setting on
   the surface carrying most of the traffic.

   .rt-list .rt-list.is-flat outranks the only other rule setting these two
   properties (the base .rt-list .rt-list), so it holds regardless of source
   order. Keep the breakpoints below tuning --rt-step rather than restating
   margin-left, or that stops being true. */
.rt-list .rt-list.is-flat{margin-left:0;border-left:0}
.rt-list .rt-list.is-flat > .rt-node > .rt-row::before{display:none}

@media (max-width:980px){
  .forum-header{grid-template-columns:1fr;gap:14px}
  .board-switch{align-self:start;overflow-x:auto}
  .topic{grid-template-columns:44px 1fr;gap:12px;padding:14px 14px 14px 10px}
  .topic-meta .view-all{margin-left:0}
  .sp-layout{grid-template-columns:1fr;gap:24px}
  .sp-rail{display:none}
  .op-card{padding:22px 22px 20px}
  /* Every step narrows together here; the plateau is the setting's, not this
     breakpoint's. Nine levels cost 112px instead of 144px. */
  .rt-list{--rt-step:14px}
}
@media (max-width:760px){
  .va-tree .va-tree{margin-left:14px}
  .va-tree .va-tree .va-tree .va-tree{margin-left:0;border-left:0;padding-left:0}
  .va-tree .va-tree .va-tree .va-tree > .va-node > .va-card{margin-left:0}
  .va-tree .va-tree .va-tree .va-tree > .va-node > .va-card::before{display:none}
  /* View All's focused post is an .op-card too, and this rule outranks the
     plain .op-card padding on specificity at every width below it — which is
     how this page kept the old spacing right through the phone pass. Both
     breakpoints now track what .op-card itself does. */
  .va-layout .op-card{padding:16px 22px 16px}
  .va-card{padding:16px 18px 14px}
}
@media (max-width:640px){
  /* Phone: drop the board name as a visible heading. Two things above it
     already say it — the last breadcrumb crumb and the active .board-switch
     tab — so on a screen with no vertical room to spare it is the third
     copy. Board index only: on the post / register / rules / password pages
     the .forum-title is the only thing naming the page (breadcrumbs.twig
     deliberately omits a leaf crumb on the post page and defers to it), so
     those keep theirs.

     Clipped rather than display:none — this is the page's only <h1>, and
     Google indexes UHND mobile-first. Off-screen keeps it in the document
     outline and the accessibility tree while taking no layout space; the
     zeroed gap then collapses the empty grid row its wrapper leaves behind. */
  /* With the title clipped (above) the switcher is the only thing left in this
     header, so the 6px/22px the title's rhythm called for now reads as the nav
     pinned to the top line. Same 28px band, split evenly, which centres it
     between the subnav rule above and the header rule below. Board index only
     — everywhere else .forum-title is still visible and still wants the
     asymmetric spacing. */
  /* 14px above and below the board switcher, then another 14 under it before
     the date row, put ~44px of empty band between the crumbs and the first
     topic on a screen with no height to spare. The switcher is a bordered pill
     and the meta row is a rule of text -- both read as their own object at 8px
     as readily as at 14. */
  .forum-header--board{gap:0;padding:8px 0}

  /* Phone: the markers sat too far off the subject they belong to. Most of the
     gap is not this margin -- both icons carry side bearing inside their own
     boxes, since neither glyph fills its 24-unit viewBox (the pin spans about
     47% of its width, the padlock about 67%). At a 19.2px topic title the .3em
     margin is 5.8px, but pin-to-lock measured ~12px and lock-to-subject ~8px
     once that bearing is counted on both sides.

     .15em takes the margin to ~2.9px and lands those at ~8px and ~5px, which
     reads as icons attached to the words rather than sitting apart from them.
     Cutting the margin rather than the icon boxes on purpose: narrowing an svg
     scales the glyph down with it, which would make the markers smaller rather
     than closer. */
  :root{--marker-gap:.15em}
  .forum-header--board .forum-title{
    position:absolute;
    width:1px;height:1px;
    margin:-1px;padding:0;border:0;
    overflow:hidden;
    clip:rect(0 0 0 0);
    clip-path:inset(50%);
    white-space:nowrap;
  }

  /* Phone: "New Topic" wrapped onto two lines inside the pill, which read as
     a layout bug. Drop the qualifier — the + icon beside it already says
     "new" — and pin the rest to one line so the shorter label cannot wrap
     either. Desktop keeps the full wording. */
  /* Closes the last two bands above the topic list: under the switcher, and
     under the date / New Topic row before the first card. Bottom keeps a
     little more than top -- the card below it has a border of its own to clear,
     where the switcher above does not. */
  .forum-meta{padding:6px 0 10px}

  .new-topic-btn{white-space:nowrap}
  .new-topic-btn__qualifier{display:none}

  /* Phone: the 44px vote column is 16px wider than the 28px controls it
     holds, so the dead space either side of the arrows plus the row's left
     gutter pushed the title in ~18px for nothing. Tighten the track to the
     control width and pull the gutter in; the 28x20 tap targets are
     untouched. */
  .topic{grid-template-columns:32px 1fr;gap:8px;padding:10px 12px 10px 6px}

  /* Phone: a density pass over the topic card. Each of these is small on its
     own — the point is the sum. Measured at 390px a topic ran ~20px shorter
     after them, so a 25-topic page gives back roughly a screen and a half of
     scrolling. Deliberately kept to a couple of pixels a piece: the card still
     has to read as a card, not as a table row.

       card padding    12 -> 10   top and bottom only; the left gutter and the
                                  vote track are load-bearing (see above)
       title -> meta    6 ->  4   the two are already bound by proximity
       wrapped meta    10 ->  4   row gap only. The byline row wraps at this
                                  width, and the 10px meant for the gaps
                                  BETWEEN chips was being spent again between
                                  the lines, where nothing needed separating.
       meta -> preview 12 ->  8   the thread rule already marks the boundary */
  .topic-title-row{margin-bottom:4px}
  .topic-meta{gap:4px 10px}

  /* Phone: the reply preview reaches back under the vote column instead of
     starting at the topic body's left edge. Nothing occupies that strip once
     the votes end — on the narrowest screen it was ~40px of blank gutter
     running the full height of the preview, which is most of a row.

     -24px lands the thread rule on the vote column's horizontal centre (the
     column spans -40 to -8 relative to the body's left edge, given the 32px
     track and 8px gap above), so the rule reads as hanging from the votes
     rather than floating in the margin. The 24px goes to the subjects. */
  .reply-preview{margin-left:-24px;margin-top:8px}

  /* A topic with no replies still opened a .reply-preview — the block is
     emitted eagerly, because the index renders one flat stream of messages and
     cannot know a topic is childless until it reaches the next one. Empty, it
     still drew its 1.5px thread rule and still spent its margin and padding, so
     a childless topic carried a stub of vertical bar hanging off nothing and
     ~20px of dead card beneath its byline.

     The template now closes that div with no whitespace inside it, which is
     what makes :empty reach it here — :empty does not match an element holding
     only spaces in every engine we ship to, so the trim is load-bearing rather
     than tidiness. Hiding the box drops its margin with it. */
  .reply-preview:empty{display:none}

  /* Phone: the "Continue" link was carrying ~22px above the word and ~21px
     below it, for one line of 12px text. It reads worst on a pinned topic,
     which by design gets no preview rows at all (WindowIndexPreviews) — there
     the link is the only thing in the block, so every one of those gaps is
     separating it from nothing.

     The savings come out of margins rather than padding: the padding is the
     link's tap target and this row is already only ~26px tall, while the
     margins are pure air. is-topic-more keeps a small step when it follows
     preview rows; the :first-child rule that zeroes it for the pinned case
     lives in components.css, because the pinned card sits at the top of every
     board at every width. It outranks the rule below on specificity, so this
     4px only ever reaches a link that really does follow preview rows. */
  .reply-preview{padding-top:2px;padding-bottom:0}
  .reply-preview .pr-continue{margin-top:0;margin-bottom:0;padding-top:4px;padding-bottom:4px}
  .reply-preview .pr-continue.is-topic-more{margin-top:4px}
  /* Same link on the single post page, which was roomier still at 6px margins
     and 8px padding. Kept a touch taller than the index's: there it is one row
     among a preview, here it stands in for a whole branch of the thread. */
  .rt-continue{margin-top:2px;margin-bottom:2px;padding-top:5px;padding-bottom:5px}

  /* Phone: get the OP tool row onto one line. At the old wording the ordinary
     reader's row — vote pill, Send Private Message, Ignore Poster, Reply —
     wanted ~509px against the ~318px inside the card here, so it wrapped.
     Padding alone could not close that, so the labels themselves were
     shortened at source (forum/pages/display.php and lib_forum.php); these
     rules bring the controls in behind them, landing at ~287px. flex-wrap
     stays: an admin's row still runs to nine buttons and is meant to wrap. */
  /* Phone: the post's own header block. Between the card edge and the first
     word of the body there were seven stacked gaps -- card padding, title
     margin, the author row's padding top and bottom, its wrapped row-gap where
     "Posted" falls below the byline, the tool row's padding either side, and
     the body's own margin -- adding up to ~120px before a single line of the
     post itself. Two rules already separate these blocks; the space was doing
     the job a second time.

       card padding      22 / 20   ->  16 / 18
       title -> rule     18        ->  10
       author row        14 both   ->  9 both
       its wrapped gap   14        ->  5   (row gap only; the 12px column gap
                                            still separates avatar from name)
       tools row         12 / 18   ->  8 / 10
       body margin-top   6         ->  4

     The avatar stays 44px. It is the one thing in the block that is sized
     rather than spaced, and shrinking it would change what the header IS
     rather than how much air it sits in. */
  .op-card,
  .va-layout .op-card{padding:16px 16px 18px}
  .op-title{margin-bottom:10px}
  .op-author-row{padding:9px 0;gap:5px 12px}
  .op-tools{gap:5px;padding:8px 0 10px}
  .op-body{margin-top:4px}
  .tool-btn{height:28px;padding:0 9px;font-size:11.5px}
  .reply-btn{padding:7px 11px;font-size:12.5px;gap:6px}
  .vote-pill{padding:2px 3px}
  .vote-pill .v-score{padding:0 4px}
  .reply-preview .pr-row{font-size:12.5px}
  /* Phone: the index preview's reply subject was the smallest thing on the
     card that a reader is actually meant to read — 12.5px against a 19.2px
     topic title, and only 1px clear of its own 11.5px byline. On a phone that
     reads as caption text rather than as a list of posts to choose from, so
     the subjects were being skipped.

     13.5px puts 2px between the subject and its byline, which is enough for
     the subject to lead. 14px was tried first and read too large against the
     rows around it. Set on .pr-title rather than on .pr-row so the byline,
     badges and continue link keep the sizes they were tuned at.

     The reply tree keeps the 14px it has always had at every width: it is the
     post you opened rather than a preview of one, so its subject was never
     competing with a byline for the reader's attention the way this one was.
     Hence no .rt-title rule here — components.css is the only place it is set. */
  .reply-preview .pr-title{font-size:13.5px}
  /* Step 1 keeps its 18px — at the default index_preview_levels of 3 it is the
     only step in play, so the phone renders exactly as it did. The deeper steps
     compress: four full 18px steps plus the row's own 14px padding leaves a
     362px content column too little room for a title. */
  .reply-preview .is-nested-2{margin-left:30px}
  .reply-preview .is-nested-3{margin-left:42px}
  .reply-preview .is-nested-4{margin-left:54px}
  .reply-preview .is-nested-5{margin-left:66px}
  .reply-preview .is-nested-6{margin-left:78px}
  .reply-preview .is-nested-7{margin-left:90px}
  .reply-preview .is-nested-8{margin-left:102px}
  .reply-preview .is-nested-9{margin-left:114px}
  .reply-preview .is-nested-10{margin-left:126px}
  /* The byline leaves the title almost no room at this width, so give the title
     its own line and let the rest wrap beneath it. */
  .reply-preview .pr-row{flex-wrap:wrap}
  .reply-preview .pr-title{flex:1 1 100%}

  /* Group each subject with its own byline, which the old spacing did not.
     Measured at 390px it ran 5px from a subject to its byline and 6px from that
     byline to the next subject — near enough identical that proximity told the
     reader nothing about which byline belonged to which subject, and every line
     read as a peer in one flat list.

     1px inside the pair against 10px between them makes the pairing the first
     thing the eye gets. The trade is deliberately net-zero on height: the 4px
     taken off the wrap gap is the same 4px handed to the padding, so a long
     preview is no longer than it was.

     Padding as longhands, not the shorthand: .is-nested-N sets padding-left, and
     while it currently outranks this rule on specificity, the shorthand would
     silently reset that the moment either selector changed. Same reasoning as
     the margin longhands noted in components.css. */
  .reply-preview .pr-row{row-gap:1px;column-gap:8px;padding-top:2px;padding-bottom:2px}
  /* 2px is the floor for this row. The subject/byline pairing now rests on 1px
     inside a pair against 4px between them, and proximity is only half of what
     carries it -- the byline is also smaller (11.5 vs 13.5), lighter (500) and
     a step back in ink. Take another pixel and the pairs start reading as one
     flat list again, which is the fault the row-gap was introduced to fix. */
  .reply-preview .pr-row.is-nested-1::before,
  .reply-preview .pr-row.is-nested-2::before,
  .reply-preview .pr-row.is-nested-3::before,
  .reply-preview .pr-row.is-nested-4::before,
  .reply-preview .pr-row.is-nested-5::before,
  .reply-preview .pr-row.is-nested-6::before,
  .reply-preview .pr-row.is-nested-7::before,
  .reply-preview .pr-row.is-nested-8::before,
  .reply-preview .pr-row.is-nested-9::before,
  .reply-preview .pr-row.is-nested-10::before{top:11px}
  /* Same problem in the reply tree: .rt-meta never shrinks, so at this width it
     leaves the title nothing. Give the title's line to .rt-head, so the badges
     stay on it with the subject rather than wrapping down ahead of .rt-meta. */
  /* One more pixel off each reply row, top and bottom: 6px now sits between
     one reply's byline and the next reply's subject on the index, 8px in the
     reply tree. The pairing the row-gap buys above still reads at 6:1 against
     the 1px inside a subject/byline pair, which is what has to survive here —
     go much below this and the two stop grouping.

     The tree stays a pixel airier than the index preview on purpose: it is the
     thread you opened rather than a preview of it, and its rows carry a hover
     background whose box is the padding. */
  /* The tree's rows come down to the index preview's rhythm exactly: 1px
     between a subject and its own byline, 4px between one reply and the next.
     Both halves move -- dropping the padding alone would have left 2px inside
     a pair against 4px between them, and at 2:1 the pairs stop grouping. At
     1:4 they read the same way the index preview's do, which is the shape
     that has already survived a few rounds of this.

     This gives up the pixel the tree used to keep on the index preview. That
     was a reasonable default -- it is the thread you opened rather than a
     preview of one -- but the ask here has been for less height twice over,
     and a reader moving between the two surfaces gets one rhythm instead of
     two near-identical ones. */
  .rt-row{flex-wrap:wrap;gap:1px 8px;padding-top:2px;padding-bottom:2px}
  /* The connector tick is positioned from the row's top edge, so it has to
     follow the padding down: 4px of padding plus half a 15px/1.35 line puts the
     subject's optical centre at ~13px, against the 16px desktop sets for the
     same 14px subject over its own 7px padding. .pr-row's tick needs no
     equivalent — 3px plus half a 13.5px/1.35 line still lands on the 12px it
     already uses. */
  .rt-list .rt-list > .rt-node > .rt-row::before{top:11px}
  .rt-head{flex:1 1 100%}

  /* The username was heavier than the subject it belongs to. Measured at 390px
     the index subject was 12.5px/500 and its username 11.5px/600 in the *same*
     ink — one step bolder, so the line meant to recede was the one pulling the
     eye. The reply tree had the flatter version of the same fault: subject and
     username both 600, so neither led.

     Dropping the name to 500 and to --ink-3 puts the byline behind its subject
     and leaves it distinguished from the timestamp beside it by weight alone,
     which is all it needs. Desktop keeps the bolder name: there the byline sits
     at the far right of the subject's own line, where the weight is a scanning
     anchor rather than competition.

     Highlighted accounts are unaffected — admin/mod colour comes from an inline
     style attribute, which outranks this. */
  .reply-preview .pr-by .author,
  .rt-meta .rt-author{font-weight:500;color:var(--ink-3)}

  /* This is the width where the byline wraps below the subject on both
     surfaces — .pr-title and .rt-head are each flex:1 1 100% here, so the line
     is always taken whatever the subject's length. That is what the dash is
     keyed to: it marks a byline that has fallen under its subject.

     It replaces a 12px indent that did the same job. The indent shifted the
     byline off the subject's left edge, which distinguished the two but also
     broke the column the rows were read down; the dash marks the line without
     moving it.

     Two rules, because the two bylines lay their children out differently:
     .rt-meta is an inline-flex with a 6px gap, which spaces the dash already,
     while .pr-by is plain inline text and has to be given the space. */
  .by-dash{display:inline}
  .reply-preview .pr-by .by-dash{margin-right:.35em}
  /* Step 1 keeps 18px and the steps below it compress to 12px — the same shape
     the index preview takes at this width, so a reply reads at the same offset
     on both surfaces. The 12px goes on the THIRD .rt-list, not the second: a
     level takes the step set on its own <ul>, so putting it on the second would
     compress step 1 itself and lose the 18px. Nine levels cost 102px, against
     144px on desktop and the 112px a flat 14px step would have cost. */
  .rt-list{--rt-step:18px}
  .rt-list .rt-list .rt-list{--rt-step:12px}
  .rt-ancestors{padding:9px 10px 10px}

  /* The frame around the tree had no phone rules at all, so it was still
     spending desktop's air: 32px above the section, a 14+6 band under the
     "Replies" heading, and 18+16 under the last row before the View Full
     Conversation button. On a phone that is most of a screen given to four
     rules and a heading.

     The heading band keeps enough to stay a band -- its border is what
     separates the post above from the thread below, and a border with no room
     around it reads as a seam rather than a division. */
  .replies-section{margin-top:20px}
  .replies-head{padding-bottom:8px;margin-bottom:2px}
  .replies-foot{margin-top:10px;padding-top:12px}
}

/* ============================================================
   SHARED SCAFFOLDING + LEGACY BRIDGES
   Everything below derives from the design system to cover pages
   the mockups don't draw (forum index, auth, profile, mail,
   search, sysop, post form). Legacy class names emitted by the
   existing templates are mapped to the new look here.
   ============================================================ */

/* Vertical rhythm wrapper used by legacy layouts */
.wrapcontent{padding:0 0 48px}

/* ── ACCOUNT SETTINGS ──────────────────────────────────── */
/* Centred and narrow: six links have no business spanning 1180px, which is
   what the page did when the legacy grid classes wrapping them turned out not
   to exist in this stylesheet. */
.account-layout{max-width:820px;margin:0 auto;padding:6px 0 56px}
/* auto-fit rather than a breakpoint: one column until two 280px cards and
   their gap fit, which on a 390px phone they never do. */
.account-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:18px;align-items:start}
.account-group{margin:0}          /* .forum-panel's own 18px margin fights the grid gap */
.account-group-title{font-family:var(--font-mono);font-size:10px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-2);margin:0 0 10px}
.account-links{list-style:none;margin:0;padding:0}
.account-links li + li{margin-top:2px}
/* Negative margin so the hover surface reaches the card's padding edge while
   the text still lines up with the group title above it. */
.account-links a{display:block;padding:9px 12px;margin:0 -12px;border-radius:var(--radius);text-decoration:none;transition:background .12s ease}
.account-links a:hover{background:var(--bg-sunk);text-decoration:none}
.account-links .label{display:block;font-family:var(--font-sans);font-size:15px;font-weight:600;color:var(--nd-navy)}
.account-links a:hover .label{color:var(--accent-hover)}
.account-links .hint{display:block;font-family:var(--font-sans);font-size:12.5px;line-height:1.4;color:var(--ink-3);margin-top:2px;text-wrap:pretty}
.account-foot{margin-top:22px;display:flex;justify-content:flex-end}

/* Generic content panel — the workhorse card for long-tail pages */
.forum-panel{
  background:var(--card-raised);border:1px solid var(--line);border-radius:var(--r-card);
  box-shadow:var(--shadow-card);padding:26px 28px;margin:18px 0;
}
.forum-panel + .forum-panel{margin-top:24px}

/* Page-level headings (legacy .title / .subtitle / hN inside content) */
/* .op-title and .forum-title are excluded for the same reason .topic-title is
   excluded from the h2 bridge below: they are designed components carrying
   their own margin, and this bare descendant selector outranked them
   (0,1,1 vs 0,1,0), applying margin:18px 0 12px over the top.

   For .op-title that was the whole visible effect — every other property here
   is byte-identical to its own — and it read as an unexplained band of
   whitespace above every thread title.

   .forum-title lost three: its margin:0, its line-height (1.06, not 1.15) and
   its letter-spacing (-.018em, not -.012em). The margin is why the page
   heading sat in more space than .forum-header's own padding accounts for, and
   it also broke the header's align-items:end — the design lines the title's
   bottom up with the board switcher, which a 12px bottom margin cannot do.

   :where() keeps this at (0,1,1), so the unclassed legacy h1s this bridge
   exists for are unaffected. */
.page h1:not(:where(.op-title,.forum-title)),.page h2.title,.title,.page .forum-h1{
  font-family:var(--font-serif);font-weight:600;color:var(--nd-navy);
  letter-spacing:-.012em;line-height:1.15;margin:18px 0 12px;
}
.title{font-size:1.7rem}
/* :where() so the exclusions cost no specificity — this stays (0,1,1) and
   keeps beating the legacy unclassed h2s it exists for. .topic-title and
   .va-title are designed components with their own sizes in components.css
   (19px and 18px); as a bare descendant selector this bridge outranked them
   (0,1,1 vs 0,1,0) and rendered both at 1.5rem instead. See
   docs/forum/plans/mobile-compactness.md §7 and §15. */
h2.title,.page h2:not(:where(.topic-title,.va-title,.account-group-title)){font-size:1.5rem}
.subtitle,h3.subtitle{font-family:var(--font-serif);font-weight:600;font-size:1.15rem;color:var(--nd-navy);margin:0 0 4px}
.basic,.basicbold{font-family:var(--font-sans);color:var(--ink-2)}
.basicbold{font-weight:600}
.basicbolditalic{font-family:var(--font-sans);font-weight:600;font-style:italic;color:var(--ink-3)}
.tinytext{font-family:var(--font-sans);font-size:12px;color:var(--ink-3)}
.tinylink{font-weight:600;color:var(--nd-green-ink)}
.specialtext{color:var(--nd-navy);font-weight:600}

/* ── FORMS & INPUTS (legacy bridges) ───────────────────── */
input[type=text],input[type=password],input[type=email],input[type=search],
input[type=url],input[type=number],textarea,select,
.formfield,.form-control{
  font-family:var(--font-sans);font-size:14px;color:var(--text);line-height:1.5;
  background:#fff;border:1px solid var(--line);border-radius:var(--r-input);
  padding:9px 12px;width:100%;max-width:620px;display:block;margin:4px 0 12px;
}
textarea,.formfield[name=bodytext]{min-height:220px;resize:vertical;font-size:15px}
input[type=checkbox],input[type=radio]{width:auto;display:inline-block;margin:0 6px 0 0}
select{max-width:320px}
input:focus,textarea:focus,select:focus,.formfield:focus,.form-control:focus{
  outline:none;border-color:var(--nd-green);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--nd-green) 20%, transparent);
}
input::placeholder,textarea::placeholder{color:var(--ink-4)}

/* Typeahead suggestion menu (typeahead.bundle.js — mail compose recipient).
   The plugin injects .twitter-typeahead/.tt-* markup; unstyled it renders
   transparent over the fields below. */
.twitter-typeahead{width:100%;max-width:620px}
.tt-menu{width:100%;margin-top:4px;padding:4px 0;background:var(--card-raised);border:1px solid var(--line);border-radius:var(--r-input);box-shadow:var(--shadow-card);z-index:30}
.tt-suggestion{padding:7px 12px;font-family:var(--font-sans);font-size:14px;color:var(--ink-2);cursor:pointer}
.tt-suggestion:hover,.tt-cursor{background:var(--bg-sunk);color:var(--nd-navy)}
.tt-highlight{font-weight:600;color:var(--nd-navy)}
.tt-hint{color:var(--ink-4)}
label{font-family:var(--font-sans);font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-3);display:block;margin:14px 0 0}
.form-inline label,label.sr-only{display:inline-block}

/* Buttons (legacy bridges). Primary = green; secondary = navy outline. */
.btn,button[type=submit],input[type=submit],.create-post-button a{
  display:inline-flex;align-items:center;gap:8px;cursor:pointer;
  font-family:var(--font-sans);font-size:13px;font-weight:600;letter-spacing:.02em;
  color:#fff;background:var(--nd-green);
  padding:10px 18px;border:0;border-radius:6px;width:auto;max-width:none;
  box-shadow:0 1px 0 oklch(1 0 0 / .25) inset, 0 1px 2px rgba(12,35,64,0.1);
  transition:background .12s ease;text-decoration:none;
}
.btn:hover,button[type=submit]:hover,input[type=submit]:hover,.create-post-button a:hover{
  background:var(--nd-green-hover);color:#fff;text-decoration:none;
}
.btn-default,.btn.btn-default,a.btn{
  background:#fff;color:var(--nd-navy);border:1px solid var(--line);box-shadow:none;
}
.btn-default:hover,a.btn:hover{background:var(--bg-muted);border-color:var(--line-strong);color:var(--nd-navy)}
.btn[disabled],button[disabled],input[disabled]{opacity:.55;cursor:not-allowed}

/* ── TABLES (forum index + sysop lists) ────────────────── */
.table,table.table{
  width:100%;border-collapse:collapse;background:var(--card-raised);
  border:1px solid var(--line);border-radius:var(--r-card);overflow:hidden;
  font-family:var(--font-sans);font-size:13.5px;color:var(--ink-2);margin:10px 0 22px;
}
.table th,.index-table-header,.headerRow th{
  text-align:left;font-family:var(--font-mono);font-size:10px;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3);
  background:var(--bg-sunk);padding:10px 14px;border-bottom:1px solid var(--line);
}
.table td{padding:12px 14px;border-bottom:1px solid var(--line-soft);vertical-align:top}
.table tr:last-child td{border-bottom:0}
.indexRow:hover,.table tbody tr:hover{background:oklch(0.99 0.005 82)}
.table a{color:var(--nd-navy);font-weight:600}
.table a:hover{color:var(--accent-hover);text-decoration:none}

/* ── FORUM INDEX (categories list) ─────────────────────── */
.forum-cat{margin:28px 0 8px}
.forum-cat h2.title{margin:0 0 4px}
.forum-cat .basic{margin:0 0 10px;font-size:13.5px;color:var(--ink-3)}
.table td.num{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-weight:600;color:var(--nd-navy)}
.table .subtitle{margin:0}
.table .subtitle a{font-size:1.05rem}
.new-badge{
  display:inline-flex;align-items:center;
  font-family:var(--font-mono);font-size:9px;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;
  color:#fff;background:var(--nd-green);
  padding:2px 6px;border-radius:9999px;
  vertical-align:middle;position:relative;top:-1px;
  margin-left:4px;
}

/* ── LEGACY FORUM BAR / NAV (forum_main top strip) ─────── */
#forum-bar{display:flex;align-items:baseline;justify-content:space-between;gap:18px;flex-wrap:wrap;padding:18px 0 4px}
#forum-title h4.title{margin:0;font-size:1.6rem}
#forum-nav,#forum-nav-mobile{font-family:var(--font-sans);font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-3);display:flex;flex-wrap:wrap;gap:8px;align-items:center}
#forum-nav span,#forum-nav-mobile span{display:inline-flex;align-items:center;gap:8px}
#forum-nav a,#forum-nav-mobile a{color:var(--ink-2)}
#forum-nav a:hover{color:var(--nd-navy);text-decoration:none}
.server-time{font-family:var(--font-mono);font-size:11px;color:var(--ink-3);display:block;margin:8px 0 14px}
.create-post-button{margin:12px 0}
.boardPages{font-family:var(--font-sans);font-size:13px;color:var(--ink-3);padding:18px 0;display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.boardPages a{min-width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--line);border-radius:4px;background:#fff;color:var(--ink-2);font-weight:600;padding:0 8px}
.boardPages a:hover{background:var(--bg-muted);text-decoration:none;color:var(--nd-navy)}

/* ── POST / REPLY FORM ─────────────────────────────────── */
#individualPost{margin:18px 0}
#individualPost .post{background:var(--card-raised);border:1px solid var(--line);border-radius:var(--r-card);box-shadow:var(--shadow-card);padding:24px 26px}
/* label{margin:14px 0 0} spaces fields from the one above them, but the first
   label in the form has the card's 24px padding above it already — the two
   stacked. (A literal <br /> sat above that in postform.twig as well, which is
   what most of the gap actually was; it is gone.) */
#individualPost form > label:first-of-type{margin-top:0}
#individualPost h4.newPost{font-family:var(--font-serif);font-size:1.05rem;color:var(--nd-navy);margin:22px 0 4px;border-top:1px solid var(--line-soft);padding-top:18px}
.postTips{display:block;font-family:var(--font-sans);font-size:11.5px;color:var(--ink-4);margin:2px 0 2px}
/* The submit used to be spaced off the last field by a literal <br />, removed
   with the two others between the optional-detail fields. It is the only one
   whose gap was doing real work — a submit hard against a text input invites a
   mis-click — so it gets a real margin instead. */
.bottom-post-button{margin-top:16px}

/* ── LEGACY POST DISPLAY (postHeader / postTools / post) ── */
.postHeader{background:var(--card-raised);border:1px solid var(--line);border-bottom:0;border-radius:var(--r-card) var(--r-card) 0 0;padding:18px 22px}
.postHeader h3.title{margin:0 0 6px;font-size:1.35rem}
.postHeader h6{margin:4px 0 0;font-family:var(--font-mono);font-size:11px;font-weight:500;color:var(--ink-3);text-transform:none;letter-spacing:.02em}
.forum-user-icon img{border-radius:50%;border:1px solid var(--line)}
.postTools{background:var(--bg-sunk);border:1px solid var(--line);border-bottom:0;padding:9px 22px;font-family:var(--font-sans);font-size:12px;font-weight:600;letter-spacing:.02em}
.postTools a{color:var(--ink-2)}
.postTools a:hover{color:var(--nd-navy);text-decoration:none}
.post,.post-bottom-bar{background:var(--card-raised);border:1px solid var(--line);border-radius:0 0 var(--r-card) var(--r-card);padding:22px;font-family:var(--font-serif)}
.postContents{font-family:var(--font-serif);font-size:16px;line-height:1.4;color:var(--text)}
.postFooter{border-top:1px dashed var(--line);margin-top:16px;padding-top:12px;font-family:var(--font-sans);font-size:12.5px;font-style:italic;color:var(--ink-4)}
h4.replies,h3.replies{font-family:var(--font-serif);font-weight:600;font-size:1.3rem;color:var(--nd-navy);border-bottom:1px solid var(--line-strong);padding-bottom:12px;margin:26px 0 8px}
.viewallpost{font-family:var(--font-serif);font-size:15.5px;line-height:1.4;color:var(--text);padding:4px 0 8px}

/* ── MAIL ──────────────────────────────────────────────── */
.mail-message-header{background:var(--bg-sunk);font-family:var(--font-mono);font-size:10px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3);border-radius:var(--r-input) var(--r-input) 0 0;border:1px solid var(--line);overflow:hidden}
.mail-message{font-family:var(--font-sans);font-size:14px;color:var(--ink-2);border-bottom:1px solid var(--line-soft)}
.mail-message:nth-child(even){background:var(--bg-sunk)}
.mail-subject{font-weight:600;color:var(--nd-navy)}

/* ── LOGIN / AUTH compact form (legacy #forum-login) ───── */
#forum-login{margin:18px 0}
.form-inline .form-group{display:inline-block;margin:0 8px 8px 0}
.form-inline .form-control{display:inline-block;width:auto;margin:0}
.remember-me{margin-right:6px}

/* ============================================================
   LONG-TAIL BRIDGE
   Neutralizes leftover Bootstrap grid + inline bgcolor from
   legacy templates and provides centered wrappers + readable
   prose so auth/account/mail/search/profile pages sit on-system.
   ============================================================ */

/* Neutralize Bootstrap grid leftovers (no framework loaded now) */
.row{display:block}
[class^="col-"],[class*=" col-"]{width:auto;float:none;padding:0;margin:0}
.col-sm-offset-4,.col-md-offset-1,.col-md-offset-2,.col-md-offset-3,.col-lg-offset-3{margin-left:0}

/* Neutralize legacy inline bgcolor attributes so cells inherit the clean look */
.wrapcontent [bgcolor],.page [bgcolor]{background-color:transparent !important}

/* Centered wrapper for auth + account + search pages */
.auth-wrap,#register,.forum-search,#forum-logincontainer,#register-form,
.accountPage,#mail-headline{max-width:560px;margin:22px auto}
.forum-search{max-width:620px}
.accountPage{max-width:760px}

.headline{text-align:center;margin:8px 0 6px}
.headline h3,.headline .title{margin:0}

/* Login box */
.login-box{max-width:420px;margin:24px auto}
/* A message crossing a redirect is not necessarily a failure — a completed
   registration lands here too — so the tone is carried by the message rather
   than assumed from the element. */
.login-note,.login-error{
  border-radius:var(--r-input);
  font-family:var(--font-sans);font-size:13.5px;line-height:1.5;
  padding:10px 14px;
  margin-bottom:16px;
  text-align:center;
}
.login-note.is-error,.login-error{
  background:var(--danger-tint);
  border:1px solid color-mix(in srgb, var(--danger) 25%, transparent);
  color:var(--danger);
}
.login-note.is-success{
  background:var(--success-tint);
  border:1px solid color-mix(in srgb, var(--success) 25%, transparent);
  color:var(--nd-green-ink, var(--success));
}
.login-box h3{font-family:var(--font-serif);font-weight:600;font-size:1.5rem;color:var(--nd-navy);margin:0 0 14px;text-align:center}
.login-box .form-group{margin:0 0 12px}
.login-box .checkbox{font-family:var(--font-sans);font-size:13px;color:var(--ink-2);margin:6px 0 14px}
.login-box .btn{width:100%;justify-content:center}

/* Account settings menu links */
.account-options{background:var(--nd-navy)!important;color:#fff!important}
.account-options *{color:#fff!important}

/* Search page */
.forum-search h3{font-family:var(--font-serif);font-weight:600;font-size:1.2rem;color:var(--nd-navy);margin:18px 0 6px}
.search-text{font-family:var(--font-sans);font-size:13.5px;color:var(--ink-2);margin:8px 0}

/* Mail folder nav + message list (bridged from retired forums.css) */
.mail-nav-container{max-width:560px;margin:0 auto;overflow:hidden}
#mail-headline h3{margin-top:12px}
.mail-messages{padding:.5em 0;position:relative}
.mail-message{text-align:left;padding:.6em 12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-height:64px;cursor:pointer}
.mail-message-checkbox{padding:6px 10px 0 0;float:left}
.mail-message-linked{overflow:hidden}
.mail-subject{float:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Header row: the mono label is short, so without its own padding the
   select-all box sits flush against the panel border. */
.mail-message-header{display:flex;align-items:center;padding:8px 12px}
.mail-message-header .mail-message-checkbox{float:none;padding:0 10px 0 0}
.mail-message-header .mail-message-linked{flex:1;min-width:0}
/* One action per row: submit and its select share a baseline. The shared
   input rule gives selects a bottom margin, which is what knocked them
   out of line with the buttons. */
.mail-actions{display:flex;align-items:center;gap:10px;margin:0 0 10px}
.mail-actions select{margin:0;width:auto;min-width:150px}
.mail-actions .btn{min-width:118px;justify-content:center}

/* Long-form prose (rules, help text) */
.prose{max-width:760px;margin:18px auto;font-family:var(--font-serif);font-size:16px;line-height:1.7;color:var(--text)}
.prose h3{font-family:var(--font-serif);font-weight:600;color:var(--nd-navy);font-size:1.25rem;margin:22px 0 8px}
.prose ol,.prose ul{padding-left:1.3em}
.prose ol li,.prose ul li{margin:0 0 10px}
.prose strong{color:var(--nd-navy)}

/* ══ ADMIN (sysop) ═══════════════════════════════════════
   The sysop templates are original bSpeak markup: wide tables built from
   <td> soup, sized with width="1%" and held open with nowrap, plus Bootstrap
   classes that stopped resolving when the redesign dropped Bootstrap.
   Rather than rewrite that markup, the legacy attributes are neutralised
   here and the tables restack as cards on a phone. ── */

/* Page shell. The admin pages are dense and utilitarian — full width, not
   the 560px reading measure the public auth pages use. */
.sysop-page{max-width:var(--page-max);margin:0 auto}
.sysop-page .headline{text-align:left;margin:18px 0 4px}
.sysop-title{
  font-family:var(--font-title);font-size:var(--type-section-title-size);
  color:var(--nd-navy);margin:0 0 2px;
}
.sysop-intro{font-size:13px;color:var(--ink-3);margin:0 0 14px;max-width:70ch}

/* Any wide table can scroll inside its own box above the stack breakpoint,
   so the page body itself never scrolls sideways. */
.table-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:10px 0 22px}
.table-wrap > .table{margin:0}

/* A full-width banner row inside a legacy table (the "Record of Suspensions"
   bars) — a <td colspan> acting as a caption. */
.table-banner td,td.table-banner{
  background:var(--bg-sunk) !important;
  font-family:var(--font-mono);font-size:10px;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3);
  padding:10px 14px;
}

/* Legacy sizing attributes fight every responsive rule below. */
.table-stack td[width],.table-stack th[width]{width:auto}

@media (max-width:760px){
  /* ── Wide tables become one card per row ── */
  .table-stack,.table-stack tbody,.table-stack tr,.table-stack td{
    display:block;width:auto;
  }
  .table-stack{border:0;background:none;overflow:visible}
  .table-stack thead,.table-stack .table-head{display:none}

  .table-stack tr{
    background:var(--card-raised);
    border:1px solid var(--line);border-radius:var(--r-card);
    margin:0 0 12px;overflow:hidden;
  }
  .table-stack tr:hover{background:var(--card-raised)}

  /* Unlabelled cells (the 2-column "label above input" edit forms) simply
     stack; labelled ones become a label/value pair. */
  .table-stack td{
    display:block;
    padding:8px 14px;border-bottom:1px solid var(--line-soft);
    white-space:normal;text-align:left;
  }
  .table-stack td[data-label]{display:flex;align-items:baseline;gap:12px}
  .table-stack tr td:last-child{border-bottom:0}

  /* Form controls in a stacked edit form get the full card width. */
  .table-stack input[type=text],.table-stack input[type=password],
  .table-stack input[type=email],.table-stack input[type=date],
  .table-stack select,.table-stack textarea{width:100%;max-width:none}
  .table-stack input[type=checkbox],.table-stack input[type=radio]{width:auto}

  /* The column header, reinstated per cell. */
  .table-stack td[data-label]::before{
    content:attr(data-label);
    flex:0 0 40%;min-width:0;
    font-family:var(--font-mono);font-size:10px;font-weight:700;
    letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3);
  }

  /* A cell whose value is several blocks wraps them in .cell-value, so the
     whole value is one flex item and stacks under its label rather than each
     block becoming a sibling item laid out across the row. */
  .table-stack td[data-label] > .cell-value{flex:1 1 auto;min-width:0}

  /* Cells that carry their own meaning (action links, banners) take the
     full width instead of a label/value split. */
  .table-stack td.cell-actions{
    display:flex;flex-wrap:wrap;gap:8px;
    background:var(--bg-sunk);padding:10px 14px;
  }
  .table-stack td.cell-actions::before{content:none}
  .table-stack td.cell-full::before{content:none}
  .table-stack .table-banner td,.table-stack td.table-banner{
    display:block;background:var(--bg-sunk) !important;
  }
  .table-stack .table-banner td::before{content:none}

  /* An empty value would collapse to just a label, which reads as a bug. */
  .table-stack td:empty{display:none}

  /* Legacy attributes, overridden rather than removed from 21 templates. */
  .table-stack td[nowrap],.table-stack th[nowrap]{white-space:normal}
  .table-stack td[align],.table-stack th[align]{text-align:left}

  .table-wrap{overflow-x:visible}

  /* ── Filter / edit forms stack instead of sitting in a table row ── */
  .sysop-filters{display:flex;flex-wrap:wrap;gap:10px}
  .sysop-filters > *{flex:1 1 100%}
  .sysop-page .form-control{width:100%;max-width:none}
}

/* ── Filter bar (audit log) ── */
.sysop-filters{
  display:flex;flex-wrap:wrap;align-items:flex-end;gap:10px 14px;
  background:var(--card-raised);border:1px solid var(--line);
  border-radius:var(--r-card);padding:14px 16px;margin:0 0 16px;
}
.sysop-filters .field{display:flex;flex-direction:column;gap:4px;min-width:0}
.sysop-filters .field > label{
  font-family:var(--font-mono);font-size:10px;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3);
}
.sysop-filters .field-actions{
  display:flex;gap:8px;align-items:flex-end;margin-left:auto;
}

/* ── Confirmation pages ── */
.confirm-card{
  max-width:520px;margin:28px auto;
  background:var(--card-raised);border:1px solid var(--line);
  border-radius:var(--r-card);box-shadow:var(--shadow-card);
  padding:24px 26px;
}
.confirm-card h1{
  font-family:var(--font-title);font-size:1.25rem;
  color:var(--nd-navy);margin:0 0 10px;
}
.confirm-card p{margin:0 0 12px;font-size:14px;color:var(--ink-2);line-height:1.55}
.confirm-card .subject{font-weight:700;color:var(--danger)}
.confirm-card .note{
  font-size:13px;color:var(--ink-3);
  background:var(--bg-sunk);border-radius:var(--r-input);
  padding:10px 12px;margin:0 0 14px;
}
.confirm-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:16px}
.confirm-actions .btn{flex:0 1 auto}
.btn-danger{background:var(--danger);border-color:var(--danger);color:#fff}
.btn-danger:hover{filter:brightness(.94);color:#fff}
.btn-quiet{background:transparent;border:1px solid var(--line-strong);color:var(--ink-2)}
.btn-quiet:hover{background:var(--bg-sunk);color:var(--ink)}

/* Status output from the action pages (plain sentences echoed in a loop). */
.sysop-status{
  background:var(--card-raised);border:1px solid var(--line);
  border-left:3px solid var(--nd-green);border-radius:var(--r-input);
  padding:14px 16px;margin:16px 0;font-size:14px;line-height:1.6;color:var(--ink-2);
}
.sysop-status.is-error{border-left-color:var(--danger)}

/* "Select / unselect all" sits beside the submit button on the queue pages. */
.check-all{
  display:inline-flex;align-items:center;gap:8px;
  font-size:13px;color:var(--ink-2);cursor:pointer;
}
.check-all input{margin:0}

/* ══ REGISTRATION ════════════════════════════════════════
   Honeypot field. Off-screen rather than display:none or visibility:hidden —
   the cheap scrapers explicitly skip those two, so hiding that way trains the
   trap to catch nobody. Kept focusable-but-unreachable (tabindex="-1" on the
   input) so a keyboard user never lands in it either. ── */
.nectar{
  position:absolute;
  width:1px;height:1px;
  margin:-1px;padding:0;border:0;
  overflow:hidden;
  clip:rect(0 0 0 0);
  clip-path:inset(50%);
  white-space:nowrap;
}

/* The Turnstile widget ships its own iframe sizing; this just gives it the
   same rhythm as the fields around it. */
.cf-turnstile,.h-captcha{margin:2px 0 6px}
