/* ============================================================
   LawnBeast V2 — ARTICLE SYSTEM, concept-guide component layer
   ------------------------------------------------------------
   The kit a CONCEPT page needs and a task guide, a news post and
   a feature page do not: the relationship graph, the thesis, the
   versus matrix, the stage chain, the disclosures, and the
   interactive decision engine.

   Loaded ONLY by the guide shell (tools/guide_article.html), and
   that is the whole point of the file existing. These sections
   lived in css/v2/article/base.css, which is render-blocking on
   all three article surfaces — they were ~30% of it, and exactly
   one page uses them (guides/jobs-vs-invoices.html, plus the
   guides/_STARTER.html skeleton). Every news post and every
   feature page was paying to download and parse a decision engine
   it can never show.

   Must load AFTER base.css: it reads the --art-* tokens defined
   there, and one pair of rules ties on specificity and settles on
   source order (.art-vs-cell code vs .art-body code, both 0,1,1).
   MOBILE-FIRST, same as the rest of the article layer.
   ============================================================ */

/* ---------- Relationship graph (flowchart) ---------- */
/* A real flowchart — nodes, labelled edges, a decision diamond, a loop-back —
   for a chain of records handing off to records.

   This replaced .art-flow, a flex strip of bordered divs that charted the same
   thing in DOM. A strip could only run in a line; it had no vocabulary for a
   fork, a bus, or an arrow that comes back up into a node it already passed,
   and it could not lay a node out freely — jobs-vs-invoices path 2 needed both
   a three-into-one merge and an itemised bill with the amounts right-aligned
   in their own column. Once one of the three paths there had to be SVG, all
   three did: two node vocabularies under sibling headings made the reader
   learn the picture twice. .art-flow had no other callers and is gone; see
   git history at the commit that removed it if you need the old strip back.

   The fragment ships GEOMETRY ONLY — every fill, stroke and type size is a
   class styled here, no presentation attributes — so the diagram moves with
   the tokens like every other block. Author a new one at the natural 720
   viewBox width, where these sizes are literal px; on a guide it renders at
   ~1.38x (the 992px body column at the xxl tier). */
/* Framed as a specimen, on the same chrome as an inline <code>: surface-alt
   fill, border-light hairline, mono-ish restraint. A diagram is a rendered
   artefact the prose refers to, not prose itself, and unframed it floated on
   the page with its own white nodes invisible against the page's white. The
   tint is what makes .art-g-box (--surface) read as a card at all.

   display:flex is not layout — a lone SVG needs none. It is the fix for the
   end padding being dropped inside an overflow-x container: block scroll
   containers lose padding-right once the content overflows, flex ones keep it. */
.art-graph {
    max-width: var(--art-wide);
    margin: 0 0 22px;
    display: flex;
    align-items: flex-start;
    /* Tight on the phone: every px of frame is a px the diagram does not get,
       and the portrait variant is already the narrowest it can be and stay
       legible. Desktop can afford the breathing room. */
    padding: 14px;
    border: 1px solid var(--border-light);
    border-radius: 6px;            /* the nodes' own corner, one step up */
    background: var(--surface-alt);
    overflow-x: auto;              /* phone: the diagram scrolls, it does not shrink */
    -webkit-overflow-scrolling: touch;
}
.art-graph svg {
    display: block;
    flex: none;
    width: 100%;
    min-width: 640px;              /* narrower than this and the labels stop being legible */
    height: auto;
    font-family: var(--art-font-sans);
}

/* ---- Landscape / portrait pair ----
   An SVG cannot reflow: its geometry is absolute, so a chain that runs
   left-to-right on a desktop cannot become top-to-bottom on a phone by any
   amount of CSS. The only honest answers are "scroll it sideways" or "author
   it twice", and sideways-scrolling a diagram hides half the argument behind
   a gesture nobody makes.

   So a graph MAY ship two <svg> children — .art-g--wide and .art-g--stack —
   and exactly one is in the box at any width. The hidden one is display:none,
   so it is out of the accessibility tree too and the two <title>/<desc> pairs
   never both announce. They must carry DIFFERENT ids, including the arrowhead
   <marker>: duplicate ids resolve to the first match in the document, and a
   url(#id) pointing into a display:none subtree drops the marker.

   The cost is real and worth stating: the content exists twice. Change a
   figure, a label or a status name in one and you must change the other.

   Breakpoint is 768px, where the body column (~736px less the frame's 44px
   of padding) first clears the 640px floor above.
   A graph with a single <svg> and no modifier class is unaffected by all of
   this and behaves as before. */
