/* blocks.css
   Response content blocks — split from style.css
   Every .block-* rule rendered in the main column */

/* ─── RESPONSE BLOCKS ─── */

.response-main {
    --response-body-size: 17px;
    --response-body-leading: 1.68;
}

.block {
    margin-bottom: 24px;
    animation: fadeUp 0.35s ease forwards;
    opacity: 0;
}

@keyframes fadeUp {
    from {
        opacity: 0;
        transform: translateY(10px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* ─── INLINE EMPHASIS ───
   Injected by highlight()/fmt() in app.js. Two-tone, on brand: the same dull
   logo red as the caselet's stat highlights (--stat-red) for numbers/stats,
   teal-blue for Tiny Magiq vocabulary — one number color everywhere. */
.tm-stat {
    color: var(--stat-red);
    font-weight: 700;
}

/* Tiny Magiq vocabulary reads in the brand blue (the AI-First Leadership
   accent), bold. A cool blue stays legible on the purple→teal gradient and
   keeps the terms clearly distinct from the purple numbers (.tm-stat). */
.tm-term {
    color: var(--aifl);
    font-weight: 700;
}

/* IN AN EYEBROW, THE BLUE SHIFTS HUE AND NOTHING ELSE.
   The eyebrows are 12px uppercase with wide tracking, already at weight 700 —
   a term inside one inherits all of that, so the only thing left for .tm-term
   to change is the colour, which is the whole point. What it must NOT do is
   also brighten to the full body-prose blue: at 12px uppercase on the gradient,
   #60a5fa against the muted lavender around it reads as a broken span rather
   than an accent. Half a step up from the eyebrow, not a full one. */
.wit-headline .tm-term,
.wim-headline .tm-term,
.ns-headline .tm-term {
    color: #a5c8ff;
    font-weight: inherit;
}

/* A before → after movement ("15 days → under 3", "$25K → $5K/month"):
   the whole phrase reads as one green, bold unit — the proof of motion. */
.tm-move {
    color: var(--green-light);
    font-weight: 700;
}

.tm-bullet {
    color: rgba(167, 139, 250, 0.8);
    margin-right: 4px;
}

/* Headline */
.block-headline h2 {
    font-family: 'Inter', system-ui, sans-serif;
    font-size: clamp(22px, 3vw, 34px);
    font-weight: 700;
    letter-spacing: -0.03em;
    color: var(--white);
    line-height: 1.2;
}

/* The company reveal's framing line ("Most organisations we work with have the
   same discovery…"). Set by the server as emphasis:"soft" — it is context for
   the answer below it, never the answer itself, and at full headline weight it
   read as the answer to whatever had just been asked. Body-adjacent size, still
   a heading in the markup so the document outline is unchanged. */
.block-headline.is-soft h2 {
    font-size: clamp(17px, 1.6vw, 20px);
    font-weight: 600;
    letter-spacing: -0.01em;
    line-height: 1.45;
    color: var(--off-white);
}

/* Welcome mode — the one-line "who we are" under the greeting. */
/* Same body treatment as every other prose block. It was 15px/--muted, which
   is caption styling — and on the browsing turn this line IS the answer, the
   only substantive thing on screen. It read as a footnote to itself. */
.block-what-we-do p {
    font-size: var(--response-body-size);
    line-height: var(--response-body-leading);
    color: rgba(255, 255, 255, 0.82);
}

/* The answer to a pointed company question. Leads the turn, so it reads above
   the orientation prose that follows it — but it is an answer, not a heading. */
.block-facet-answer p {
    font-size: clamp(16px, 1.5vw, 18px);
    line-height: 1.6;
    font-weight: 500;
    color: var(--white);
}

/* Acknowledgement */
.block-acknowledgement {
    padding: 14px 20px;
    background: rgba(124, 58, 237, 0.1);
    border-left: 3px solid var(--iws);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.block-acknowledgement p {
    font-size: 14px;
    color: var(--iws);
    font-style: italic;
}

/* Direct answer */
.block-direct-answer p {
    font-size: var(--response-body-size);
    color: rgba(255, 255, 255, 0.82);
    line-height: var(--response-body-leading);
}

/* THE CATALOGUE'S OPENING LINE IS A CAPTION, NOT AN ANSWER. Every other
   direct_answer IS the answer, so 19px is right for it. This one only says how
   to read the shelf underneath it ("15 agents, grouped by …"), and at answer
   size it competed with the question above and crowded the tab strip — the
   thing the visitor is actually meant to choose from. Dropped to body size and
   a shade quieter so the five constraints stay the loudest thing on screen.

   Selected off the shelf that follows rather than a class of its own: the
   composer pushes these two blocks from ONE resolution (see composer.js,
   "The catalogue's list"), so their adjacency is the fact, not a flag. */
.block-direct-answer:has(+ .block-agent-catalogue) p {
    font-size: var(--response-body-size);
    line-height: var(--response-body-leading);
    letter-spacing: -0.005em;
    color: rgba(255, 255, 255, 0.7);
}

/* Differentiator */
.block-differentiator {
    padding: 18px 22px;
    background: rgba(13, 148, 136, 0.1);
    border-left: 3px solid var(--teal-light);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.block-differentiator p {
    font-size: var(--response-body-size);
    color: rgba(255, 255, 255, 0.8);
    line-height: var(--response-body-leading);
}

/* Construct cards */
.block-construct-cards .cards-label {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.35);
    margin-bottom: 14px;
}

.construct-cards-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 12px;
}

.construct-card {
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: var(--radius);
    padding: 20px;
    cursor: pointer;
    transition: background var(--transition), border-color var(--transition), transform var(--transition), box-shadow var(--transition);
    text-align: left;
    position: relative;
    overflow: hidden;
}

.construct-card::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 4px;
    border-radius: 4px 0 0 4px;
}

.construct-card[data-construct="construct:iws"]::before {
    background: var(--iws);
}

.construct-card[data-construct="construct:pux"]::before {
    background: var(--pux);
}

.construct-card[data-construct="construct:aifl"]::before {
    background: var(--aifl);
}

.construct-card[data-construct="construct:fsa"]::before {
    background: var(--fsa);
}

.construct-card:hover {
    background: rgba(255, 255, 255, 0.1);
    border-color: rgba(255, 255, 255, 0.25);
    transform: translateY(-3px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
}

.construct-card-name {
    font-size: 17px;
    font-weight: 700;
    color: var(--white);
    margin-bottom: 3px;
    letter-spacing: -0.01em;
}

.construct-card-full {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.08em;
    color: rgba(255, 255, 255, 0.38);
    text-transform: uppercase;
    margin-bottom: 12px;
}

.construct-card-constraint {
    font-size: 13px;
    color: rgba(255, 255, 255, 0.62);
    line-height: 1.5;
}

/* Credibility */
.block-credibility {
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: var(--radius);
    padding: 22px 26px;
}

.credibility-headline {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.35);
    margin-bottom: 16px;
}

.credibility-bullets {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.credibility-bullets li {
    font-size: 14px;
    color: rgba(255, 255, 255, 0.75);
    line-height: 1.65;
    padding-left: 18px;
    position: relative;
}

.credibility-bullets li::before {
    content: '→';
    position: absolute;
    left: 0;
    color: var(--pux);
    font-size: 12px;
    top: 2px;
}

/* What it is */
.block-what-it-is .wit-headline {
    font-size: 12px;
    font-weight: 700;
    color: rgba(199, 182, 255, 0.85);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin-bottom: 10px;
}

/* The position and its explanation share one body scale. Weight and the accent
   spine preserve the hierarchy without turning the claim into a second
   headline. */
.block-what-it-is .wit-concept {
    font-size: var(--response-body-size);
    font-weight: 600;
    line-height: var(--response-body-leading);
    letter-spacing: 0;
    color: var(--white);
    margin-bottom: 12px;
    padding-left: 12px;
    border-left: 2px solid var(--aifl);
}

.block-what-it-is .wit-connective {
    font-size: var(--response-body-size);
    color: var(--iws);
    font-style: italic;
    margin-bottom: 14px;
    padding: 12px 16px;
    background: rgba(124, 58, 237, 0.1);
    border-radius: var(--radius-sm);
    border-left: 3px solid var(--iws);
    line-height: var(--response-body-leading);
}

.block-what-it-is .wit-content {
    font-size: var(--response-body-size);
    color: rgba(255, 255, 255, 0.85);
    line-height: var(--response-body-leading);
}

/* v5 prose blocks — what / why.
   The renderer emits .block-what / .block-why (not .block-what-it-is); these
   were previously unstyled and fell back to flat default text. Mirror the
   eyebrow-label + body hierarchy used across the rest of the response. */
.block-what .wit-headline,
.block-why .wim-headline {
    font-size: 12px;
    font-weight: 700;
    color: rgba(199, 182, 255, 0.85);
    text-transform: uppercase;
    letter-spacing: 0.09em;
    margin-bottom: 12px;
}

.block-what .wit-content,
.block-why .wim-content {
    font-size: var(--response-body-size);
    color: rgba(255, 255, 255, 0.85);
    line-height: var(--response-body-leading);
}

/* Why it matters */
.block-why-it-matters .wim-headline {
    font-size: 12px;
    font-weight: 700;
    color: rgba(199, 182, 255, 0.85);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin-bottom: 10px;
}

.block-why-it-matters .wim-content {
    font-size: var(--response-body-size);
    color: rgba(255, 255, 255, 0.85);
    line-height: var(--response-body-leading);
    margin-bottom: 16px;
}

.wim-patterns {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.wim-patterns li {
    font-size: 14px;
    color: rgba(255, 255, 255, 0.55);
    padding-left: 18px;
    position: relative;
    font-style: italic;
    line-height: 1.5;
}

.wim-patterns li::before {
    content: '"';
    position: absolute;
    left: 0;
    color: var(--pux);
    font-style: normal;
}

/* Next step */
.block-next-step .ns-headline {
    font-size: 12px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.38);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin-bottom: 12px;
}

.ns-outputs {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 12px;
}

.ns-outputs li {
    font-size: 14px;
    color: rgba(255, 255, 255, 0.75);
    padding-left: 20px;
    position: relative;
    line-height: 1.55;
}

.ns-outputs li::before {
    content: '✓';
    position: absolute;
    left: 0;
    color: var(--pux);
    font-size: 12px;
    top: 2px;
}

.ns-evidence {
    font-size: 13px;
    color: rgba(255, 255, 255, 0.45);
    font-style: italic;
    padding: 10px 14px;
    background: rgba(13, 148, 136, 0.07);
    border-radius: var(--radius-sm);
    border-left: 3px solid var(--teal);
}

/* Fork */
.block-fork {
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: var(--radius);
    padding: 24px;
}

.fork-question {
    font-size: 16px;
    font-weight: 700;
    color: var(--white);
    margin-bottom: 16px;
    letter-spacing: -0.01em;
}

.fork-options {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.fork-option {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 14px 18px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: var(--radius-sm);
    cursor: pointer;
    text-align: left;
    transition: background var(--transition), border-color var(--transition), transform var(--transition);
    width: 100%;
    font-family: inherit;
}

.fork-option:enabled:hover {
    background: rgba(255, 255, 255, 0.09);
    border-color: rgba(255, 255, 255, 0.2);
    transform: translateX(4px);
}

.fork-option-name {
    font-size: 14px;
    font-weight: 700;
    color: var(--white);
    min-width: 44px;
}

.fork-option-desc {
    font-size: 13px;
    color: rgba(255, 255, 255, 0.55);
    line-height: 1.5;
}

/* Boundary */
.block-boundary {
    padding: 28px;
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: var(--radius);
}

.boundary-content {
    font-size: var(--response-body-size);
    color: rgba(255, 255, 255, 0.75);
    margin-bottom: 14px;
    line-height: var(--response-body-leading);
    font-weight: 500;
}

.boundary-redirect {
    font-size: 14px;
    color: var(--pux);
    line-height: 1.65;
}

/* People */
.block-people .people-headline {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.35);
    margin-bottom: 20px;
}

.people-acknowledgement {
    font-size: 14px;
    color: #d7c2ff;
    font-style: italic;
    margin-bottom: 20px;
    padding: 14px 18px;
    background: rgba(124, 58, 237, 0.18);
    border-radius: var(--radius-sm);
    border-left: 3px solid #b088ff;
}

.people-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 16px;
}

.person-card {
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: var(--radius);
    padding: 24px;
    transition: transform var(--transition), box-shadow var(--transition);
}

.person-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 28px rgba(0, 0, 0, 0.25);
}

.person-photo {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    object-fit: cover;
    margin-bottom: 14px;
    border: 2px solid var(--card-border);
    background: rgba(124, 58, 237, 0.2);
}

/* ── Proof wall (proof_wall mode) ─────────────────────────────────────────
   Receipts, not an about-us page. The number leads: a visitor scanning for
   proof reads stats first and prose only if a stat stops them — so the stat
   carries the numeric highlight colour and the context sits quiet beneath it.
   Cards reuse person-card's surface so the about-space reads as one system. */

.proof-wall-headline {
    font-size: 20px;
    font-weight: 600;
    line-height: 1.35;
    color: #fff;
    margin-bottom: 10px;
}

.proof-wall-acknowledgement {
    font-size: 14px;
    color: #d7c2ff;
    font-style: italic;
    margin-bottom: 20px;
    padding: 14px 18px;
    background: rgba(124, 58, 237, 0.18);
    border-radius: var(--radius-sm);
    border-left: 3px solid #b088ff;
}

.proof-wall-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 16px;
}

