/* THE ONE CARD (Steven, COO hands 2026-10-12; card redesign plan 10a).
   Styles for templates/cards/_card.html; flip in static/cards/card.js.
   Inline by default; .tb-card--full fills the screen under the header
   (Steven's screenshot 31): art on top with the title over it, a white panel
   with one big button, "Details · Tap card to flip", rounded corners, no
   ring around it (Steven 2026-10-14 ~14:40: "on the card I want to remove
   the green blue gradient around the outside"). .tb-card-deck pages full
   cards one per screen.

   Knobs: --tb-card-full-h (the full card's height), --tb-card-top (the
   header's height, default 64px), --tb-card-radius. */

.tb-card {
    --tb-card-radius: var(--radius-hero);
    /* the old ring's gradient: the card no longer wears it; the Toll Bench
       page's own cards (css/pages/toll-bench.css .tbx-card) still read it */
    --tb-card-ring: linear-gradient(160deg, var(--color-cyan-400) 0%, var(--tb-brand-purple-hover) 32%, var(--tb-brand-purple-hover) 50%, var(--accent-neon) 78%, var(--color-yellow-400) 100%);
    --tb-card-night: radial-gradient(ellipse 90% 60% at 50% 62%, var(--color-dark-500) 0%, var(--color-dark-600) 42%, var(--color-dark-800) 78%, var(--color-dark-900) 100%);
    --tb-card-green: var(--accent-neon);
    --tb-card-purple: var(--highlight-purple);
    --tb-card-yellow: var(--color-yellow-400);
    position: relative;
    display: block;
    width: 100%;
    color: var(--text-primary);
    /* NO RING, NO GLOW (Steven 2026-10-14 ~14:40, the card's cyan to
       purple to green ring and its glow beside his flat mock: "on the card
       I want to remove the green blue gradient around the outside"): the
       frame is the faces' own corner, nothing drawn around it, a plain
       drop shadow from the tokens; each face keeps its own radius and
       clips its art (.tb-card__face). */
    padding: 0;
    border-radius: var(--tb-card-radius);
    background: none;
    box-shadow: var(--shadow-lg);
    -webkit-tap-highlight-color: transparent;
}
/* THE CARD KEEPS ITS OWN FACES, wherever it is drawn (one card: the deck
   and the step page, Steven 2026-10-13 night). The step page draws it
   inside .boh-interface, whose standards (css/components/interface-
   standards.css, 2026-09-08) point every font token at the system face and
   put var(--interface-font) on every element at 0,2,1, which outranks the
   card's own faces below. So the card points the tokens back at their
   :root values (as the sheet language does, step-cards.css .sl-sheet:
   --auth-title-font the heading face, --topbar-pill-font the mono,
   --font-edit the serif) and hands the standards' own variable the face
   each part asks for: the body face here, and beside every font-family in
   the card's files the same face (--interface-font), so the standards'
   rule draws the card's faces. Inside .boh-interface the card also takes
   the page's base size and leading again (the standards set 15px and 1.55
   on the page). Off .boh-interface every value is what it was. */
.tb-card {
    --font-body: var(--font-sans);
    --font-heading: var(--auth-title-font);
    --font-serif: var(--font-edit);
    --font-mono: var(--topbar-pill-font);
    --interface-font: var(--font-body);
}
.boh-interface .tb-card { font-size: var(--text-base); line-height: var(--leading-normal); }
/* The full card is at least the screen (--tb-card-full-h) and grows when
   its words need more: the art never squeezes the title down onto the white
   panel (the long-title overlap, COO hands 2026-10-12). The chart gives up
   its height first (.tb-card--full .tb-card__chart below); only then does
   the card get taller. */
.tb-card--full {
    display: flex;
    flex-direction: column;
    min-height: 480px;
}
.tb-card--full > .tb-card__inner {
    flex: 1 0 auto;
    height: auto;
    min-height: var(--tb-card-full-h, calc(100svh - var(--tb-card-top, var(--size-16)) - var(--size-4)));
}

/* faces stack in one grid cell: the card is as tall as its taller face */
.tb-card__inner {
    display: grid;
    height: 100%;
    border-radius: var(--tb-card-radius);
    transition: transform 0.6s cubic-bezier(.2, .7, .2, 1);
}
.tb-card.is-3d { perspective: 1600px; }
.tb-card.is-3d .tb-card__inner { transform-style: preserve-3d; }
.tb-card.is-flipped .tb-card__inner { transform: rotateY(180deg); }
.tb-card__face {
    grid-area: 1 / 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
    border-radius: var(--tb-card-radius);
    overflow: hidden;
    background: var(--surface-primary);
}
.tb-card.is-3d .tb-card__face { backface-visibility: hidden; -webkit-backface-visibility: hidden; }
.tb-card__back { transform: rotateY(180deg); visibility: hidden; }
.tb-card.is-3d .tb-card__back,
.tb-card.is-flipped .tb-card__back { visibility: visible; }
.tb-card.is-flipped:not(.is-3d) .tb-card__front { visibility: hidden; }

/* ---- the art ------------------------------------------------------- */
.tb-card__art {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    min-height: 260px;
    padding: var(--space-5);
    background: var(--tb-card-night);
    color: var(--text-inverse);
    isolation: isolate;
}
.tb-card--full .tb-card__art { flex: 1 1 auto; min-height: 0; container-type: inline-size; }
/* the back scrolls inside the card; it never makes the card taller than the
   front needs. Its scroller is a child (the Proposals rows, or the agent
   card's page), so the foot under it stays put. */
.tb-card--full .tb-card__back { contain: size; overflow: hidden; }
/* THE WHOLE AGENT PAGE ON THE BACK (Steven 2026-10-13, the fourth time:
   "Inside this card container you can scroll to see ALL of the information
   for the agent ... the card stays, but it scrolls"). Every card whose back
   is the agent (THE agent card, cards/_agent_side.html, its scroller
   .tb-side__scroll in static/cards/agent-side.css) or the Proposals rows,
   full or inline, keeps the front's box: the page scrolls inside and "Tap
   card to flip back" stays pinned under it, outside the scroller. */