.art-graph .art-g--wide { display: none; }
.art-graph .art-g--stack {
    min-width: 0;
    max-width: 360px;   /* the portrait viewBox is authored at 320; past ~1.1x
                           its 11px labels start rendering as headline type */
    margin: 0 auto;
}
@media (min-width: 768px) {
    .art-graph { padding: 20px 22px; }
    .art-graph .art-g--wide { display: block; }
    .art-graph .art-g--stack { display: none; }
}

/* node families — plain, invoice, done, part. A record of a given kind takes
   the same fill everywhere it appears, across every graph on a page. */
.art-g-box          { fill: var(--surface);       stroke: var(--border);          stroke-width: 1; }
.art-g-box--invoice { fill: var(--accent-subtle); stroke: var(--accent-border); }
.art-g-box--done    { fill: var(--accent-bg);     stroke: var(--accent-border); }
.art-g-box--part    { fill: var(--art-warn-bg);   stroke: var(--art-warn-line); }
.art-g-diamond      { fill: var(--surface-alt);   stroke: var(--border);          stroke-width: 1; }
.art-g-rule         { stroke: var(--border);      stroke-width: 1; }

/* edges — --border is a hairline for panels and reads as a smudge at diagram
   scale, so the lines take the muted ink instead */
.art-g-edge { fill: none; stroke: var(--text-muted); stroke-width: 1.4; }
.art-g-head { fill: var(--text-muted); }

/* text. Kind labels are typed uppercase in the markup rather than transformed:
   text-transform on SVG <text> is not reliable across browsers. */
.art-g-kind          { fill: var(--text-muted); font-size: 9.5px; font-weight: 700; letter-spacing: .06em; }
.art-g-kind--invoice { fill: var(--accent-dark); }
.art-g-t             { fill: var(--text); font-size: 13px; font-weight: 600; }
.art-g-t--done       { fill: var(--positive); }
.art-g-sub           { fill: var(--text-secondary); font-size: 11px; }
.art-g-amt           { fill: var(--text); font-family: var(--art-font-mono); font-size: 12px; font-variant-numeric: tabular-nums; }
.art-g-amt--total    { font-weight: 700; }
/* Record id — mono and tabular so a column of them lines up digit for digit,
   which is the whole reason to print an id in a diagram: the reader traces the
   same #001 from one node to another. Muted, because it identifies the row, it
   is not the content of it. */
.art-g-id            { fill: var(--text-muted); font-family: var(--art-font-mono); font-size: 11px; font-variant-numeric: tabular-nums; }
.art-g-elabel        { fill: var(--text-muted); font-size: 10.5px; }
.art-g-branch        { fill: var(--text); font-size: 11px; font-weight: 700; }

/* ============================================================
   3b. Concept blocks
   ------------------------------------------------------------
   From the "Concept Explainer" layout. A concept page's job is to
   separate two things the reader is conflating, so it needs a
   different kit from a task guide: state the distinction, tabulate
   it, chart the lifecycle, then clear up the confusions.
   ============================================================ */

/* ---------- Thesis ----------
   The one-sentence distinction, stated before anything else. Not
   .art-callout--key: a callout is a mid-page aside at body size, and
   this is lede-weight — it is the page's argument, sitting between
   the headline and the first section. */
.art-thesis {
    display: flex;
    gap: 14px;
    margin: 0 0 28px;
    padding: 16px 18px;
    max-width: var(--art-measure);
    border: 1px solid var(--accent);
    border-radius: 12px;
    background: var(--accent-bg);
}
.art-thesis > i {
    flex: none;
    color: var(--accent-dark);
    font-size: 19px;
    line-height: 1;
    margin-top: 3px;
}
.art-body .art-thesis p {
    margin: 0;
    font-size: 15px;
    line-height: 1.6;
    color: var(--text);
}
.art-body .art-thesis p + p { margin-top: 8px; }