/* The card is a caselet in miniature: it reuses .caselet-panel-header,
   .caselet-waterline, .caselet-panel-number, .caselet-panel-contribution and
   .caselet-panel-more verbatim. Those classes carry their own horizontal
   inset, so the card itself must not add padding or every row double-indents.
   Only the inset is retuned here — never the type. */
.proof-card {
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: var(--radius);
    padding: 0;
    overflow: hidden;
    transition: transform var(--transition), box-shadow var(--transition);
}

.proof-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 28px rgba(0, 0, 0, 0.25);
}

.proof-card .caselet-panel-header {
    padding: 16px 20px 10px;
}

.proof-card .caselet-waterline {
    margin: 0 20px 12px;
}

.proof-card .caselet-eng-wrap {
    padding: 0 20px 6px;
}

.proof-card-body {
    padding: 0 20px 20px;
}

.proof-card .caselet-panel-contribution {
    margin-top: 14px;
    padding-top: 14px;
}

.proof-card .caselet-panel-more {
    margin-top: 16px;
}

/* The line the whole wall argues for. Quoted from the caselet record. */
.proof-wall-closer {
    margin-top: 20px;
    padding-left: 14px;
    border-left: 3px solid var(--stat-red);
    font-size: 15px;
    font-style: italic;
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.8);
}

@media (max-width: 640px) {
    .proof-wall-grid {
        grid-template-columns: 1fr;
    }
}

.person-photo-placeholder {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    margin-bottom: 14px;
    background: linear-gradient(135deg, var(--purple), var(--teal));
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    font-weight: 800;
    color: var(--white);
    font-family: 'Syne', sans-serif;
}

.person-name {
    font-size: 18px;
    font-weight: 700;
    color: var(--white);
    margin-bottom: 2px;
    letter-spacing: -0.01em;
}

.person-role {
    font-size: 11px;
    font-weight: 600;
    color: var(--pux);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-bottom: 14px;
}

.person-bio {
    font-size: 13px;
    color: rgba(255, 255, 255, 0.6);
    line-height: 1.65;
    margin-bottom: 16px;
}

.person-linkedin {
    font-size: 12px;
    font-weight: 600;
    color: #c4a5ff;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    transition: color var(--transition);
}

.person-linkedin:hover {
    color: var(--white);
}

/* CTA */
.block-cta {
    margin-top: 8px;
}

.block-cta .cta-message {
    font-size: 14px;
    color: rgba(255, 255, 255, 0.5);
    margin-bottom: 14px;
    line-height: 1.6;
}

/* ─── THE CLOSE (offer leads → OR → follow-up question) ───────────────────────
   Once a turn is answered the visitor has two moves, and the offer now leads
   them. Trailing everything, the CTA message was an aside under the reply box
   and 14px/50% was right for it. Leading the close it is the offer itself, and
   it carries a tint so it reads as its own thing rather than as the last
   sentence of the diagnosis directly above it.

   Same card as the scope note: brand wash, hairline, accent spine on the left
   edge, small radius. Both are the canvas saying something ABOUT the answer
   rather than continuing it, so they are one card, not two inventions — and the
   spine is what carries that, which is why this reads as a deliberate statement
   at a fraction of the padding a bordered box needed to.

   The spine doing the work is what keeps it small: the fill only has to tint,
   not fence, so the height here is the ask plus the button — which is what the
   offer IS — over the tightest padding that still reads as a surface. The ask
   is left uncapped (the scope note caps to a reading measure) because a wrapped
   ask costs another whole line inside the card; uncapped it lands on ONE line
   on a desktop column, which is the single biggest saving available here.

   .leads-close is set by mountClose, which only fires when a follow-up question
   is there to hand off to — a CTA still closing a turn alone keeps the plain
   treatment above. */