.tb-card__back--agent,
.tb-card__back--proposals { contain: size; overflow: hidden; }
.tb-card__backscroll {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior-y: contain;
    -webkit-overflow-scrolling: touch;
}
.tb-card__bg, .tb-card__img {
    position: absolute;
    inset: 0;
    z-index: -2;
    width: 100%;
    height: 100%;
}
.tb-card__img { object-fit: cover; }
.tb-card__bg { overflow: hidden; background: var(--tb-card-night); }
/* the agent visual draws "meet": overfill so no band shows at the edges */
.tb-card__bg svg { display: block; width: 100%; height: 100%; transform: scale(1.18); }
.tb-card__bg .agent-art { width: 100%; height: 100%; }
.tb-card__stars {
    position: absolute;
    inset: 0;
    background:
        radial-gradient(1px 1px at 12% 18%, rgb(255 255 255 / 0.53) 50%, transparent 51%),
        radial-gradient(1px 1px at 72% 12%, rgb(255 255 255 / 0.6) 50%, transparent 51%),
        radial-gradient(1.5px 1.5px at 38% 34%, rgb(255 255 255 / 0.47) 50%, transparent 51%),
        radial-gradient(1px 1px at 86% 40%, rgb(255 255 255 / 0.53) 50%, transparent 51%),
        radial-gradient(1px 1px at 22% 58%, rgb(255 255 255 / 0.4) 50%, transparent 51%),
        radial-gradient(1.5px 1.5px at 64% 26%, rgb(255 255 255 / 0.67) 50%, transparent 51%),
        radial-gradient(1px 1px at 52% 8%, rgb(255 255 255 / 0.47) 50%, transparent 51%);
}
.tb-card__shade {
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(180deg, transparent 45%, color-mix(in srgb, var(--color-dark-900) 72%, transparent) 100%);
    pointer-events: none;
}
.tb-card__top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); }
.tb-card__topright { display: inline-flex; align-items: flex-start; gap: var(--space-2); }
.tb-card__share {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--size-10);
    height: var(--size-10);
    padding: 0;
    border: 1px solid rgb(255 255 255 / 0.28);
    border-radius: 50%;
    background: color-mix(in srgb, var(--color-dark-900) 45%, transparent);
    color: var(--text-inverse);
    font-size: var(--text-xl);
    cursor: pointer;
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
}
.tb-card__share[data-copied]::after {
    content: attr(data-copied);
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-sm);
    background: var(--surface-primary);
    color: var(--color-gray-950);
    font-size: var(--text-sm);
    font-weight: 600;
    white-space: nowrap;
}
.tb-card__kicker { display: inline-flex; align-items: center; gap: var(--space-3); }
.tb-card__num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    border: 2px solid rgb(255 255 255 / 0.35);
    background: rgb(255 255 255 / 0.08);
    font-weight: 600;
}
.tb-card__label {
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-sm);
    background: var(--tb-card-yellow);
    color: var(--color-gray-950);
    font-family: var(--font-mono);
    --interface-font: var(--font-mono);
    font-size: var(--text-base);
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
}
/* YOUR TURN IS THE GREEN PILL (Steven 2026-10-13 night: "YOUR TURN needs
   to be in a green pill"): the person's kicker wears the green the button
   wears, black mono caps, on the deck and the step page alike (one card).
   The agent's and the gathering kicker are purple, a done want's dark. */
.tb-card__kicker--you .tb-card__label { background: var(--tb-card-green); color: var(--color-black); }
.tb-card__kicker--agent .tb-card__label { background: var(--tb-card-purple); color: var(--text-inverse); }
.tb-card__kicker--done .tb-card__label { background: var(--surface-primary); color: var(--color-gray-950); }
/* THE KICKER IN THE WHITE PANEL (Steven 2026-10-13 night: the kicker
   leaves the art): over the step's heading, its number ring in the panel's
   ink, a done want's label dark on the white */
.tb-card__kickrow { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.tb-card__panel .tb-card__num {
    border-color: var(--border-default);
    background: var(--surface-secondary);
    color: var(--text-primary);
}
.tb-card__panel .tb-card__kicker--done .tb-card__label { background: var(--color-gray-950); color: var(--text-inverse); }
/* DELIVERED IS THE SUCCESS TONE (Steven 2026-10-14 ~14:50: "the card should
   be complete and should be a success. Do we have a success card?"): a
   delivered want's chip, on its front's panel and over the agent's name on
   its finish line back, wears the neon green with its check, never the dim
   done dark an ended want keeps (home_cards.success_card). */
.tb-card__kicker--success .tb-card__label,
.tb-card__panel .tb-card__kicker--success .tb-card__label {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    background: var(--tb-card-green);
    color: var(--color-black);
}
.tb-card__kicker--success .tb-card__label iconify-icon { font-size: var(--text-lg); }
/* the success card's record: who delivered, the money, the day, one line
   under the delivered piece */
.tb-card__delivered {
    margin: 0;
    color: var(--text-secondary);
    font-size: var(--text-base);
    line-height: var(--leading-snug);
}
.tb-card__delivered strong { color: var(--text-primary); font-weight: 700; }
/* THE MINUTES DISC (Steven 2026-10-14 ~15:25, his shot of a deck card's
   top right corner, the "15 min" yellow ring with its glow beside the three
   dots: "Make the 15 minutes the same size as the circle with the three
   dots, put it on the side below it with the three dots, get rid of the
   yellow outer glow, make the 15 yellow, and then it should look like just
   two dots down the side."): the three dots' own round (THE THREE DOTS,
   .tb-card__menubtn), its size and its quiet glass, no ring and no glow;
   the minutes in the brand yellow, the unit tiny under them in the same
   yellow. In the art's head it rides the corner column under the dots
   (THE CORNER, after THE THREE DOTS below). */
.tb-card__badge {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: var(--size-10);
    height: var(--size-10);
    border-radius: var(--radius-full);
    background: color-mix(in srgb, var(--color-dark-900) 38%, transparent);
    color: var(--tb-card-yellow);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    line-height: 1;
}
.tb-card__badge b { font-family: var(--font-heading); --interface-font: var(--font-heading); font-size: var(--text-base); }
.tb-card__badge small { font-family: var(--font-mono); --interface-font: var(--font-mono); font-size: calc(var(--text-xs) * 0.8); letter-spacing: 0.06em; }
/* a range ("10-15") steps down so it stays inside the round */
.tb-card__badge--long b { font-size: var(--text-xs); letter-spacing: -0.02em; }

.tb-card__over { display: flex; flex-direction: column; gap: var(--space-2); margin-top: auto; }

/* ---- THE WANT CARD'S FRONT (Steven 2026-10-13 night, confirmed after a
   read-back) ----------------------------------------------------------------
   (1) the title and its words at the TOP of the art (.tb-card__head), under
   a soft fade from the picture's top edge, never a box behind the words;
   (2) the middle of the picture stays clear; (3) the probability block (the
   number, the move, the band, the caption, the line, the three markers) at
   the FOOT of the art (.tb-card__over), just above the white panel, a fade
   below it so it reads; (4) the kicker in the white panel
   (.tb-card__kickrow) and (5) the share button in the foot
   (.tb-card__share--foot). The same on the want as the back of an agent's
   card. */
.tb-card__head {
    position: relative;
    flex: none;
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
}
.tb-card__headwords {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}
.tb-card .tb-card__head .tb-card__title { margin: 0; }
.tb-card__head .tb-card__badge { flex: none; }
/* the fade from the picture's top edge for the words, the middle clear,
   the fade below for the odds (the number's own shade deepens it) */
.tb-card--want .tb-card__shade {
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--color-dark-900) 62%, transparent) 0%,
        color-mix(in srgb, var(--color-dark-900) 30%, transparent) 18%,
        transparent 34%,
        transparent 54%,
        color-mix(in srgb, var(--color-dark-900) 72%, transparent) 100%);
}
.tb-card__title {
    margin: var(--space-2) 0 0;
    font-family: var(--font-heading);
    --interface-font: var(--font-heading);
    font-size: clamp(var(--text-2xl), 7.4vw, var(--text-4xl));
    font-weight: 800;
    line-height: 1.08;
    letter-spacing: -0.02em;
    overflow-wrap: anywhere;
    text-shadow: 0 2px 16px rgb(0 0 0 / 0.4);
    /* in the flow under the chart, three lines at most, then an ellipsis */
    flex: none;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    overflow: hidden;
}
.tb-card__subtitle { margin: 0; color: rgb(255 255 255 / 0.82); font-size: var(--text-base); }