/* ---------- Versus matrix ----------
   Two entities down the columns, one aspect per row, with a label
   gutter on the left. .art-table can't do this: its first column is
   a real <th> scope="row" carrying data, and a two-entity comparison
   wants the entity names as icon-led column heads instead.

   Desktop is one flat grid (rows are display:contents, so their own
   boxes and the mobile row rule vanish). Mobile keeps each row as a
   stacked card and prints the column name from data-vs, because a
   132px gutter beside two columns of prose is unreadable on a phone. */
.art-vs {
    margin: 0 0 26px;
    max-width: var(--art-wide);
    border: 1px solid var(--border);
    border-radius: 10px;
    overflow: hidden;
    background: var(--surface);
}
.art-vs-heads,
.art-vs-gutter { display: none; }
.art-vs-row + .art-vs-row { border-top: 1px solid var(--border); }
.art-vs-label {
    padding: 9px 14px;
    background: var(--surface-alt);
    border-bottom: 1px solid var(--border-light);
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.art-vs-cell {
    padding: 10px 14px;
    font-size: 13px;
    line-height: 1.6;
    color: var(--text-secondary);
}
.art-vs-cell + .art-vs-cell { border-top: 1px solid var(--border-light); }
.art-vs-cell[data-vs]::before {
    content: attr(data-vs);
    display: block;
    margin-bottom: 3px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--accent-dark);
}
.art-vs-cell code { font-size: 12px; }

/* ---------- Stage chain ----------
   A lifecycle: evenly weighted phases joined by chevrons. Distinct
   from .art-graph, which charts records moving between each other and
   carries amounts and merges — this one is a single object changing
   state over time, so every link is the same size and the chevrons
   are muted rather than accent. */
.art-stages {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
    margin: 0 0 14px;
    max-width: var(--art-wide);
}
.art-stage {
    flex: 1 1 0;
    min-width: 0;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--surface);
    padding: 10px 12px;
}
.art-stage-name {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 3px;
}
.art-stage-sub {
    font-size: 11px;
    line-height: 1.5;
    color: var(--text-muted);
}
/* work states green, money states blue — the same split the rest of
   the page uses, so a reader can tell the two lifecycles apart at a
   glance without reading the labels */
.art-stage--work  { border-color: var(--accent); background: var(--accent-bg); }
.art-stage--money { border-color: var(--art-info-deep); background: var(--art-info-bg); }
/* a branch off the happy path (void, written off, cancelled) */
.art-stage--off {
    border-style: dashed;
    background: transparent;
}
.art-stage--off .art-stage-name { color: var(--text-muted); }

.art-stages-arrow {
    flex: none;
    align-self: center;
    color: var(--text-muted);
    font-size: 14px;
    line-height: 1;
}
.art-stages-arrow i { transform: rotate(90deg); }   /* stacked on mobile */

/* the fragment writes this as a <p>; .art-body p would otherwise win.
   It's the caption for .art-stages, which is --art-wide — capping the label
   at the measure while its own block runs wider than that is just wrong. */
.art-body p.art-stages-label,
.art-stages-label {
    margin: 0 0 6px;
    max-width: var(--art-wide);
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--text-muted);
}

/* ============================================================
   3c. Disclosure — collapsed by default
   ------------------------------------------------------------
   Native <details>/<summary>. No JS behind the toggle; the only
   script involved is article-concept.js re-opening a collapsed ancestor
   when a deep link lands inside one.

   Why this exists: a long reference run — jobs-vs-invoices ships
   seven use cases and eight mixups — is a lookup list, scanned
   for ONE entry, not read top to bottom. Every other block here
   renders all of its content at once, which is right for prose
   and wrong for a list where 90% of what is on screen is not the
   entry you came for. Nothing existing does it: .art-faq is a
   flat always-open list, .art-cards a grid of peers, .art-vs and
   .art-stages diagrams that only mean anything whole.

   Collapse at ITEM level, never at section level. The <h2> and
   its intro <p> must stay OUTSIDE the <details>, because
   js/v2/article.js builds the rail TOC from section[id] + <h2>
   pairs — an <h2> swallowed by a collapsed <details> is still
   found by querySelectorAll, but hiding a section's heading
   behind a toggle is not what the rail is describing.

   Two shapes, one reset:
     .art-disclose        heading-led, wraps the body of a nested
                          <section> whose <h3> becomes the title
     .art-cards--collapse modifier that turns an existing Q/A card
                          into a disclosure
   ============================================================ */