.block-cta.leads-close {
    margin-top: 18px;
    margin-bottom: 0;
    /* Optically even rather than numerically even: the ask's line-height already
       lays ~7px of leading under its last line, so a matching bottom figure
       would look heavier than the top. The extra 2px below settles it. */
    padding: 16px 22px 18px;
    background: linear-gradient(135deg,
            rgba(124, 58, 237, 0.18) 0%,
            rgba(13, 148, 136, 0.20) 100%);
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-left: 3px solid var(--teal-light);
    border-radius: var(--radius-sm);
}

.block-cta.leads-close .cta-message {
    font-size: 15.5px;
    color: rgba(255, 255, 255, 0.94);
    line-height: 1.6;
    /* Reads as ~22px against the button once the ask's leading is counted. At
       12px the button crowded the sentence it answers. */
    margin-bottom: 15px;
}

/* Seated in the card rather than dropped on it. Three things were fighting:
   the button carried the page-level 14px radius inside an 8px card, and a child
   rounder than the thing containing it always reads as unseated; the standalone
   button's shadow is tuned to lift it off the page background, so at this size
   inside a tint it bloomed into a halo instead of a lift; and trimming it to
   11px/14px to save height left it a lozenge rather than a button.

   So: the card's own radius, a shadow scaled to the shorter drop, optical
   padding (more air at the sides than above and below, which is what makes a
   short button read as considered rather than squeezed), and the label tracked
   slightly open the way small caps-height type wants. */
.block-cta.leads-close .cta-button {
    padding: 13px 30px;
    font-size: 14.5px;
    line-height: 1.15;
    letter-spacing: 0.015em;
    border-radius: var(--radius-sm);
    box-shadow:
        0 5px 16px rgba(0, 0, 0, 0.2),
        0 2px 8px rgba(124, 58, 237, 0.34),
        inset 0 1px 0 rgba(255, 255, 255, 0.34);
}

.block-cta.leads-close .cta-button:hover {
    box-shadow:
        0 9px 24px rgba(0, 0, 0, 0.24),
        0 3px 12px rgba(124, 58, 237, 0.4),
        inset 0 1px 0 rgba(255, 255, 255, 0.4);
}

/* The split between the two moves, labelled from LABELS.orDivider. The rule
   runs out to the right of the word and fades as it goes, so the fork reads as
   a seam in the glass rather than a border ruled across the answer. Margins are
   deliberately tight: this is a beat between two moves, not a section break. */
.close-divider {
    display: flex;
    align-items: center;
    gap: 14px;
    margin: 22px 0;
    /* Carries the same entrance as the blocks either side so restampStagger can
       time it into the sweep; without an animation it would pop in ahead of
       them and break the top-down assembly. */
    animation: fadeUp 0.35s ease forwards;
    opacity: 0;
}

/* A short fixed stub, NOT a flexed half — it sets the word a step in off the
   spine and gives the rule something to come from, where a second flexed arm
   would centre the word and a bare left edge left it dangling. */
.close-divider::before {
    content: "";
    flex: 0 0 26px;
    height: 1px;
    background: linear-gradient(90deg,
            rgba(255, 255, 255, 0) 0%,
            rgba(255, 255, 255, 0.28) 100%);
}

/* Full strength where it leaves the word, fading only as it runs out. Fading
   across the whole span instead left it averaging near-invisible, which read as
   a word floating in a gap rather than a divider. */
.close-divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background: linear-gradient(90deg,
            rgba(255, 255, 255, 0.28) 0%,
            rgba(255, 255, 255, 0) 88%);
}

/* Sized and tracked like the section eyebrows so the fork reads as part of the
   same system, but a step quieter than them: it labels the choice, it is not a
   heading for what follows. */
.close-divider-word {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.55);
}

.cta-button {
    display: inline-block;
    padding: 16px 36px;
    font-size: 15px;
    font-weight: 700;
    font-family: inherit;
    color: var(--white);
    /* Brighter than the page gradient + a crisp light edge and glossy top, so
       the button reads as "lit up" against the matching-gradient background. */
    background: linear-gradient(135deg, #8b5cf6 0%, #14b8a6 100%);
    border: 1px solid rgba(255, 255, 255, 0.32);
    border-radius: var(--radius);
    cursor: pointer;
    text-decoration: none;
    letter-spacing: 0.01em;
    transition: filter var(--transition), transform var(--transition), box-shadow var(--transition);
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.3), 0 3px 14px rgba(124, 58, 237, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.35);
}

.cta-button:hover {
    filter: brightness(1.06);
    transform: translateY(-2px);
    box-shadow: 0 16px 36px rgba(0, 0, 0, 0.34), 0 4px 18px rgba(124, 58, 237, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.4);
}

.cta-button.urgent {
    background: linear-gradient(135deg, #dc2626, var(--purple));
    box-shadow: 0 4px 20px rgba(220, 38, 38, 0.3);
    animation: urgentPulse 2.5s ease infinite;
}

@keyframes urgentPulse {

    0%,
    100% {
        box-shadow: 0 4px 20px rgba(220, 38, 38, 0.3);
    }

    50% {
        box-shadow: 0 8px 32px rgba(220, 38, 38, 0.55);
    }
}

/* Inline caselet (mobile / when no aside) — whitish glass matching the aside
   proof card and the CTA band: flat translucent white + light blur. */
.block-caselet {
    background: rgba(255, 255, 255, 0.10);
    border: 1px solid rgba(255, 255, 255, 0.22);
    border-radius: var(--radius);
    padding: 22px 24px;
    position: relative;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    box-shadow: 0 16px 42px rgba(0, 0, 0, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.12);
}

.block-caselet::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 4px;
    background: linear-gradient(180deg, var(--purple), var(--teal));
    border-radius: 4px 0 0 4px;
}

.caselet-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: rgba(159, 103, 245, 0.7);
    margin-bottom: 8px;
}

.caselet-title {
    font-size: 14px;
    font-weight: 700;
    color: var(--iws);
    margin-bottom: 10px;
    line-height: 1.4;
}

.caselet-pain {
    font-size: 13px;
    color: rgba(255, 255, 255, 0.6);
    font-style: italic;
    margin-bottom: 10px;
}

.caselet-summary {
    font-size: 14px;
    color: rgba(255, 255, 255, 0.8);
    line-height: 1.65;
    margin-bottom: 12px;
}

.caselet-signals {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.caselet-signals li {
    font-size: 13px;
    color: var(--pux);
    padding-left: 16px;
    position: relative;
    line-height: 1.5;
}

.caselet-signals li::before {
    content: '→';
    position: absolute;
    left: 0;
    color: var(--teal);
    font-size: 11px;
}

/* --- Conversational response blocks (moved from index.html inline <style>) --- */

/* diagnosis_opener — consultant's first sentence */
.block-diagnosis-opener {
    border-left: 3px solid rgba(139, 92, 246, 0.6);
    padding-left: 16px;
    margin-bottom: 4px;
}
.block-diagnosis-opener p {
    font-size: var(--response-body-size);
    font-style: italic;
    color: rgba(255,255,255,0.92);
    line-height: var(--response-body-leading);
    margin: 0;
}

/* scope_note — the scope-redirect boundary card (r4). One sentence naming
   what sits outside Tiny Magiq's practice + the pivot offer. A coloured
   glass card with the brand gradient tint and a teal spine, so the boundary
   reads as a deliberate, considered statement — distinct from both the plain
   prose answer above it and the question below. */
.block-scope-note {
    background: linear-gradient(135deg,
        rgba(124, 58, 237, 0.18) 0%,
        rgba(13, 148, 136, 0.20) 100%);
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-left: 3px solid var(--teal-light);
    border-radius: var(--radius-sm);
    padding: 18px 24px;
    margin: 14px 0 10px;
}
.block-scope-note p {
    font-size: var(--response-body-size);
    color: rgba(255, 255, 255, 0.94);
    line-height: var(--response-body-leading);
    margin: 0;
    max-width: 68ch;
}

/* lead_capture — inline form in conversation */
.block-lead-capture {
    margin-top: 8px;
}
/* The lead-capture card must read as a distinct, raised surface — not a faint
   tint that blends into the page gradient. Whitish glass + brand top-edge +
   drop shadow, matching the caselet proof card / contact windows, so it clearly
   "pops" as a card the visitor is meant to act on.

   The lift is built from three stacked shadows rather than one big black blur:
   a tight contact shadow that seats the card, a wide ambient that carries the
   depth, and a brand bloom. Near-black at high alpha greyed the glass and made
   the gradient behind it look dirty — most of the darkness now lives in the
   ambient layer, where it reads as distance instead of soot.

   No backdrop-filter here, deliberately. These cards are inside .block, whose
   fadeUp animates opacity — an opacity animation establishes a backdrop root,
   which cuts every descendant's backdrop-filter off from the page painted
   behind it. Measured: blur(40px) saturate(3) hue-rotate(90deg) rendered
   pixel-identical to no filter at all. It only ever cost paint. Anything added
   here has to survive that test first. */
.lead-capture-inner,
.lead-capture-pattern {
    position: relative;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.10);
    /* Dimmer than the fill it wraps. At 0.22 the border measured lighter than
       BOTH the card inside it and the page outside it, so it read as a halo
       ringing the card rather than as its edge. */
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: var(--radius);
    box-shadow:
        0 1px 2px rgba(12, 10, 30, 0.16),
        0 18px 44px -12px rgba(12, 10, 30, 0.42),
        0 6px 20px -8px rgba(124, 58, 237, 0.34);
}
.lead-capture-inner {
    padding: 26px;
}
/* Brand top-edge — the same accent language as the caselet / contact cards, so
   the card reads as a lit surface with a defined top. Tapered to transparent at
   both ends: a full-bleed bar butts into the rounded corners and reads as an
   applied stripe, where a taper reads as light falling across the edge.

   2px, not 1.5px: a fractional height can't land on a device pixel at DPR 1, so
   it antialiased across two rows at partial alpha and read as a smudge rather
   than a line.

   Only on the form card. The pattern card carried a dimmed copy, which put a
   second line 1px under the border and made the top edge read as doubled — the
   card that is meant to sit back has no business having a lit edge at all. */