/* the want's odds and chart, over the art */
.tb-card__odds { display: flex; align-items: center; gap: var(--space-2) var(--space-3); flex-wrap: wrap; }
.tb-card__number {
    flex: none;
    font-family: var(--font-heading);
    --interface-font: var(--font-heading);
    font-size: clamp(var(--size-10), 12vw, var(--text-5xl));
    font-weight: 800;
    line-height: 1;
    letter-spacing: -0.04em;
    white-space: nowrap;
}
.tb-card__number--long { font-size: var(--text-4xl); white-space: normal; }
/* THE BUDGET UNDER THE NUMBER (Steven 2026-10-14: "I think we need to add
   the budget under the number, so I can see what it is"): the number and
   its one quiet line stacked, in the caption's type ("Probability of
   success"). The move, the band and the caption sit beside them while
   there is room for them (the side's least width), else under them: a
   long number ("1 in 320,000") pushed the move off the card's edge. */
.tb-card__numcol { flex: none; display: inline-flex; flex-direction: column; align-items: flex-start; gap: var(--space-1); min-width: 0; }
.tb-card__numcol--long { flex: 1 1 100%; }
.tb-card__budget { color: color-mix(in srgb, var(--text-inverse) 80%, transparent); font-size: var(--text-base); line-height: var(--leading-snug); white-space: nowrap; }
.tb-card__oddsside { display: inline-flex; flex: 1 1 0; flex-direction: column; align-items: flex-start; gap: var(--space-1); min-width: min(100%, calc(var(--size-32) + var(--size-10))); }
.tb-card__caption { color: rgb(255 255 255 / 0.8); font-size: var(--text-base); }
/* THE MOVE, ONE LINE: "↗ 3.0 pts", no date under it (Steven 2026-10-14
   ~14:30: "can you please remove the 'since [date]' there"). The colours
   stay the move's own (green up, red down). */
.tb-card__move {
    display: inline-flex;
    align-items: center;
    gap: 0.3em;
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-sm);
    font-family: var(--font-mono);
    --interface-font: var(--font-mono);
    font-size: var(--text-sm);
    font-weight: 700;
    white-space: nowrap;
}
/* the move and the band chip side by side, beside the number */
.tb-card__chips { display: inline-flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); }
/* THE BAND (Steven 2026-10-13: "it needs to have the band"): Easy / Hard /
   Moonshot, the chip's own colours (wants.css .target-chart__band), shaped
   like the move beside it */
.tb-card__band {
    display: inline-flex;
    align-items: center;
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-sm);
    font-family: var(--font-mono);
    --interface-font: var(--font-mono);
    font-size: var(--text-sm);
    font-weight: 700;
    white-space: nowrap;
}
/* THE BAND'S COLOURS ARE THE BRAND'S (Steven 2026-10-13: "Eek, the pill is
   the wrong green! And Moonshot should be the neon blue from the brand"):
   Easy the neon green of the card's button and its up move (--accent-neon),
   Moonshot the brand's neon blue (--cyan), Hard the brand yellow, the
   header's and the certification badge's --color-yellow-400 (Steven
   2026-10-13 evening: "the colour of Hard should be our brand yellow, not
   that odd blue"; --status-warning is that blue, #0112f7), all three with
   black words. The same tokens on the interior card (wants.css
   .target-chart__band) and the /start card (start-home.css
   .probability-card__band), so the chip never differs between them; the
   visitor deck's bands card draws this chip. */
.tb-card__band--easy { background: var(--accent-neon); color: var(--color-black); }
.tb-card__band--hard { background: var(--color-yellow-400); color: var(--color-black); }
.tb-card__band--moonshot { background: var(--cyan); color: var(--color-black); }
.tb-card__move--up { background: var(--tb-card-green); color: var(--color-black); }
.tb-card__move--down { background: var(--status-error); color: var(--text-inverse); }
.tb-card__move--flat { background: rgb(255 255 255 / 0.14); color: var(--text-inverse); }
.tb-card__chart { display: block; width: 100%; height: auto; max-height: 34vh; overflow: visible; }
/* full card: the chart starts small and grows into the room left over, up to
   its own shape (640x210 across the art's width less its padding), so a
   long title takes the chart's room before the card has to grow */
.tb-card--full .tb-card__over { flex: 1 1 auto; justify-content: flex-end; }
.tb-card--full .tb-card__over > * { flex: none; }
.tb-card--full .tb-card__over > .tb-card__chart {
    flex: 1 1 64px;
    min-height: 64px;
    max-height: min(34vh, calc((100cqi - 2 * var(--space-5)) * 0.33));
}
.tb-chart__grid { stroke: rgb(255 255 255 / 0.12); stroke-width: 2; }
.tb-chart__line { fill: none; stroke: var(--tb-card-green); stroke-width: 6; stroke-linecap: round; stroke-linejoin: round; filter: drop-shadow(0 0 6px color-mix(in srgb, var(--tb-card-green) 60%, transparent)); }
.tb-chart__ahead { fill: none; stroke: rgb(255 255 255 / 0.55); stroke-width: 4; stroke-dasharray: 2 9; stroke-linecap: round; }
.tb-chart__now { fill: var(--color-dark-700); stroke: var(--tb-card-green); stroke-width: 5; }
.tb-chart__target { fill: var(--color-dark-700); stroke: var(--tb-card-yellow); stroke-width: 4; }
.tb-chart__fail { stroke: var(--status-error); stroke-width: 4; stroke-linecap: round; }
/* WORDS ON THE DOTS (Steven 2026-10-14: "don't we have it set up that there
   is text on each dot, like what the thoughts were on that step?"): every
   point a small dot on the line (the last the now ring, an ended attempt
   its X), each in a hit area larger than its mark; the tapped one grows. */