/* ---------- Shared summary reset ----------
   list-style:none kills the standards marker (Chrome, Firefox);
   ::-webkit-details-marker the legacy triangle Safari still draws.
   Both are needed — neither alone clears every engine. */
.art-disclose > summary,
.art-cards--collapse .art-card > summary {
    cursor: pointer;
    list-style: none;
}
.art-disclose > summary::-webkit-details-marker,
.art-cards--collapse .art-card > summary::-webkit-details-marker { display: none; }

/* Keyboard focus. Inset, not outset: the Q/A summary is flush inside
   a card with overflow:hidden, which would clip an outset ring. */
.art-disclose > summary:focus-visible,
.art-cards--collapse .art-card > summary:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}

/* The chevron. Same font + escape precedent as .art-checklist's tick,
   so no extra <i> has to be authored into every summary. margin-left
   pushes it to the end of the row while the WHOLE row stays the click
   target — a real <button> beside the title would give the reader two
   things to aim at, one of which does nothing. */
.art-disclose > summary::after,
.art-cards--collapse .art-card > summary::after {
    content: "\F282";                  /* bi-chevron-down */
    font-family: 'bootstrap-icons';
    flex: none;
    margin-left: auto;
    padding-left: 12px;
    font-size: 12px;
    line-height: 1.5;
    color: var(--text-muted);
    transition: transform .18s ease;
}
.art-disclose[open] > summary::after,
.art-cards--collapse .art-card[open] > summary::after { transform: rotate(180deg); }

.art-disclose > summary:hover::after,
.art-cards--collapse .art-card > summary:hover::after { color: var(--accent-dark); }

/* ---------- Heading-led disclosure ----------
   The nested <section id> stays put and keeps its <h3>; only the body
   moves inside.

   Collapsed, this is deliberately the SAME OBJECT as a "common mixups" card
   in .art-cards--collapse: a bordered card whose entire visible body is a
   tinted title bar with an icon at the left and a chevron at the right. Same
   border, radius, tint, hairline, 15px gutter, 9px icon gap. Two collapsible
   lists on one page that look like unrelated widgets make the reader learn
   the control twice; the only differences left are content-driven (a heading
   plus a verdict line here, a single question there).

   Side padding lives on the <details> so the body copy is inset with the bar,
   and the summary pulls back out to the card edges with -15px margins — the
   alternative is padding every child block individually. */
.art-disclose {
    border: 1px solid var(--border);
    border-radius: 10px;
    overflow: hidden;
    background: var(--surface);
    padding: 0 15px;
    margin-bottom: 12px;              /* matches the .art-cards grid gap */
}
.art-disclose > summary {
    display: flex;
    align-items: baseline;
    gap: 9px;
    margin: 0 -15px;
    padding: 11px 15px;
    background: var(--surface-alt);
}
/* Accent, not the mixups' warn-deep: a use case is a route to follow, not a
   misconception to correct. */
.art-disclose > summary > i {
    flex: none;
    color: var(--accent);
    font-size: 15px;
}
.art-disclose > summary:hover > i { color: var(--accent-dark); }
/* .art-body h3 owns a 22px top margin, which inside a flex summary row
   pushes the title off the chevron's baseline. Descendant, not child: the
   heading may be wrapped in .art-disclose-title (below). */
/* Sized down from the 17px .art-body h3 to sit in the same weight class as a
   mixups question (13px) while still out-ranking its own 12.5px verdict line.
   It is still an <h3> in the outline — this is a bar label, not a heading in
   a column of prose. */
.art-body .art-disclose > summary h3 {
    margin: 0;
    min-width: 0;
    font-size: 14.5px;
    line-height: 1.4;
}
.art-disclose > summary:hover h3 { color: var(--accent-dark); }