.lead-capture-inner::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 2px;
    background: linear-gradient(90deg,
        transparent 0%,
        var(--purple-light) 16%,
        var(--teal-light) 84%,
        transparent 100%);
}
/* R4 Workstream A — the one-line pattern synthesis on the converged turn. Its
   own panel above the form: the pattern is the payoff of the whole
   conversation, so it lands as a statement the visitor reads on its own, not as
   a heading on a form. It is a statement to read, not a surface to act on, so
   it sits back — shallower lift, no brand bloom, no lit top edge — leaving the
   form card as the one thing that pops, because it's the one thing to do. */
.lead-capture-pattern {
    padding: 22px 26px 24px;
    margin-bottom: 12px;
    box-shadow:
        0 1px 2px rgba(12, 10, 30, 0.10),
        0 10px 26px -16px rgba(12, 10, 30, 0.26);
}
/* Sheen — a soft highlight raking off the top-left corner, kept faint so it
   models the glass without lighting the card up. */
.lead-capture-pattern::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: radial-gradient(110% 90% at 0% 0%,
        rgba(255, 255, 255, 0.05) 0%,
        rgba(255, 255, 255, 0) 62%);
}
/* Above the sheen, which is a sibling in the same stacking context. */
.lead-capture-pattern-eyebrow,
.lead-capture-pattern-line {
    position: relative;
    z-index: 1;
}
.lead-capture-pattern-eyebrow {
    display: block;
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.52);
    margin-bottom: 10px;
}
/* The payoff line. Body prose on the shared response scale, normal
   weight, default tracking) — the same type as .continuation-content and
   .block-what / .block-why, which is what actually sits above it on a converged
   turn. It was display-weight, then 19px/1.75; either way it stepped up from the
   prose it follows and read as a pull-quote shouted back at the visitor rather
   than as the closing sentence of what they had just been told. The eyebrow and
   the card already mark it as the payoff — the type does not have to as well.
   Held a touch brighter than body (0.88 → 0.92) only because it sits on the
   dimmed pattern card, not on the page: same apparent weight, not more. */
.lead-capture-pattern-line {
    display: block;
    font-size: var(--response-body-size);
    line-height: var(--response-body-leading);
    font-weight: 400;
    letter-spacing: normal;
    color: rgba(255, 255, 255, 0.92);
}
/* Turn feedback strip. Two mount points, one component: inside the converged
   lead-capture card (default size), and above every answered turn's CTA
   (--compact). Quieter than whatever it sits next to either way — it's an aside
   the visitor may answer, not the thing we're asking them to do. */
.tm-feedback {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    background: rgba(255, 255, 255, 0.055);
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: var(--radius);
    padding: 15px 20px;
    margin-bottom: 12px;
    box-shadow:
        0 1px 2px rgba(12, 10, 30, 0.12),
        0 8px 22px -10px rgba(12, 10, 30, 0.30);
}
/* Above the CTA: no card at all. A third panel stacked over the offer competed
   with it — this is one quiet line the eye can skip, with a hairline to sit it
   under the answer rather than a border to box it in. Chrome only: both mounts
   share one type scale, so the aside reads the same wherever it appears. */
.tm-feedback--compact {
    background: none;
    border: 0;
    border-top: 1px solid rgba(255, 255, 255, 0.10);
    border-radius: 0;
    box-shadow: none;
    padding: 12px 2px 0;
    margin-bottom: 0;
    gap: 10px 14px;
}
.tm-feedback--compact .tm-feedback-sub {
    display: none;
}
/* The strip is a .block only so it inherits the entrance stagger; it must not
   also inherit the 24px block gap, or it detaches from the CTA it belongs to. */