.tb-chart__pt { cursor: pointer; outline: none; }
.tb-chart__hit { fill: transparent; stroke: none; pointer-events: all; }
.tb-chart__dot { fill: var(--color-dark-700); stroke: var(--tb-card-green); stroke-width: 4; }
.tb-chart__pt .tb-chart__dot,
.tb-chart__pt .tb-chart__now {
    transform-box: fill-box;
    transform-origin: center;
    transition: transform var(--duration-fast) var(--ease-default);
}
.tb-chart__pt.is-on .tb-chart__dot,
.tb-chart__pt.is-on .tb-chart__now { transform: scale(1.5); }
.tb-chart__pt:focus-visible .tb-chart__hit { stroke: var(--text-inverse); stroke-width: 2; stroke-dasharray: 3 5; }
@media (prefers-reduced-motion: reduce) {
    .tb-chart__pt .tb-chart__dot,
    .tb-chart__pt .tb-chart__now { transition: none; }
}
.tb-card__markers {
    position: relative;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: var(--space-2);
    font-size: var(--text-sm);
    line-height: 1.3;
    color: rgb(255 255 255 / 0.78);
}
.tb-card__markers strong { color: var(--text-inverse); }
.tb-card__markers > :nth-child(2) { text-align: center; }
.tb-card__markers > :nth-child(3) { text-align: right; }
/* the tapped dot's words in the markers' place, the markers held still
   under them (no jump), up to three lines rising over the chart's foot;
   taps go through them to the dots below */
.tb-card__markers.is-noting > :not(.tb-card__dotnote) { visibility: hidden; }
.tb-card__dotnote {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    margin: 0;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    background: color-mix(in srgb, var(--color-dark-900) 84%, transparent);
    color: color-mix(in srgb, var(--text-inverse) 86%, transparent);
    font-size: var(--text-sm);
    line-height: var(--leading-snug);
    text-align: left;
    pointer-events: none;
}
.tb-card__dotnote[hidden] { display: none; }
.tb-card__dotwords {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    overflow: hidden;
}

/* ---- the white panel ----------------------------------------------- */
.tb-card__panel {
    flex: none;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-5) var(--space-5) var(--space-3);
    background: var(--surface-primary);
}
.tb-card__heading {
    margin: 0;
    font-family: var(--font-heading);
    --interface-font: var(--font-heading);
    font-size: var(--text-2xl);
    font-weight: 800;
    line-height: 1.15;
    letter-spacing: -0.015em;
}
.tb-card__heading--sm { font-size: var(--text-lg); }
.tb-card__body { margin: 0; color: var(--text-secondary); font-size: var(--text-lg); line-height: 1.45; }
/* THE WORDS SCROLL IN PLACE (Steven 2026-10-14, his phone shot of the
   proposal card "Select Luca", Luca's pitch cut at "... send the" with no
   ellipsis: "is there a max amount of text, or can the text scroll in that
   spot?"). The panel's body sits in its own scroller ([data-tb-card-
   bodyscroll], cards/_card.html). A full offer card (the proposal card, the
   market's offer card, the agent page's card) keeps its one screen: the
   picture keeps its floor (its own words), the odds row, the green button
   and the foot always show, and the words take the room left, never less
   than three lines, scrolling in place: touch, momentum, no scrollbar on a
   phone. While more words wait below, the bottom edge fades (data-more,
   card.js); scrolled to the end, no fade. The whole text is reachable, and
   no line is ever cut without the fade over it. A spot that clamps its
   words on purpose with an ellipsis (.hc-slide, .pdpc) keeps its clamp:
   its words never overflow, so there is no fade there. A swipe in the
   words scrolls them, never the deck under the card (overscroll-behavior)
   or the next plan (proposal-cards.js). */
.tb-card--offer.tb-card--full > :where(.tb-card__inner:has(.tb-card__bodyscroll)) {
    height: var(--tb-card-full-h, calc(100svh - var(--tb-card-top, var(--size-16)) - var(--size-4)));
    grid-template-rows: minmax(0, 1fr);
}
.tb-card--offer.tb-card--full .tb-card__panel:has(> .tb-card__bodyscroll) { flex: 0 1 auto; min-height: 0; }
.tb-card--offer.tb-card--full .tb-card__panel:has(> .tb-card__bodyscroll) > :not(.tb-card__bodyscroll) { flex: none; }
.tb-card--offer.tb-card--full .tb-card__bodyscroll {
    flex: 0 1 auto;
    min-height: 4.5em;
    margin-right: calc(-1 * var(--space-2));
    padding-right: var(--space-2);
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior-y: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.tb-card--offer.tb-card--full .tb-card__bodyscroll::-webkit-scrollbar { display: none; }
@media (hover: hover) and (pointer: fine) {
    .tb-card--offer.tb-card--full .tb-card__bodyscroll { scrollbar-width: thin; }
    .tb-card--offer.tb-card--full .tb-card__bodyscroll::-webkit-scrollbar { display: initial; }
}
.tb-card__bodyscroll[data-more] {
    -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 3.25em), transparent);
    mask-image: linear-gradient(to bottom, #000 calc(100% - 3.25em), transparent);
}
.tb-card__facts { display: flex; align-items: baseline; gap: var(--space-2); margin: 0; }
.tb-card__factlabel { color: var(--text-secondary); margin-right: auto; }
.tb-card__pct { color: var(--tb-card-purple); font-family: var(--font-heading); --interface-font: var(--font-heading); font-size: var(--text-4xl); font-weight: 800; line-height: 1; }
.tb-card__pct small { font-size: 0.55em; }
.tb-card__pct--odds { font-size: var(--text-base); }
.tb-card__price { font-weight: 800; font-size: var(--text-lg); }
.tb-card__dashes { display: flex; gap: var(--space-2); }
.tb-card__dashes span { flex: 1; height: 6px; border-radius: var(--radius-xs); background: var(--border-default); }
.tb-card__dashes span.is-done { background: var(--tb-card-green); }
.tb-card__cta {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 60px;
    padding: 0 var(--space-5);
    border-radius: var(--radius-full);
    background: var(--tb-card-green);
    color: var(--color-gray-800);
    font-family: var(--font-heading);
    --interface-font: var(--font-heading);
    font-size: var(--text-xl);
    font-weight: 800;
    text-align: center;
    text-decoration: none;
}
.tb-card__cta--quiet { background: var(--tb-card-purple); color: var(--text-inverse); min-height: 52px; font-size: var(--text-lg); }
.tb-card__foot {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-1) 0 var(--space-2);
    color: var(--text-secondary);
    font-size: var(--text-base);
}
.tb-card__back > .tb-card__foot { flex: none; margin-top: auto; padding: var(--space-3) 0; background: var(--surface-primary); }
.tb-card__back--agent > .tb-card__foot { border-top: 1px solid var(--border-default); }
.tb-card__details, .tb-card__fliptap {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-1);
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-decoration: none;
    cursor: pointer;
}