/* Optional second line in the summary — the item's verdict, hoisted out of
   the body. A collapsed run of these is a contents list, and a contents list
   of bare titles is only useful if the titles are self-explanatory; where the
   section tells the reader to skim for a match (use cases), the one-line
   verdict has to survive the collapse or the promise is empty. The wrapper
   takes the baseline the chevron aligns to, which is the h3's first line. */
.art-disclose-title { min-width: 0; }
.art-disclose-sub {
    margin-top: 3px;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--text-muted);
}
/* Open: the bar keeps a hairline under it so the title still reads as the
   item's head, exactly as .art-cards--qa does. Closed, that hairline would
   double up against the card border one pixel below, so it is only drawn
   when open — the mirror of the .art-cards--collapse rule below. */
.art-disclose[open] > summary {
    margin-bottom: 14px;
    border-bottom: 1px solid var(--border-light);
}
.art-disclose[open] { padding-bottom: 16px; }

/* ---------- Q/A card as a disclosure ----------
   OPT-IN, deliberately not folded into .art-cards--qa: the same block
   is the troubleshooting list in guides/_STARTER.html, news/_STARTER.html
   and every task guide, where two or three answers should simply be
   readable. Only a long scan-for-one list earns a toggle.

   The card becomes the <details> and the title bar the <summary>, so
   .art-cards--qa's tinted bar, hairline and warn-deep icon all still
   apply unchanged — this is the same card with its answer hidden, not a
   second Q/A treatment. The .art-card-text indent (39px, clearing the
   icon) survives for the same reason. */
.art-cards--collapse .art-card:not([open]) > summary {
    /* closed, the bar IS the card: its hairline would double up against
       the card's own border one pixel below it */
    border-bottom: 0;
}
.art-cards--collapse .art-card > summary:hover > i { color: var(--art-warn); }

/* ============================================================
   3d. Decision engine
   ------------------------------------------------------------
   Restores the interactive "Which setup do I need?" flow that
   shipped on the bespoke jobs-vs-invoices page (pre-86044f9) as a
   first-class .art-decide component, driven by js/v2/article-concept.js
   block 4: two questions, five outcomes; Q2 branches on the Q1
   answer, and the "non-service charge" Q1 branch skips Q2 and
   jumps straight to its result.

   Progressive enhancement: the whole engine ships display:none and
   article-concept.js block 4 adds .is-live once it has wired the handlers.
   Without JS the reader never sees it — which is the point. Q1's
   options are <button>s; showing three buttons that swallow a click
   and do nothing is worse than showing nothing, and the answers
   table plus the five #setup-* sections directly below already
   cover every outcome without a click. Inside a live engine, Q2 and
   the result cards stay display:none until .is-open.
   ============================================================ */
.art-decide { display: none; }
.art-decide.is-live {
    display: block;
    margin: 4px 0 26px;
    padding: 20px 16px 22px;
    max-width: var(--art-wide);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface-alt);
}

/* ---------- Progress rail (decorative — the step content already
   says where you are, so this is aria-hidden in the fragment) ---------- */
.art-decide-progress {
    display: flex;
    align-items: center;
    max-width: 260px;
    margin: 0 auto 20px;
}
.art-decide-pn {
    flex: none;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 2px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--art-font-mono);
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted);
    background: var(--surface);
    transition: border-color .25s ease, background-color .25s ease, color .25s ease, box-shadow .25s ease;
}
.art-decide-pn.is-active {
    border-color: var(--accent);
    color: var(--accent-dark);
    box-shadow: 0 0 0 3px var(--accent-bg);
}
.art-decide-pn.is-done {
    border-color: var(--accent);
    background: var(--accent);
    color: #fff;
}
.art-decide-pn.is-skipped {
    border-color: var(--border);
    background: var(--surface-alt);
    color: var(--text-muted);
}
.art-decide-pl {
    flex: 1;
    height: 2px;
    margin: 0 4px;
    background: var(--border);
    position: relative;
    overflow: hidden;
}
.art-decide-pl-fill {
    position: absolute;
    inset: 0 auto 0 0;
    width: 0;
    background: var(--accent);
    transition: width .35s ease;
}
.art-decide-pl.is-filled .art-decide-pl-fill { width: 100%; }