.block-turn-feedback {
    margin-bottom: 10px;
}
.tm-feedback-ask {
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.tm-feedback-q {
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: -0.005em;
    color: rgba(255, 255, 255, 0.72);
}
.tm-feedback-sub {
    font-size: 0.7rem;
    color: rgba(255, 255, 255, 0.5);
}
.tm-feedback-opts {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
/* Each option carries its own accent, set per-variant below and picked up by
   the icon, border and hover wash through currentColor / --fb-accent. */
.tm-feedback-btn {
    --fb-accent: var(--purple-bright);
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: rgba(255, 255, 255, 0.07);
    border: 1px solid color-mix(in srgb, var(--fb-accent) 34%, transparent);
    border-radius: 999px;
    padding: 6px 12px;
    color: rgba(255, 255, 255, 0.9);
    font-family: inherit;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: -0.005em;
    line-height: 1;
    cursor: pointer;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.10);
    transition: background var(--transition), border-color var(--transition),
        color var(--transition), transform var(--transition), box-shadow var(--transition);
}
.tm-feedback-btn.is-makes_sense { --fb-accent: var(--teal-light); }
.tm-feedback-btn.is-partially { --fb-accent: var(--purple-bright); }
.tm-feedback-btn.is-not_quite { --fb-accent: var(--pink-light); }
.tm-feedback-icon {
    width: 13px;
    height: 13px;
    flex-shrink: 0;
    color: var(--fb-accent);
}
/* Each verdict's confirmation colour (affirm / partial / miss). The idle
   accent (--fb-accent) keeps driving hover and focus; --fb-picked fills the
   icon solid when the verdict is chosen below. */
.tm-feedback-btn.is-makes_sense { --fb-picked: var(--green); }
.tm-feedback-btn.is-partially { --fb-picked: var(--fsa); }
.tm-feedback-btn.is-not_quite { --fb-picked: var(--pink); }
.tm-feedback-btn:hover:not(:disabled):not(.is-picked) {
    background: color-mix(in srgb, var(--fb-accent) 18%, rgba(255, 255, 255, 0.07));
    border-color: color-mix(in srgb, var(--fb-accent) 70%, transparent);
    color: #fff;
    transform: translateY(-1px);
    box-shadow:
        0 6px 18px -4px color-mix(in srgb, var(--fb-accent) 34%, transparent),
        inset 0 1px 0 rgba(255, 255, 255, 0.16);
}
.tm-feedback-btn:active:not(:disabled) {
    transform: translateY(0);
}
.tm-feedback-btn:focus-visible {
    outline: 2px solid var(--fb-accent);
    outline-offset: 2px;
}
/* Answered: the chosen option stays lit, the others recede rather than
   disappear — the visitor can still see what they picked. */
.tm-feedback-btn:disabled {
    cursor: default;
    opacity: 0.4;
}
/* Picked: the pill keeps its glassy wash and lights its accent border + glow
   ring; the confirmation lands in the ICON, which fills solid with the
   verdict's colour and pops once as it lands. The pill stays fully lit whether
   the strip locked (a weighted verdict) or stays live: a verdict the visitor
   can still untap keeps its pointer cursor, so it reads as chosen AND
   re-tappable. Placed after :disabled so it wins at equal specificity. */
.tm-feedback-btn.is-picked {
    opacity: 1;
    background: color-mix(in srgb, var(--fb-accent) 26%, rgba(255, 255, 255, 0.08));
    border-color: var(--fb-accent);
    color: #fff;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--fb-accent) 18%, transparent);
    animation: tm-fb-pop 0.34s cubic-bezier(0.2, 0.9, 0.3, 1.35);
}
.tm-feedback-btn.is-picked:hover:not(:disabled) {
    transform: translateY(-1px);
}
/* Solid icon fill. The thumbs fill whole; the "partially" disc fills while its
   question-mark strokes flip to dark ink — filling every path the same colour
   would dissolve the glyph into the disc. */
.tm-feedback-btn.is-picked .tm-feedback-icon path {
    fill: var(--fb-picked);
    stroke: var(--fb-picked);
}
.tm-feedback-btn.is-picked.is-partially .tm-feedback-icon circle {
    fill: var(--fb-picked);
    stroke: var(--fb-picked);
}
.tm-feedback-btn.is-picked.is-partially .tm-feedback-icon path {
    fill: none;
    stroke: #0e1026;
    stroke-width: 2.2;
}
@keyframes tm-fb-pop {
    0% { transform: scale(1); }
    45% { transform: scale(1.08); }
    100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    .tm-feedback-btn.is-picked { animation: none; }
}

/* ── Optional "why" field inside the lead-capture form ──
   Slides open above the name input when the visitor taps Partially / Not
   quite. One 0fr→1fr wrapper row around a single overflow-hidden inner, so
   the height genuinely animates; the textarea itself is a .lead-capture-input,
   so the well treatment stays identical to name/email above it. */
.lead-capture-feedback-note {
    display: grid;
    grid-template-rows: 0fr;
    opacity: 0;
    transition: grid-template-rows 0.28s ease, opacity 0.28s ease;
}
.lead-capture-feedback-note.is-open {
    grid-template-rows: 1fr;
    opacity: 1;
}
.lead-capture-feedback-note-inner {
    min-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: 8px;
    /* room for the textarea's 3px focus ring inside the overflow clip;
       the negative margin gives the space back to the layout */
    padding: 3px;
    margin: -3px;
}
.lead-capture-feedback-note-label {
    font-size: 0.82rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: rgba(255, 255, 255, 0.85);
}
/* Verdict-coloured dot before the prompt, so the field visibly belongs to the
   chip that opened it. */
.lead-capture-feedback-note[data-choice="partially"] { --fb-note-accent: var(--fsa); }
.lead-capture-feedback-note[data-choice="not_quite"] { --fb-note-accent: var(--pink); }
.lead-capture-feedback-note-label::before {
    content: "";
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    margin-right: 8px;
    background: var(--fb-note-accent, var(--purple-bright));
    box-shadow: 0 0 10px color-mix(in srgb,
        var(--fb-note-accent, var(--purple-bright)) 60%, transparent);
}
.lead-capture-feedback-note-input {
    resize: vertical;
    min-height: 58px;
    font-size: 0.9rem;
    line-height: 1.5;
}
.lead-capture-message {
    font-size: 1rem;
    color: rgba(255, 255, 255, 0.9);
    margin-bottom: 18px;
    line-height: 1.6;
    max-width: 64ch;
    transition: opacity 0.19s ease, transform 0.19s ease;
}
/* Mid-crossfade (swapLeadMessage): the old copy dips out, the verdict's
   acknowledgement fades back in its place. */
.lead-capture-message.is-swapping {
    opacity: 0;
    transform: translateY(3px);
}
.lead-capture-form {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
/* Fields read as wells cut into the card, not as more raised glass. The cue is
   the inset top shadow, not a dark fill — darkening the surface muddied it
   against the page gradient and read as a hole rather than a field. */
.lead-capture-input {
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 10px;
    padding: 13px 15px;
    color: #fff;
    font-size: 0.95rem;
    font-family: inherit;
    outline: none;
    box-shadow: inset 0 1px 2px rgba(12, 10, 30, 0.12);
    transition: border-color var(--transition), background var(--transition),
        box-shadow var(--transition);
}
.lead-capture-input:hover:not(:focus) {
    border-color: rgba(255, 255, 255, 0.28);
}
.lead-capture-input:focus {
    border-color: rgba(159, 103, 245, 0.85);
    background: rgba(255, 255, 255, 0.10);
    box-shadow:
        0 0 0 3px rgba(124, 58, 237, 0.18),
        inset 0 1px 2px rgba(12, 10, 30, 0.10);
}
.lead-capture-input::placeholder {
    color: rgba(255, 255, 255, 0.45);
}
/* Lit gradient Send — same treatment as the reply-dock Send, so both "Send"
   controls on the page read identically. */
.lead-capture-submit {
    background: linear-gradient(135deg, var(--purple-bright-fill) 0%, #14b8a6 100%);
    border: 1px solid rgba(255, 255, 255, 0.28);
    border-radius: 11px;
    padding: 13px 28px;
    margin-top: 4px;
    color: #fff;
    font-size: 0.95rem;
    font-family: inherit;
    font-weight: 700;
    letter-spacing: -0.005em;
    cursor: pointer;
    align-self: flex-start;
    box-shadow:
        0 1px 2px rgba(12, 10, 30, 0.20),
        0 10px 26px -8px rgba(165, 109, 255, 0.55),
        inset 0 1px 0 rgba(255, 255, 255, 0.32);
    transition: filter var(--transition), transform var(--transition), box-shadow var(--transition);
}
.lead-capture-submit:hover {
    filter: brightness(1.08);
    transform: translateY(-1px);
    box-shadow:
        0 1px 2px rgba(12, 10, 30, 0.22),
        0 14px 32px -8px rgba(165, 109, 255, 0.62),
        inset 0 1px 0 rgba(255, 255, 255, 0.38);
}
.lead-capture-submit:active {
    transform: translateY(0);
}
.lead-capture-submit:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    transform: none;
    filter: none;
}
.lead-capture-note {
    font-size: 0.78rem;
    color: rgba(255,255,255,0.5);
    margin-top: 12px;
}
.lead-capture-error {
    color: #fca5a5;
    font-size: 0.8rem;
    margin-top: 8px;
}
/* Returning visitor — we already hold their contact details, so the card shows
   this instead of name/email inputs. It is NOT the success panel: nothing was
   just submitted. Quieter, and it always renders, so a converged card can never
   come out empty when there is no pattern line to hang a feedback strip on. */
.lead-capture-ack {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 14px;
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.14);
    font-size: 0.9rem;
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.78);
}
.lead-capture-ack-mark {
    flex: none;
    width: 18px;
    height: 18px;
    margin-top: 2px;
    color: #4ade80;
}
.lead-capture-ack-mark svg {
    width: 100%;
    height: 100%;
    display: block;
}
/* Confirmation for the in-chat lead form. Same language as the Contact Us
   page's thank-you panel — a gradient mark and a lifted panel — sized down to
   sit inside a chat card rather than take over a page. */