/* ---- the back: Proposals (a want while agents bid) ------------------ */
/* Steven 2026-10-13 night: "the back of a want card while agents bid is
   Proposals": the proposal rows (cards/_proposal_row.html, their look in
   static/cards/agents-now.css .pcards) scrolling inside the card on its
   white sheet, the card staying put, the foot pinned under them. The old
   "Agents on this" list with its letter discs is gone. */
.tb-card__back--proposals .tb-card__backscroll {
    gap: var(--space-3);
    padding: var(--space-5) var(--space-4) var(--space-4);
}
.tb-card__backtitle { margin: 0 var(--space-1); font-family: var(--font-heading); --interface-font: var(--font-heading); font-size: var(--text-2xl); font-weight: 800; }
.tb-card__none { margin: 0 var(--space-1); color: var(--text-secondary); }

/* ---- the cover wears the want's picture (Steven 2026-10-13: "The cover
   should have the image on it"; then "I wanted the percentages, the changes
   and all that on the card. Why can't they be there?") ------------------
   The want's Flux picture is the art behind the whole front, cover-cropped
   a little above its middle, under the shade below; the number, the move,
   the band, the chart and its markers draw over it exactly as over the
   starfield. The step page draws this same card (one card), so these are
   its picture's rules too. From the number down
   the shade deepens to the starfield's own night (the odds' ::before,
   anchored on the number wherever the title's length puts it), so the
   number and the line read on any picture; above the number the picture
   stays bright. The art clips that shade at its own edge, never over the
   white panel. */
.tb-card--want .tb-card__art--image { overflow: hidden; }
.tb-card--want .tb-card__art--image .tb-card__img { object-position: center 35%; }
.tb-card--want .tb-card__art--image .tb-card__shade {
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--color-dark-900) 66%, transparent) 0%,
        color-mix(in srgb, var(--color-dark-900) 34%, transparent) 18%,
        transparent 34%,
        transparent 54%,
        color-mix(in srgb, var(--color-dark-900) 72%, transparent) 78%,
        color-mix(in srgb, var(--color-dark-900) 94%, transparent) 100%);
}
.tb-card--want .tb-card__art--image .tb-card__title,
.tb-card--want .tb-card__art--image .tb-card__head .tb-card__subtitle { text-shadow: 0 1px 14px rgb(0 0 0 / 0.5); }
.tb-card--want .tb-card__art--image .tb-card__odds { position: relative; }
.tb-card--want .tb-card__art--image .tb-card__odds::before {
    content: '';
    position: absolute;
    z-index: -1;
    top: -64px;
    left: calc(-1 * var(--space-5));
    right: calc(-1 * var(--space-5));
    height: 1600px;
    background: linear-gradient(180deg,
        transparent 0,
        color-mix(in srgb, var(--color-dark-900) 62%, transparent) 64px,
        color-mix(in srgb, var(--color-dark-900) 74%, transparent) 240px,
        color-mix(in srgb, var(--color-dark-900) 90%, transparent) 440px);
    pointer-events: none;
}
.tb-card--want .tb-card__art--image .tb-card__number,
.tb-card--want .tb-card__art--image .tb-card__caption,
.tb-card--want .tb-card__art--image .tb-card__budget,
.tb-card--want .tb-card__art--image .tb-card__markers { text-shadow: 0 1px 12px rgb(0 0 0 / 0.45); }
.tb-card--want .tb-card__art--image .tb-card__dotnote { text-shadow: none; }

/* THE certification badge top left of a certified offer
   (components/_certified_badge.html, certified-badge.css), where a kicker
   would sit */
.tb-card__cert { display: inline-flex; min-width: 0; max-width: 100%; }

/* the kicker, a link on a your-turn card (the step page): its own colours */
.tb-card a.tb-card__kicker,
.tb-card a.tb-card__kicker:hover,
.tb-card a.tb-card__kicker:focus-visible { color: inherit; text-decoration: none; }

/* ---- the record grid and a list (the agent page's front record, the
   /home deck's Details sheet's "Your agent"). The agent card itself, the
   back of every card that shows an agent, is the one dark card
   (cards/_agent_side.html, static/cards/agent-side.css): the light
   profile that stood here is deleted (Steven 2026-10-13 night: "one agent
   card, always dark"). ------------------------------------------------- */
.tb-card__record { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-2); margin: 0; }
.tb-card__record div { padding: var(--space-2); border-radius: var(--radius-lg); background: var(--surface-secondary); text-align: center; }
.tb-card__record dt { color: var(--text-secondary); font-size: var(--text-xs); }
.tb-card__record dd { margin: 0; font-family: var(--font-heading); --interface-font: var(--font-heading); font-size: var(--text-xl); font-weight: 800; }
.tb-card__gives { margin: 0; padding-left: 1.1em; color: var(--text-secondary); font-size: var(--text-base); line-height: 1.45; }
/* the maker's mark before a model line (the agent page's front by line) */
.tb-card__mark { flex: none; width: 1em; height: 1em; font-size: 1em; color: currentColor; }

/* THE PROPOSAL CARD'S PICTURE (Steven 2026-10-13 night: "a picture for the
   proposal as the art ... never the green starfield"): the want's Flux
   picture, else the agent's tall pose still, cropped from its top so the
   face stays whole (proposal_cards.front_art; .tb-card__art--pose). */
.tb-card__art--pose .tb-card__img,
.tb-card__art--photo .tb-card__img { object-position: 50% 0; }

/* THE AGENT ON AN OFFER'S FRONT (Steven 2026-10-13: "On every one of these
   cards there needs to be the agent on the front, with that motion. Beside
   'Make Comics / By Kai' there should be a circle"): the round the /start
   rows draw (static/cards/agents-available.css .tb-avail__art: the square
   cut playing, zoomed on the face, no ring). Then (Steven 2026-10-13 night:
   "Nia has got to be double that size, and the top aligned with the top of
   the title"): twice the old 40px round, --size-20, to the LEFT of the
   title and its by line, its top on the title's top; the title and "By
   Nia" stack to its right (.tb-card__bystack), the title keeping its
   three-line clamp. The row's top margin is the title's own, so the title
   sits where it did, now beside the round. "The top of the title" is the
   top of its capitals: text-box trims the line's room above the cap height
   (the round's top and the letters' top were 6px apart at 390), and a
   --space-2 of padding, pulled back up by the same margin, keeps an accent
   (the stroke over an E) inside the clamp's clip. Where text-box is not
   supported the title's line box top is on the round's top. */