/* The result node is the outcome, and the original coloured it by outcome:
   green for "card on file", amber for the four that end in an invoice. It is
   the only signal that survives being scrolled past, so it is worth keeping. */
.art-decide-pn--result i { display: block; font-size: 11px; }
.art-decide-pn--result.is-active {
    border-color: transparent;
    background: var(--accent);
    color: #fff;
    box-shadow: 0 0 0 4px var(--accent-bg);
}
.art-decide-pn--result.is-active.is-amber {
    background: var(--art-warn-deep);
    box-shadow: 0 0 0 4px var(--art-warn-bg);
}
.art-decide-pn--result.is-active.is-info {
    background: var(--art-info);
    box-shadow: 0 0 0 4px var(--art-info-bg);
}

/* ---------- Flow column: "Start here" + connectors ----------
   The original drew the engine as a literal flowchart — a start marker, then a
   2px rule between each step that GREW into place as the next step unlocked.
   That growth is the whole reason it reads as a flow rather than a stack of
   cards, so it is animated height, not a static divider. Decorative: the
   fragment marks every connector aria-hidden. */
.art-decide-start {
    display: block;
    width: max-content;
    margin: 0 auto;
    padding: 4px 12px;
    font-family: var(--art-font-mono);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--accent-dark);
    background: var(--accent-bg);
    border: 1px solid var(--accent-border);
    border-radius: 999px;
}
.art-decide-conn {
    width: 2px;
    height: 0;
    margin: 0 auto;
    overflow: hidden;
    background: linear-gradient(180deg, var(--border), var(--border-light));
    transition: height .4s ease;
}
.art-decide-conn.is-open { height: 34px; }

/* ---------- Question step ----------
   Closed by default (display:none) — that alone keeps every .art-decide-opt
   button out of the tab order while its step is hidden, no extra attribute
   needed. Q1 ships with .is-open already in the markup. */
.art-decide-step {
    display: none;
    flex-direction: column;
    max-width: var(--art-wide);
    margin: 0 auto;
}
.art-decide-step.is-open {
    display: flex;
    animation: art-decide-in .45s ease both;
}
.art-decide-step + .art-decide-step,
.art-decide-step + .art-decide-results { margin-top: 0; }
/* An answered question stays on screen (you can change your mind) but stops
   competing with the one you are being asked now. */
.art-decide-step.is-answered .art-decide-qtext { color: var(--text-muted); }

.art-decide-qhead {
    margin-bottom: 12px;
}
.art-decide-qnum {
    display: block;
    font-family: var(--art-font-mono);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--accent-dark);
    margin-bottom: 4px;
}
/* The cue. Three cards with a hairline radio dot read as a diagram of the
   choice rather than the choice itself — people scroll past them to the
   answers table. This says out loud that the thing is operable.

   Form help text: it sits under the group of options it applies to, the way a
   hint sits under a fieldset, and it is styled like one — small, muted, quiet.
   Deliberately not loud. The job is to remove the doubt about whether the
   cards do anything, not to shout; anything with more weight competes with the
   question above it and with the cards themselves.

   It is a sibling of .art-decide-opts inside the column-flex step, so it lands
   on its own row under the cards with no wrapper. */
.art-decide-cue {
    align-self: start;
    margin-top: 10px;
    font-size: 12.5px;
    line-height: 1.4;
    color: var(--text-muted);
}
/* Once a question is answered the instruction is noise — the answer itself is
   the state now. Reset puts it back by removing .is-answered. */
.art-decide-step.is-answered .art-decide-cue { display: none; }

/* .art-body p (0,1,1) would otherwise out-specify the bare class (0,1,0) —
   same trap as .art-body p.art-note. */
.art-body p.art-decide-qtext {
    margin: 0;
    max-width: var(--art-wide);
    font-size: 16px;
    font-weight: 600;
    line-height: 1.35;
    color: var(--text);
}