.lead-capture-success {
    display: flex;
    align-items: center;
    gap: 13px;
    padding: 16px 18px;
    border-radius: 14px;
    background:
        radial-gradient(120% 160% at 0% 0%, rgba(159, 103, 245, 0.30), transparent 62%),
        rgba(255, 255, 255, 0.10);
    border: 1px solid rgba(255, 255, 255, 0.24);
    box-shadow: 0 12px 32px rgba(5, 3, 20, 0.26), inset 0 1px 0 rgba(255, 255, 255, 0.18);
    animation: lead-success-in 0.42s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes lead-success-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: none; }
}
.lead-capture-success-mark {
    flex: none;
    width: 38px;
    height: 38px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: linear-gradient(135deg, #8b5cf6 0%, #14b8a6 100%);
    border: 1px solid rgba(255, 255, 255, 0.42);
    box-shadow: 0 6px 18px rgba(124, 58, 237, 0.42), inset 0 1px 0 rgba(255, 255, 255, 0.4);
}
.lead-capture-success-mark svg {
    width: 20px;
    height: 20px;
    display: block;
}
.lead-capture-success-mark path {
    stroke-dasharray: 32;
    stroke-dashoffset: 32;
    animation: lead-success-tick 0.38s 0.18s cubic-bezier(0.65, 0, 0.35, 1) forwards;
}
@keyframes lead-success-tick {
    to { stroke-dashoffset: 0; }
}
.lead-capture-success-text {
    min-width: 0;
    font-size: 0.98rem;
    font-weight: 600;
    line-height: 1.45;
    color: #ffffff;
}
@media (prefers-reduced-motion: reduce) {
    .lead-capture-success,
    .lead-capture-success-mark path {
        animation: none;
    }
    .lead-capture-success-mark path {
        stroke-dashoffset: 0;
    }
}
/* Touch input, at any width — a mouse can hit a 35px pill, a thumb cannot.
   Keyed off pointer type rather than width because a 1024px tablet is still
   touch, and a narrow desktop window is still a mouse. */
@media (pointer: coarse) {
    .tm-feedback-btn {
        min-height: 44px;
        padding-block: 0;
    }
    .lead-capture-input,
    .lead-capture-submit {
        min-height: 46px;
    }
}
/* Narrow screens — the feedback options drop under their question rather than
   squeezing beside it. The pattern line needs no step-down of its own: it is
   body prose now, and body prose does not shrink here either. */
@media (max-width: 640px) {
    .lead-capture-pattern {
        padding: 18px 20px 20px;
    }
    .lead-capture-inner {
        padding: 20px;
    }
    .tm-feedback {
        align-items: flex-start;
        gap: 12px;
    }
    .tm-feedback-opts {
        width: 100%;
    }
    /* The converged card's strip only. It is a real card (the compact strip is a
       hairline), and on a phone that card sits directly above the name/email form
       — the thing we are actually asking for. Desktop has the width to carry
       both; a phone does not, so the aside gives some back. `:not()` rather than
       a third class: there are exactly two mounts, and the compact one is already
       sized for narrow screens above. */
    .tm-feedback:not(.tm-feedback--compact) {
        padding: 12px 14px;
        gap: 10px;
    }
    .tm-feedback:not(.tm-feedback--compact) .tm-feedback-sub {
        font-size: 0.66rem;
    }
    /* Both strips shrink on phones, where the feedback is an aside next to the
       thing we're actually asking for and the 44px touch minimum made it as loud
       as the CTA. 34px still clears WCAG 2.5.8's 24px target minimum with room to
       spare. The doubled class is specificity, so this wins over the
       pointer:coarse rule rather than relying on source order. */
    .tm-feedback.tm-feedback .tm-feedback-q {
        font-size: 0.75rem;
    }
    .tm-feedback.tm-feedback .tm-feedback-btn {
        min-height: 34px;
        padding: 0 11px;
        font-size: 0.7rem;
        gap: 5px;
    }
    .tm-feedback.tm-feedback .tm-feedback-icon {
        width: 12px;
        height: 12px;
    }
    .tm-feedback.tm-feedback .tm-feedback-opts {
        gap: 6px;
    }
    /* Sized to their labels and left to wrap. Letting them grow made whichever
       option landed alone on a row stretch to full width, which reads as
       emphasis the option hasn't earned — "Not quite" is not the headline. */
    .tm-feedback-btn {
        flex: 0 1 auto;
    }
    /* Full-bleed CTA — the standard mobile affordance, and it keeps the label
       on one line, which it can't do at desktop padding on a 320px screen. */
    .lead-capture-submit {
        align-self: stretch;
        width: 100%;
        padding-inline: 16px;
        font-size: 0.92rem;
        text-align: center;
    }
}

/* continuation block — follow-up query response */
.block-continuation {
    margin-bottom: 8px;
}
.continuation-content {
    font-size: var(--response-body-size);
    color: rgba(255,255,255,0.88);
    line-height: var(--response-body-leading);
    margin-bottom: 14px;
}

/* approach block — Mode 1 fork replacement */
.block-approach {
    margin-top: 8px;
}
.approach-content {
    font-size: var(--response-body-size);
    color: rgba(255,255,255,0.82);
    line-height: var(--response-body-leading);
    margin-bottom: 16px;
}
.approach-cta-question {
    font-size: 1.12rem;
    font-weight: 600;
    color: rgba(255,255,255,0.95);
    border-left: 3px solid rgba(139, 92, 246, 0.7);
    padding-left: 14px;
    line-height: 1.4;
}

/* --- Domain cards (moved from app.js renderDomainCards injection) --- */
.block-domain-cards {
    margin: 16px 0 8px;
}
.domain-cards-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
    margin-bottom: 16px;
}
.domain-card {
    background: rgba(255,255,255,0.04);
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 10px;
    padding: 14px 16px;
    cursor: pointer;
    text-align: left;
    transition: background 0.15s, border-color 0.15s, transform 0.15s;
    display: flex;
    flex-direction: column;
    min-height: 100px;
}
.domain-card:hover {
    background: rgba(139,92,246,0.1);
    border-color: rgba(139,92,246,0.4);
    transform: translateY(-1px);
}
.domain-card-label {
    font-size: 0.65rem;
    font-weight: 700;
    color: rgba(139,92,246,0.9);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    margin-bottom: 8px;
    flex-shrink: 0;
}
.domain-card-proof {
    font-size: 0.8rem;
    color: rgba(255,255,255,0.68);
    line-height: 1.5;
    flex: 1;
}
.domain-cards-footer {
    font-size: 0.82rem;
    color: rgba(255,255,255,0.45);
    line-height: 1.55;
    border-top: 1px solid rgba(255,255,255,0.07);
    padding-top: 12px;
    font-style: italic;
}


/* ── The agent line ────────────────────────────────────────────────────────
   The last thing on an answered turn: one quiet sentence pointing at the
   Agents-Hub agent for the pain just diagnosed. It sits BELOW the whole close
   (CTA → OR → follow-up question → reply dock), and its entire job is to be
   findable without ever reading as a second call to action.

   So: no fill, no border, no radius, no button. A hairline sits it under the
   turn the way .tm-feedback--compact sits under the answer, and the type runs
   a step below body copy. The CTA keeps every affordance this one gives up. */
.agent-offer {
    border-top: 1px solid rgba(255, 255, 255, 0.09);
    margin-top: 26px;
    padding-top: 14px;
    /* Same entrance as the blocks above it so restampStagger can time it into
       the sweep — without one it would pop in ahead of the close. */
    animation: fadeUp 0.35s ease forwards;
    opacity: 0;
}
.agent-offer-label {
    display: block;
    font-size: 12px;
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.42);
    margin-bottom: 5px;
}
/* Baseline-aligned rather than centred: the name is the anchor, and the
   one-liner hangs off its line however the text wraps. */
.agent-offer-link {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 8px;
    text-decoration: none;
    font-size: 13px;
    line-height: 1.55;
    /* ~60% white at rest — present, skippable, never louder than the offer. */
    color: rgba(255, 255, 255, 0.6);
    transition: color var(--transition);
}
/* Hover lifts alpha and nothing else — 0.6 → 0.9 on the same white. A hue
   shift, a fill or a lift would all have been louder than the CTA's own
   hover, which is the one thing this line may never out-shout. */
.agent-offer-link:hover,
.agent-offer-link:focus-visible {
    color: rgba(255, 255, 255, 0.9);
}
.agent-offer-name {
    font-weight: 600;
    /* Only the name is underlined, and only on the trailing edge, so at rest
       the line reads as prose rather than as a link bar. */
    text-decoration: underline;
    text-decoration-color: rgba(255, 255, 255, 0.22);
    text-underline-offset: 3px;
    transition: text-decoration-color var(--transition);
}
.agent-offer-link:hover .agent-offer-name,
.agent-offer-link:focus-visible .agent-offer-name {
    text-decoration-color: rgba(255, 255, 255, 0.55);
}
.agent-offer-liner {
    color: rgba(255, 255, 255, 0.45);
    font-size: 12.5px;
}
.agent-offer-link:hover .agent-offer-liner,
.agent-offer-link:focus-visible .agent-offer-liner {
    color: rgba(255, 255, 255, 0.68);
}
/* Name + glyph travel together as one flex item. The glyph marks the LINK, and
   the link's identity is the name — trailing it after the one-liner made it
   read as decorating the description instead of marking the destination.
   It also fixed a wrap bug: with the one-liner at flex-basis:100% on narrow
   screens, a glyph sitting after it was pushed onto a third row, alone. */
.agent-offer-head {
    /* Not display:flex — the glyph must stay INLINE so it flows with the last
       word of the name and follows it wherever the name itself wraps. */
    min-width: 0;
}
/* Leaves-the-site glyph. Sized off the name's line so it tracks the text
   rather than sitting as an icon beside it, and raised to sit at the name's
   top-right the way an external-link marker conventionally does. */
.agent-offer-glyph {
    display: inline-block;
    width: 11px;
    height: 11px;
    margin-left: 4px;
    /* Raised off the baseline rather than vertical-align:super, which would
       also shrink it and drag the line-height around. */
    vertical-align: baseline;
    transform: translateY(-2px);
    opacity: 0.75;
}
/* The "prompt copied" confirmation, shown for a few seconds after a click.
   Quieter than the one-liner it sits under: it is a receipt for something that
   already happened, not a third thing competing for the eye. display:block so
   it takes its own row under the inline-flex link rather than joining it. */
.agent-offer-copied {
    display: block;
    margin-top: 6px;
    font-size: 11.5px;
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.38);
    animation: fadeUp 0.25s ease forwards;
}
/* Keyboard focus needs to be visible even though the link is deliberately
   quiet — the ring is the one place this may be as loud as anything else. */
.agent-offer-link:focus-visible {
    outline: 2px solid rgba(255, 255, 255, 0.55);
    outline-offset: 3px;
    border-radius: var(--radius-xs);
}

/* Touch: a thumb needs 44px of target. Grown with padding and a full-width
   row, NOT with type size or a fill — the target gets bigger, the line does
   not get louder. Keyed off pointer type for the same reason .tm-feedback-btn
   is: a tablet is touch at any width. */