.tb-card__byline {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    margin-top: var(--space-2);
}
.tb-card__bystack {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}
.tb-card .tb-card__byline .tb-card__title {
    margin: calc(-1 * var(--space-2)) 0 0;
    padding-top: var(--space-2);
    text-box: trim-start cap alphabetic;
}
.tb-card__round {
    position: relative;
    flex: none;
    width: var(--size-20);
    height: var(--size-20);
    border-radius: var(--radius-full);
    overflow: hidden;
    background: var(--tb-card-night);
}
.tb-card__round > .aa,
.tb-card__round > .aa-pose,
.tb-card__round > .tb-avail__photo { display: block; width: 100%; height: 100%; object-fit: cover; }
.tb-card__round .aa-pose__media,
.tb-card__round .aa-pose__still { object-position: 50% 0; transform: scale(1.45); transform-origin: 50% 30%; }
.tb-card__bytext {
    min-width: 0;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
}

/* THE PROOF LINE on an offer's white panel (Steven 2026-10-13: "1 person
   helped" carries the certification with it): the badge and the people
   helped on one line, the card's share button beside it, small, on the
   right (off the picture: a popped card's X takes the top right). */
.tb-card__proof { display: flex; align-items: center; gap: var(--space-2); min-height: var(--size-8); }
.tb-card__proofline { margin: 0; min-width: 0; color: var(--text-secondary); font-size: var(--text-sm); font-weight: 700; }
.tb-card .tb-card__share--panel {
    flex: none;
    margin-left: auto;
    width: var(--size-8);
    height: var(--size-8);
    border: 1px solid var(--border-default);
    background: var(--surface-secondary);
    color: var(--text-secondary);
    font-size: var(--text-base);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}
.tb-card .tb-card__share--panel[data-copied]::after { border: 1px solid var(--border-default); }
/* A want card's share in its foot (Steven 2026-10-13 night: "small and
   quiet, icon only"): the foot's own ink, no ring, no glass */
.tb-card .tb-card__share--foot {
    flex: none;
    width: var(--size-8);
    height: var(--size-8);
    border: 0;
    background: none;
    color: inherit;
    font-size: var(--text-lg);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}
.tb-card .tb-card__share--foot[data-copied]::after { top: auto; bottom: calc(100% + var(--space-1)); border: 1px solid var(--border-default); }

/* ---- the agent's side (Steven 2026-10-13: "When I do the thing, the card
   needs to flip over and go to 'agent working now'"; that night: "it should
   flip to the agent page, the actual agent working page, and that should be
   the darker one") ----------------------------------------------------
   A want card's dark agent side, on its front while the want waits on an
   agent and on the back of the person's turn, is the one implementation in
   templates/cards/_agent_side.html and static/cards/agent-side.css (the
   step page's card draws it too). Here only its kicker on a back: the
   step's number on dark glass ("2  AGENT"; home-cards.js renames it when
   it turns the card over to the working state). */
.tb-card__back .tb-card__num {
    background: color-mix(in srgb, var(--color-dark-900) 45%, transparent);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    color: var(--text-inverse);
}
.tb-card__back .tb-card__num[hidden] { display: none; }
/* the want as the back of an agent's-turn card: its art fills the face
   above the foot */
.tb-card__back--want > .tb-card__art { flex: 1 1 auto; min-height: 0; }

/* ---- room for the fail dot ------------------------------------------ */
/* THE DOT STANDS STILL (the dot lane, 6ba809e5a: bottom 24px, right 20px,
   52px round, static/css/components/fail-dot.css, over every popup), so on
   a page that carries it a full card keeps its foot ("Details · Tap card to
   flip") and its one button clear of the dot's corner: nothing tappable
   sits under it. --tb-dot-room is the room fail-dot.css gives a sheet's
   bottom row, set once: the dot, its gap from the edge and a step more.
   The button keeps the panel's own inset on its right, so it stops that
   much short of the room's edge (at 390 wide its right edge is left of
   x 318, the dot's left edge). */
.tb-card { --tb-dot-room: calc(var(--size-12) + var(--space-1) + var(--space-5) + var(--space-2)); }
body:has(.fail-dot) .tb-card--full .tb-card__face > .tb-card__foot { padding-right: var(--tb-dot-room); }
body:has(.fail-dot) .tb-card--full .tb-card__panel > .tb-card__foot,
body:has(.fail-dot) .tb-card--full .tb-card__panel > .tb-card__cta { margin-right: calc(var(--tb-dot-room) - var(--space-5)); }
body:has(.fail-dot) .tb-card--full .tb-card__foot :is(.tb-card__details, .tb-card__fliptap) { white-space: nowrap; }
/* with the share in the foot too, the words keep the row and drop their
   two small icons, so the row stays on one line left of the dot */
body:has(.fail-dot) .tb-card--full .tb-card__foot:has(.tb-card__share--foot) :is(.tb-card__details, .tb-card__fliptap) > iconify-icon { display: none; }

/* ---- one card per screen -------------------------------------------- */
.tb-card-deck {
    height: var(--tb-card-deck-h, calc(100svh - var(--tb-card-top, var(--size-16))));
    overflow-y: auto;
    scroll-snap-type: y mandatory;
    overscroll-behavior-y: contain;
    padding: var(--space-2) var(--space-3);
    scroll-padding: var(--space-2);
}
.tb-card-deck > .tb-card { scroll-snap-align: start; scroll-snap-stop: always; margin-bottom: var(--space-4); }

@media (prefers-reduced-motion: reduce) {
    .tb-card__inner { transition: none; }
}

/* the one button keeps its own colours under the pointer (the site's a:hover
   is more specific than a class alone) */
.tb-card .tb-card__cta:hover,
.tb-card .tb-card__cta:focus-visible { color: var(--color-gray-800); }
.tb-card .tb-card__cta--quiet:hover,
.tb-card .tb-card__cta--quiet:focus-visible { color: var(--text-inverse); }

/* ---- THE PROPOSAL CARD'S FRONT (Steven 2026-10-14 morning, his phone shots
   of a bidding want: "why isn't the title at the top"; "I don't like the
   design of the 1 month thing ... the design has to be more simple and on
   brand") ------------------------------------------------------------------
   cards/_card.html draws an offer with `head` (proposal_cards.proposal_card)
   the way the want card draws its words: the pitch title at the TOP of the
   art in .tb-card__head under the want card's own fade (the stops of
   .tb-card--want .tb-card__art--image .tb-card__shade above, copied: the
   same treatment, not a second one), the middle of the picture clear, the
   agent's round and "By <agent>" at the foot (.tb-card__byline--foot). A
   long title (title_long) steps one size down and keeps its whole length
   in view (up to five lines) instead of an ellipsis after three. No ring:
   the span is quiet words beside the price (.tb-card__span), and the steps
   line labels the dashes (.tb-card__dashlabel). */