.art-decide-opts {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.art-decide-opt {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 12px;
    width: 100%;
    padding: 12px 38px 12px 14px;   /* right pad clears the radio dot */
    text-align: left;
    font-family: inherit;
    color: var(--text-secondary);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: border-color .15s ease, box-shadow .15s ease, opacity .15s ease;
}
/* The radio dot. Without it the options read as links — nothing says "these
   are mutually exclusive and one of them is your current answer" until you
   have already clicked. The original had it; it is doing real work. */
.art-decide-opt::after {
    content: "";
    position: absolute;
    right: 13px;
    top: 14px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    border: 2px solid var(--border);
    transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease;
}
/* The tick is an inline SVG data URI, not a bootstrap-icons glyph: the icon
   font is loaded from a CDN with a deferred onload, so a font-glyph tick can
   flash as tofu (or as nothing) on the first click of a cold page. The dot is
   the confirmation that the click registered — it must not depend on a
   third-party stylesheet having arrived. Same choice the original made. */
.art-decide-opt.is-selected::after {
    border-color: var(--accent);
    background: var(--accent)
        url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E")
        center / 9px no-repeat;
    box-shadow: 0 0 0 3px var(--accent-bg);
}
.art-decide-opt:hover { border-color: var(--accent-border); }
.art-decide-opt:hover::after { border-color: var(--accent-border); }
.art-decide-opt:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}
.art-decide-opt.is-selected {
    border-color: var(--accent);
    background: var(--accent-subtle);
    box-shadow: 0 0 0 1px var(--accent);
}
.art-decide-opt.is-selected .art-decide-opt-title { color: var(--accent-dark); }
.art-decide-opt.is-unselected { opacity: .5; }
.art-decide-opt.is-unselected:hover { opacity: .85; }

.art-decide-opt-icon {
    flex: none;
    width: 30px;
    height: 30px;
    border-radius: 8px;
    background: var(--accent-bg);
    display: flex;
    align-items: center;
    justify-content: center;
}
.art-decide-opt-icon i { color: var(--accent-dark); font-size: 14px; }
.art-decide-opt-body { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.art-decide-opt-title { font-size: 13.5px; font-weight: 600; color: var(--text); line-height: 1.4; }
.art-decide-opt-sub { font-size: 12px; line-height: 1.5; color: var(--text-muted); }

/* ---------- Result cards ----------
   Closed by default (display:none), which already excludes the "See it in
   action" / "Full setup steps" links from the tab order — inert +
   aria-hidden are added in the markup too, belt-and-suspenders, matching
   (and slightly exceeding) what the original bespoke page did. */
.art-decide-results { max-width: var(--art-wide); margin: 0 auto; }
.art-decide-result {
    position: relative;
    display: none;
    margin-top: 0;
    padding: 20px 18px;
    overflow: hidden;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: 0 6px 20px rgba(16, 24, 32, .07);
}
.art-decide-result.is-open {
    display: block;
    animation: art-decide-in .5s ease both;
}
/* Outcome tone. Three families, matching the original: green = the job
   collects its own money, amber = it ends on an invoice you send, blue = there
   is no job at all. The 4px cap is the fastest read of "which family am I in"
   and it survives at a glance from the far end of a long card. */
.art-decide-result::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 4px;
    background: var(--accent);
}
.art-decide-result--amber::before { background: var(--art-warn); }
.art-decide-result--info::before  { background: var(--art-info); }

.art-decide-result--amber .art-decide-result-badge {
    color: var(--art-warn-deep);
    background: var(--art-warn-bg);
    border-color: var(--art-warn-line);
}
.art-decide-result--info .art-decide-result-badge {
    color: var(--art-info-deep);
    background: var(--art-info-bg);
    border-color: var(--art-info-line);
}
.art-decide-result--amber .art-decide-result-features li::before { color: var(--art-warn-deep); }
.art-decide-result--info .art-decide-result-features li::before  { color: var(--art-info); }
.art-decide-result-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--art-font-mono);
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--accent-dark);
    background: var(--accent-bg);
    border: 1px solid var(--accent-border);
    padding: 3px 9px;
    border-radius: 999px;
    margin-bottom: 10px;
}
.art-decide-result-badge::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.art-decide-result-title {
    font-size: 18px;
    font-weight: 700;
    letter-spacing: -.01em;
    color: var(--text);
    margin-bottom: 8px;
}
/* compound selectors: .art-body p / .art-body ul are (0,1,1) and would
   otherwise out-specify these bare classes (0,1,0) — same trap the file
   already documents for .art-note / .art-checklist. */