@media (pointer: coarse) {
    .agent-offer-link {
        display: flex;
        width: 100%;
        min-height: 44px;
        align-content: center;
        padding-block: 6px;
    }
}
/* Narrow screens: the one-liner drops under the name instead of squeezing
   beside it, so neither is truncated. */
@media (max-width: 640px) {
    .agent-offer {
        margin-top: 22px;
    }
    .agent-offer-liner {
        flex-basis: 100%;
    }
}
@media (prefers-reduced-motion: reduce) {
    .agent-offer {
        animation: none;
        opacity: 1;
    }
}

/* ── Agent catalogue ─────────────────────────────────────────────────────────
   The Hub rendered INSIDE the answer, for the turn that asked what tools exist.

   ONE TAB PER LENS, not one ladder of fifteen links and not five cards of
   them. The rows carry the same language as .agent-offer — same type size, same
   resting alpha, same glyph on the name — because a row here IS that link. What
   the strip adds is the decision the offer never had to support: five
   constraints, side by side, with the tools of exactly one of them underneath.

   Every visual weight is spent on the GROUPING, not the rows. The accent lives
   in the strip, the spine and the badge; the links themselves stayed quiet,
   because a block of fifteen could out-shout the close simply by being big, and
   this block still sits under the CTA. Tabs also cap its height at one lens, so
   the follow-up question underneath is on the same screen as the shelf.

   No backdrop-filter, deliberately — see .lead-capture-inner above: .block's
   fadeUp animates opacity, which establishes a backdrop root and cuts every
   descendant's filter off from the page behind it. Glass here is a plain white
   fill plus shadow, which survives that. */
.block-agent-catalogue {
    margin-top: 4px;
}
.agent-cat-note {
    font-size: 13px;
    line-height: 1.6;
    color: rgba(255, 255, 255, 0.55);
    margin-bottom: 16px;
}
/* THE LENS STRIP. The five constraints together, and the rest of the shelf
   behind them: the choice is made against the constraints, not against fifteen
   tool names.

   WRAPS, never scrolls. The five authored lens names run past 1100px — the
   block's widest possible home — so a single-line strip clipped "AI-First
   Leadership" at the edge on the widest screen the site has, with no bar and no
   fade to say a fifth lens was there. A hidden tab is a hidden lens, which is
   the one thing this layout cannot afford: the panel below shows a quarter of
   the Hub, and the strip is the only evidence of the rest. Two rows of pills
   cost nothing and hide nothing. */
.agent-cat-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding-bottom: 10px;
    margin-bottom: 12px;
    box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.08);
}
/* A tab is quiet at rest and never underlined: the only loud thing in the strip
   is the one that is open, because "which is selected" is the single fact the
   strip has to answer at a glance. */
.agent-cat-tab {
    display: flex;
    align-items: center;
    gap: 7px;
    flex: 0 0 auto;
    padding: 7px 12px;
    border: 1px solid transparent;
    border-radius: 999px;
    background: transparent;
    font: inherit;
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--transition), border-color var(--transition);
}
.agent-cat-tab:hover {
    background: rgba(255, 255, 255, 0.05);
}
/* The open lens: its own accent as a tinted fill and a matching hairline, so it
   reads as the panel's top edge rather than as a button that happens to be on.
   color-mix keeps one --accent value serving the fill, the border and the type. */
.agent-cat-tab[aria-selected="true"] {
    background: color-mix(in srgb, var(--accent) 14%, transparent);
    border-color: color-mix(in srgb, var(--accent) 38%, transparent);
}
.agent-cat-tab-badge {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--accent);
    opacity: 0.75;
    transition: opacity var(--transition);
}
.agent-cat-tab[aria-selected="true"] .agent-cat-tab-badge {
    opacity: 1;
}
.agent-cat-tab-label {
    font-size: 12.5px;
    font-weight: 600;
    letter-spacing: -0.005em;
    color: rgba(255, 255, 255, 0.62);
    transition: color var(--transition);
}
.agent-cat-tab:hover .agent-cat-tab-label {
    color: rgba(255, 255, 255, 0.85);
}
.agent-cat-tab[aria-selected="true"] .agent-cat-tab-label {
    color: var(--white);
}
/* The bare number, not "3 agents": five tabs repeating the same word spend the
   strip's width on the one part of the count that never varies. */
.agent-cat-tab-count {
    font-size: 10.5px;
    font-weight: 600;
    line-height: 1;
    padding: 3px 6px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.5);
}
.agent-cat-tab[aria-selected="true"] .agent-cat-tab-count {
    background: color-mix(in srgb, var(--accent) 20%, transparent);
    color: rgba(255, 255, 255, 0.78);
}
.agent-cat-tab:focus-visible {
    outline: 2px solid rgba(255, 255, 255, 0.55);
    outline-offset: 2px;
}
/* THE PANEL — the lens that is open. Same surface the cards had, at full width
   now that only one is on screen at a time. */
.agent-cat-panel {
    position: relative;
    overflow: hidden;
    isolation: isolate;
    background: rgba(255, 255, 255, 0.055);
    border: 1px solid rgba(255, 255, 255, 0.11);
    border-radius: var(--radius);
    padding: 16px 16px 8px;
    /* Seated, not floating: a tight contact shadow plus a wide ambient. The
       panel is not clickable, so it never lifts on hover — the row does. */
    box-shadow:
        0 1px 2px rgba(12, 10, 30, 0.14),
        0 12px 30px -14px rgba(12, 10, 30, 0.34);
}
.agent-cat-panel:focus-visible {
    outline: 2px solid rgba(255, 255, 255, 0.4);
    outline-offset: 2px;
}
/* The lens accent, one declaration per construct and then derived everywhere
   from --accent. Same ids and same colours as .construct-card, so a lens is the
   same colour wherever the visitor meets it. The fallback covers the company
   group (Ace AI), which is Tiny Magiq itself rather than one of the four. */
.agent-cat-panel,
.agent-cat-tab {
    --accent: var(--purple-bright);
}
.agent-cat-panel[data-construct="construct:iws"],
.agent-cat-tab[data-construct="construct:iws"] {
    --accent: var(--iws);
}
.agent-cat-panel[data-construct="construct:pux"],
.agent-cat-tab[data-construct="construct:pux"] {
    --accent: var(--pux);
}
.agent-cat-panel[data-construct="construct:aifl"],
.agent-cat-tab[data-construct="construct:aifl"] {
    --accent: var(--aifl);
}
.agent-cat-panel[data-construct="construct:fsa"],
.agent-cat-tab[data-construct="construct:fsa"] {
    --accent: var(--fsa);
}
/* Top-edge spine — the panel's identity, read before any word on it. Fades to
   nothing across the width so it reads as light on the edge rather than as a
   ruled line boxing the panel in. */
.agent-cat-panel::before {
    content: '';
    position: absolute;
    inset: 0 0 auto;
    height: 2px;
    background: linear-gradient(90deg, var(--accent), rgba(255, 255, 255, 0) 78%);
    opacity: 0.85;
    z-index: 0;
}
/* The same accent bled into the top-left corner at very low alpha, so the panel
   is tinted by its lens instead of merely striped by it. opacity on a solid
   gradient, not a mixed colour — one --accent value has to serve both. */
.agent-cat-panel::after {
    content: '';
    position: absolute;
    inset: 0;
    background: radial-gradient(120% 90% at 0% 0%, var(--accent), rgba(255, 255, 255, 0) 62%);
    opacity: 0.1;
    pointer-events: none;
    z-index: 0;
}
.agent-cat-card-head,
.agent-cat-panel-blurb,
.agent-cat-list {
    position: relative;
    z-index: 1;
}
/* What this lens is FOR, in the construct's own authored constraint. The block
   opens by saying the shelf is grouped by constraint; this is the line that
   makes that true on screen. Quiet — it is context for the rows, not a heading
   above them. */
.agent-cat-panel-blurb {
    font-size: 12.5px;
    line-height: 1.55;
    color: rgba(255, 255, 255, 0.52);
    margin-bottom: 10px;
}
.agent-cat-card-head {
    margin-bottom: 10px;
}
.agent-cat-card-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 5px;
}
/* The lens's own short form, in its own colour — the one place the accent
   appears as type. Sized as a marker, not a heading. */
.agent-cat-badge {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--accent);
}
.agent-cat-count {
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.06em;
    color: rgba(255, 255, 255, 0.4);
    /* Right-aligned and last: it answers "how many here?" for a visitor already
       scanning the titles, so it may never be read before one. */
    margin-left: auto;
}
/* The lens name. The one thing on the card allowed to be bigger than the rows,
   because choosing a card is the decision this layout exists to make — and it
   has to win that against four bold agent names underneath it, so the gap to
   the rows is 2.5px and full white, not a half-step. */