.tb-card--offer .tb-card__art:has(> .tb-card__head) { overflow: hidden; }
.tb-card--offer .tb-card__art:has(> .tb-card__head) .tb-card__shade {
    background: linear-gradient(180deg,
        color-mix(in srgb, var(--color-dark-900) 66%, transparent) 0%,
        color-mix(in srgb, var(--color-dark-900) 34%, transparent) 18%,
        transparent 34%,
        transparent 54%,
        color-mix(in srgb, var(--color-dark-900) 72%, transparent) 78%,
        color-mix(in srgb, var(--color-dark-900) 94%, transparent) 100%);
}
.tb-card--offer .tb-card__head .tb-card__title { text-shadow: 0 1px 14px rgb(0 0 0 / 0.5); }
.tb-card .tb-card__head .tb-card__title--long {
    font-size: var(--text-2xl);
    -webkit-line-clamp: 5;
    line-clamp: 5;
}
.tb-card__byline--foot { align-items: center; }
.tb-card__byline--foot .tb-card__bytext { color: var(--text-inverse); font-size: var(--text-lg); font-weight: 600; text-shadow: 0 1px 12px rgb(0 0 0 / 0.45); }
/* the dot sits a space from the price, as from the words after it */
.tb-card__span { margin-left: calc(-1 * var(--space-1)); color: var(--text-secondary); font-size: var(--text-base); white-space: nowrap; }
.tb-card__dashlabel { margin: 0 0 calc(-1 * var(--space-2)); color: var(--text-secondary); font-size: var(--text-sm); }

/* ---- THE BIG CARD, STEVEN'S RULINGS 2026-10-14 (card.css and card.js
   20261014-bigcard-1) ---------------------------------------------------- */

/* (1) THE TITLE'S DESCENDERS (his crop of a want card's title "I want a
   birthday party." at the top of the picture: "for some reason the font on
   the bottom here gets cut off"). The title clamps to three lines with
   overflow hidden, and its 1.08 line box was shorter than the font's
   descenders, so the last line's y, p and g lost their tails on every big
   card (want, proposal, offer). The clamp and its ellipsis stay; the box
   gets a little more line and room under the last line for the tails. */
.tb-card__title { line-height: 1.12; padding-bottom: var(--space-1); }

/* (2) THE PICTURE'S FOCUS IN THE CLEAR BAND (his want card "I want to
   rewrite my dating profile...", a handshake photo: "after we put the title
   at the top, the center of the picture needs to be focused in the center
   of the area between the title and the 69%"). On a card with its title at
   the top (a want, a proposal, a market offer), the picture's focus, the
   point the card has always framed (35% down, a little above its middle,
   where the pictures put faces: --tb-card-focus), lands in the middle of
   the clear band between the title's bottom and the odds' top (a want) or
   the agent's line at the foot (a proposal, an offer). The picture's box
   grows only as much as it must to keep the art covered (the least zoom),
   read off the two blocks with anchor positioning (anchor-scope keeps each
   card's names its own). A pose or a photo of the agent keeps its own crop
   from the top (the face whole). Where anchors are not supported the
   picture keeps the art's box, as before. */
@supports (top: anchor(--tb-card-a bottom)) and (height: stretch) {
    .tb-card__art:has(> .tb-card__head) { anchor-scope: --tb-card-head, --tb-card-band-end; }
    .tb-card__art > .tb-card__head { anchor-name: --tb-card-head; }
    .tb-card__art > .tb-card__over > .tb-card__odds,
    .tb-card__art > .tb-card__over > .tb-card__byline--foot { anchor-name: --tb-card-band-end; }
    .tb-card__art--image:has(> .tb-card__head):has(> .tb-card__over > :is(.tb-card__odds, .tb-card__byline--foot)):not(.tb-card__art--pose, .tb-card__art--photo) > .tb-card__img {
        --tb-card-focus: 0.35;
        /* the band's middle: from the art's top in `top`, from its bottom in
           `bottom` (anchor() reads the edge the property it sits in names) */
        --tb-card-mid: calc((anchor(--tb-card-head bottom) + anchor(--tb-card-band-end top)) / 2);
        top: calc(var(--tb-card-mid) - var(--tb-card-focus) * max(100%, var(--tb-card-mid) / var(--tb-card-focus), (100% - var(--tb-card-mid)) / (1 - var(--tb-card-focus))));
        bottom: calc(var(--tb-card-mid) - (1 - var(--tb-card-focus)) * max(100%, (100% - var(--tb-card-mid)) / var(--tb-card-focus), var(--tb-card-mid) / (1 - var(--tb-card-focus))));
        height: stretch;
        object-position: 50% calc(var(--tb-card-focus) * 100%);
    }
}

/* (3) THE ODDS SIT ON THE CHART'S TOP LINE (the same card: "since the four
   probability bars are gone and we have this line, move the 69 down a
   little so it's tighter: the bottom of the sixes now should be about where
   the top is, so down by about that amount. And put a light bar at the top
   below the 69, so we know the top is the chart and the bottom is the
   text."). On a full want card the chart rises into the room over its top
   line (Target, y 34 of its 210), so the odds block (the number, the move,
   the band, "Probability of success") comes down about one digit toward
   the line while the markers row stays put; the line itself is drawn as a
   light bar across the art's width at the chart's top grid line, through
   the target ring (no other grid line comes back). The chart draws at its
   height cap, (art width) x 0.33, so its top line sits 34/210 of that down
   its box. */
.tb-card--want.tb-card--full .tb-card__over > .tb-card__odds + .tb-card__chart {
    margin-top: calc(-1 * min(34vh, (100cqi - 2 * var(--space-5)) * 0.33) * 34 / 210);
    background: linear-gradient(color-mix(in srgb, var(--border-default) 40%, transparent),
                                color-mix(in srgb, var(--border-default) 40%, transparent))
                0 calc(34 / 210 * 100%) / 100% 1px no-repeat;
}

/* (4) THE POPPED CARD'S X KEEPS CLEAR OF THE TITLE: a market card popped
   over the landing (.ni-pop) or the Want Market's shelf (.wm-full) wears
   its round X in its top-right corner (ready-targets.css, THE POPPED
   CARD'S X: 40px, a card's padding in), and its title now rides the top of
   the picture, so the title's lines stop short of the X. */
.ni-pop .tb-card__art > .tb-card__head,
.wm-full .tb-card__art > .tb-card__head { padding-right: calc(var(--size-10) + var(--space-1)); }

/* THE THREE DOTS (Steven 2026-10-14 ~13:00, his prod shot of the your-turn
   card "Give AI editors a reason": "We are missing the three dots in the
   top right-hand corner that are the ones that allow us to cancel this
   request."). On the front of a want card its owner holds
   (templates/cards/_card.html _menu, home_cards.owner_menu): a quiet glass
   round in the top right corner of the art, and of the dark agent side;
   the want's title keeps clear of it, the minutes disc sits under it
   (THE CORNER, below), and the popped card's X keeps the same room ((4)
   above). A tap opens a small menu in
   the sheet's tones (step-cards.css .sl-*: white, the body face, the red
   words of "Fail agent" for the doors that end things); Cancel and Remove
   ask first, in the menu itself. static/cards/card.js drives it. */