.art-body p.art-decide-result-lead {
    margin: 0 0 10px;
    max-width: none;
    font-size: 14px;
    line-height: 1.65;
    color: var(--text-secondary);
}
.art-body ul.art-decide-result-features {
    list-style: none;
    padding: 0;
    margin: 4px 0 12px;
    max-width: var(--art-wide);
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.art-decide-result-features li {
    position: relative;
    padding-left: 22px;
    font-size: 13.5px;
    line-height: 1.55;
    color: var(--text-secondary);
}
.art-decide-result-features li::before {
    content: "\F26E";                  /* bi-check-circle-fill */
    font-family: 'bootstrap-icons';
    position: absolute;
    left: 0;
    top: 0;
    font-size: 13px;
    color: var(--accent);
}
.art-body p.art-decide-result-meta {
    margin: 0 0 8px;
    padding: 8px 10px;
    max-width: none;
    background: var(--surface-alt);
    border: 1px solid var(--border-light);
    border-radius: 7px;
    font-size: 12.5px;
    line-height: 1.55;
    color: var(--text-secondary);
}
.art-decide-result-meta-label { font-weight: 700; color: var(--text); margin-right: 4px; }
.art-decide-result-links {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 12px;
}
.art-decide-result-links a { font-size: 13px; font-weight: 600; }

/* ---------- Reset ---------- */
.art-decide-reset {
    display: none;
    align-items: center;
    gap: 6px;
    margin: 18px auto 0;
    padding: 8px 16px;
    font-family: var(--art-font-mono);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-secondary);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 999px;
    cursor: pointer;
}
.art-decide-reset.is-visible { display: inline-flex; }
.art-decide-reset:hover { border-color: var(--accent-border); color: var(--accent-dark); }
.art-decide-reset:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

@media (prefers-reduced-motion: no-preference) {
    @keyframes art-decide-in {
        from { opacity: 0; transform: translateY(8px); }
        to   { opacity: 1; transform: translateY(0); }
    }
}

/* ============================================================
   4. Desktop
   ============================================================ */
@media (min-width: 768px) {
    /* ---- Concept blocks ---- */
    .art-thesis { padding: 18px 20px; }
    .art-body .art-thesis p { font-size: 15.5px; }

    /* rows collapse into the parent grid, so .art-vs-row's own border
       (and box) disappear and the cells line up column-wise */
    .art-vs {
        display: grid;
        grid-template-columns: 132px minmax(0, 1fr) minmax(0, 1fr);
    }
    .art-vs-heads,
    .art-vs-row { display: contents; }
    .art-vs-gutter,
    .art-vs-h {
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 11px 14px;
        background: var(--surface-alt);
        border-bottom: 2px solid var(--border);
    }
    .art-vs-h {
        border-left: 1px solid var(--border-light);
        font-size: 14px;
        font-weight: 600;
        letter-spacing: -.01em;
        color: var(--text);
    }
    .art-vs-h > i { color: var(--accent-dark); font-size: 15px; }
    .art-vs-cell {
        border-left: 1px solid var(--border-light);
        border-bottom: 1px solid var(--border-light);
    }
    .art-vs-cell + .art-vs-cell { border-top: 0; }
    .art-vs-cell[data-vs]::before { display: none; }
    .art-vs-row:last-child > * { border-bottom: 0; }

    .art-stages { flex-direction: row; align-items: stretch; gap: 8px; }
    .art-stages-arrow i { transform: none; }

    /* ---- Decision engine ---- */
    .art-decide { padding: 28px 32px 30px; }
    .art-body p.art-decide-qtext { font-size: 18px; }
    .art-decide-opts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
    .art-decide-opts--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .art-decide-result-title { font-size: 20px; }
    .art-decide-result-links { flex-direction: row; gap: 22px; }
}

@media (prefers-reduced-motion: reduce) {
    /* the chevron flip is the only transition the article layer runs */
    .art-disclose > summary::after,
    .art-cards--collapse .art-card > summary::after { transition: none; }
    .art-decide-step.is-open,
    .art-decide-result.is-open { animation: none; }
}