.agent-cat-card-title {
    font-size: 15.5px;
    font-weight: 700;
    line-height: 1.3;
    letter-spacing: -0.01em;
    color: var(--white);
}
.agent-cat-list {
    display: flex;
    flex-direction: column;
}
/* A row is a two-line stack, never a baseline pair: inside a card column the
   blurb beside the name would wrap into a ragged block, and the name is what
   the eye is scanning for. Pulled out to the card's edge with negative margin
   so the hover fill reaches the padding rather than floating inside it. */
.agent-cat-row {
    display: block;
    text-decoration: none;
    position: relative;
    padding: 8px 10px 8px 12px;
    margin-inline: -6px;
    border-radius: var(--radius-sm);
    transition: background var(--transition);
}
/* Hairline between rows — enough to separate a stack of four blurbs, far too
   faint to read as a table. An inset shadow rather than a border so it costs no
   layout height and cannot shift the rows it divides. */
.agent-cat-row + .agent-cat-row {
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
/* The hovered row drops its divider: an inset shadow paints OVER the fill, so
   keeping it would leave a line cutting across the top of the highlight. */
.agent-cat-row:hover,
.agent-cat-row:focus-visible {
    background: rgba(255, 255, 255, 0.07);
    box-shadow: none;
}
/* Accent tick on the hovered row — the card's colour confirming which row the
   pointer owns, in the same hue that grouped it. Grows from short to full
   rather than fading in, so the movement points along the row. */
.agent-cat-row::before {
    content: '';
    position: absolute;
    left: 2px;
    top: 10px;
    bottom: 10px;
    width: 2px;
    border-radius: 2px;
    background: var(--accent);
    opacity: 0;
    transform: scaleY(0.45);
    transition: opacity var(--transition), transform var(--transition);
}
.agent-cat-row:hover::before,
.agent-cat-row:focus-visible::before {
    opacity: 0.9;
    transform: none;
}
.agent-cat-name {
    display: block;
    font-size: 13px;
    font-weight: 600;
    line-height: 1.45;
    color: rgba(255, 255, 255, 0.86);
    transition: color var(--transition);
}
.agent-cat-row:hover .agent-cat-name,
.agent-cat-row:focus-visible .agent-cat-name {
    color: var(--white);
}
.agent-cat-liner {
    display: block;
    margin-top: 1px;
    font-size: 12px;
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.5);
    transition: color var(--transition);
}
.agent-cat-row:hover .agent-cat-liner,
.agent-cat-row:focus-visible .agent-cat-liner {
    color: rgba(255, 255, 255, 0.72);
}
/* THE SHELF IS ALL OURS, SO THE BLUE HAS TO HOLD A HIERARCHY.
   Every agent name is a brand term by definition, so highlight() colours the
   whole name — that is the point, and it is what makes the shelf read as our
   vocabulary rather than a list of links. But the row already ranks name over
   blurb by alpha, and a full-strength .tm-term in both would flatten that: the
   12px blurb would shout as loudly as the 13px name above it. So the name takes
   the brand blue, and the quieter lines take it dimmed to roughly their own
   alpha. Weight is inherited in the blurb (it is not a heading) and kept at the
   name's 600 above, so nothing reflows. */
.agent-cat-name .tm-term {
    color: var(--aifl);
    font-weight: inherit;
}
.agent-cat-row:hover .agent-cat-name .tm-term,
.agent-cat-row:focus-visible .agent-cat-name .tm-term {
    color: #8fc0ff;
}
.agent-cat-liner .tm-term,
.agent-cat-panel-blurb .tm-term {
    color: rgba(96, 165, 250, 0.72);
    font-weight: inherit;
}
.agent-cat-row:hover .agent-cat-liner .tm-term,
.agent-cat-row:focus-visible .agent-cat-liner .tm-term {
    color: rgba(143, 192, 255, 0.9);
}
/* The glyph rides the name's alpha, so it brightens with the row instead of
   sitting at a fixed opacity that reads as brighter than the text at rest. */
.agent-cat-name .agent-offer-glyph {
    opacity: 0.5;
    transition: opacity var(--transition);
}
.agent-cat-row:hover .agent-offer-glyph,
.agent-cat-row:focus-visible .agent-offer-glyph {
    opacity: 0.85;
}
.agent-cat-row:focus-visible {
    outline: 2px solid rgba(255, 255, 255, 0.55);
    outline-offset: 1px;
}
/* The "prompt copied" receipt, in the panel whose row was clicked — never the
   block, so a visitor who clicked two lenses can see which one is on their
   clipboard. Aligned to the rows' text edge, under the list it belongs to. */
.agent-cat-panel .agent-offer-copied {
    position: relative;
    z-index: 1;
    margin-top: 2px;
    padding: 0 4px 6px 6px;
}
/* Touch: 44px of thumb per row, bought with padding rather than type size. The
   tabs take the same treatment — a wrapped strip of five is the first thing a
   phone visitor touches, and a 31px pill is a miss waiting to happen. */
@media (pointer: coarse) {
    .agent-cat-row {
        min-height: 44px;
    }
    .agent-cat-tab {
        min-height: 40px;
    }
}
@media (prefers-reduced-motion: reduce) {
    .agent-cat-row::before {
        transition: none;
        transform: none;
    }
}

/* THE TECHNIQUE FAMILY — the method in one breath, then ten editorial groups.
   The surface borrows the catalogue's seated glass and quiet rows, but every
   row is a conversation clicker rather than an external link. */
.block-technique-family {
    margin-top: 4px;
}
.tf-summary {
    font-size: var(--response-body-size);
    line-height: var(--response-body-leading);
    color: rgba(255, 255, 255, 0.82);
    margin-bottom: 18px;
}
.tf-shortlist-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 9px;
}
.tf-shortlist-eyebrow {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgba(199, 182, 255, 0.86);
}
.tf-shortlist-instruction {
    font-size: 11.5px;
    color: rgba(255, 255, 255, 0.42);
}
.tf-shortlist {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 7px;
    margin: 0;
    padding: 0;
}
.tf-technique-card {
    --accent: var(--purple-bright);
    position: relative;
    isolation: isolate;
    display: grid;
    grid-template-columns: 28px minmax(0, 1fr) auto;
    align-items: center;
    gap: 10px;
    min-height: 62px;
    padding: 10px 12px;
    border: 1px solid rgba(255, 255, 255, 0.11);
    border-radius: var(--radius-sm);
    background:
        linear-gradient(105deg, color-mix(in srgb, var(--accent) 9%, transparent), transparent 62%),
        rgba(255, 255, 255, 0.052);
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    box-shadow: 0 8px 24px -18px rgba(12, 10, 30, 0.7);
    transition:
        transform var(--transition),
        background var(--transition),
        border-color var(--transition),
        box-shadow var(--transition);
}
.tf-technique-card::before {
    content: '';
    position: absolute;
    inset: 9px auto 9px 0;
    width: 2px;
    border-radius: 999px;
    background: var(--accent);
    opacity: 0.58;
}
.tf-technique-card:hover,
.tf-technique-card:focus-visible {
    transform: translateY(-1px);
    border-color: color-mix(in srgb, var(--accent) 38%, transparent);
    background:
        linear-gradient(105deg, color-mix(in srgb, var(--accent) 15%, transparent), transparent 68%),
        rgba(255, 255, 255, 0.075);
    box-shadow: 0 12px 28px -18px rgba(12, 10, 30, 0.82);
}
.tf-technique-card:focus-visible {
    outline: 2px solid rgba(255, 255, 255, 0.48);
    outline-offset: 2px;
}
.tf-technique-index {
    align-self: start;
    padding-top: 2px;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.08em;
    color: rgba(255, 255, 255, 0.3);
}
.tf-technique-copy {
    display: grid;
    gap: 3px;
    min-width: 0;
}
.tf-technique-stage {
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: color-mix(in srgb, var(--accent) 80%, white);
}
.tf-technique-label {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 6px;
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1.35;
    color: rgba(255, 255, 255, 0.86);
}
.tf-technique-label small {
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--accent);
}
.tf-technique-action {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 10.5px;
    font-weight: 650;
    color: rgba(255, 255, 255, 0.38);
    transition: color var(--transition), transform var(--transition);
}
.tf-technique-card:hover .tf-technique-action,
.tf-technique-card:focus-visible .tf-technique-action {
    color: rgba(255, 255, 255, 0.82);
    transform: translateX(2px);
}
@media (max-width: 720px) {
    .tf-shortlist {
        grid-template-columns: 1fr;
    }
}
@media (max-width: 480px) {
    .tf-shortlist-head {
        align-items: flex-start;
        flex-direction: column;
        gap: 3px;
    }
    .tf-technique-card {
        grid-template-columns: 25px minmax(0, 1fr) auto;
    }
    .tf-technique-action {
        font-size: 0;
    }
    .tf-technique-action span {
        font-size: 14px;
    }
}