.tb-card__menu {
    position: absolute;
    z-index: var(--z-dropdown);
    top: var(--space-4);
    right: var(--space-4);
    transition: opacity var(--duration-fast) var(--ease-default);
}
/* The dots ride the card, outside its faces (Steven 2026-10-14, his shot of
   a flipped agent card, the dots at the top left over its title: "it should
   disappear, then reappear in the corner, and it is always needed"): the
   same corner on the front and the back, gone at once while the card turns
   (is-3d, card.js flip), fading back into the corner when the turn ends;
   a face's 3D never carries them, so they are never mirrored. */
.tb-card.is-3d > .tb-card__menu { visibility: hidden; opacity: 0; transition: none; }
.tb-card__menubtn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--size-10);
    height: var(--size-10);
    padding: 0;
    border: 0;
    border-radius: var(--radius-full);
    background: color-mix(in srgb, var(--color-dark-900) 38%, transparent);
    color: var(--text-inverse);
    font-size: var(--text-xl);
    cursor: pointer;
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    transition: background var(--duration-fast) var(--ease-default);
}
.tb-card__menubtn[aria-expanded="true"],
.tb-card__menubtn:hover { background: color-mix(in srgb, var(--color-dark-900) 62%, transparent); }
.tb-card__menubtn:focus-visible { outline: 2px solid var(--interactive-focus-ring); outline-offset: 2px; }
.tb-card:has(> .tb-card__menu) .tb-card__art > .tb-card__head { padding-right: calc(var(--size-10) + var(--space-1)); }
.tb-card:has(> .tb-card__menu) .tb-card__face--side .tb-side__head { padding-right: calc(var(--space-5) + var(--size-10) + var(--space-1)); }
.tb-card:has(> .tb-card__menu) .tb-card__backtitle { padding-right: calc(var(--size-10) + var(--space-1)); }
/* THE CORNER (Steven 2026-10-14 ~15:25: "put it on the side below it with
   the three dots ... it should look like just two dots down the side"):
   the minutes disc leaves the head's row for the corner column, the dots'
   column: under the dots round on a card that wears them, a space between,
   on one axis; in the dots' own place on a card that does not. The head's
   padding reserves the column's width, so neither round covers the title.
   The head gives up its own position so the disc measures from the art's
   corner, as the dots do, whatever the art's padding (the deck steps it
   down on a phone). The dark side draws no disc. */
.tb-card__art > .tb-card__head:has(> .tb-card__badge) { position: static; padding-right: calc(var(--size-10) + var(--space-1)); }
.tb-card__art > .tb-card__head > .tb-card__badge { position: absolute; top: var(--space-4); right: var(--space-4); }
.tb-card:has(> .tb-card__menu) .tb-card__art > .tb-card__head > .tb-card__badge { top: calc(var(--space-4) + var(--size-10) + var(--space-2)); }
.tb-card__menupop {
    position: absolute;
    top: calc(100% + var(--space-2));
    right: 0;
    width: calc(var(--size-32) * 2.25);
    max-width: calc(100vw - var(--space-10));
    padding: var(--space-2) 0;
    border-radius: var(--radius-lg);
    background: var(--surface-primary);
    color: var(--text-primary);
    box-shadow: var(--shadow-xl);
    text-align: left;
    cursor: default;
}
.tb-card__menupop[hidden],
.tb-card__menupop [hidden] { display: none; }
.tb-card__menulist { display: flex; flex-direction: column; }
.tb-card__menuitem {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    min-height: var(--size-12);
    margin: 0;
    padding: 0 var(--space-4);
    border: 0;
    background: none;
    color: var(--text-primary);
    font-family: var(--font-body);
    --interface-font: var(--font-body);
    font-size: var(--text-base);
    font-weight: var(--font-semibold);
    line-height: var(--leading-snug);
    text-align: left;
    cursor: pointer;
}
.tb-card__menuitem > iconify-icon { flex: none; width: var(--size-5); height: var(--size-5); font-size: var(--text-xl); color: var(--text-secondary); }
.tb-card__menuitem:hover,
.tb-card__menuitem:focus-visible { background: var(--surface-secondary); outline: none; }
.tb-card__menuitem:disabled { cursor: default; opacity: 0.6; }
/* the doors that end things wear the red words ("Fail agent"),
   one hairline over the first of them */
.tb-card__menuitem--danger,
.tb-card__menuitem--danger > iconify-icon { color: var(--color-red-600); }
.tb-card__menuitem:not(.tb-card__menuitem--danger) + .tb-card__menuitem--danger { border-top: 1px solid var(--border-default); }
.tb-card__menuask { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-2) var(--space-4) var(--space-2); }
.tb-card__menutitle {
    margin: 0;
    font-family: var(--font-heading);
    --interface-font: var(--font-heading);
    font-size: var(--text-lg);
    font-weight: 800;
    line-height: var(--leading-snug);
}
.tb-card__menubody { margin: 0; color: var(--text-secondary); font-size: var(--text-sm); line-height: var(--leading-normal); }
.tb-card__menuerr { margin: 0; color: var(--color-red-600); font-size: var(--text-sm); font-weight: var(--font-semibold); }
/* the two answers stacked, the card's width each: the red one first */
.tb-card__menuacts { display: flex; flex-direction: column-reverse; align-items: stretch; gap: var(--space-2); margin-top: var(--space-1); }
.tb-card__menukeep,
.tb-card__menuyes {
    min-height: var(--size-10);
    padding: 0 var(--space-4);
    border-radius: var(--radius-full);
    font-family: var(--font-body);
    --interface-font: var(--font-body);
    font-size: var(--text-sm);
    font-weight: var(--font-bold);
    white-space: nowrap;
    cursor: pointer;
}
.tb-card__menukeep { border: 1px solid var(--border-default); background: var(--surface-primary); color: var(--text-primary); }
.tb-card__menuyes { border: 0; background: var(--color-red-600); color: var(--text-inverse); }
.tb-card__menuyes:disabled { opacity: 0.6; cursor: default; }
.tb-card__menukeep:focus-visible,
.tb-card__menuyes:focus-visible { outline: 2px solid var(--interactive-focus-ring); outline-offset: 2px; }
/* a want the person just canceled or removed fades while the deck moves on */
.tb-card.tb-card--leaving { opacity: 0; transition: opacity var(--duration-normal) var(--ease-default); }
@media (prefers-reduced-motion: reduce) {
    .tb-card__menu,
    .tb-card__menubtn,
    .tb-card.tb-card--leaving { transition: none; }
}
/* end THE THREE DOTS */
