/*
 * Trips surface — Phase A (nav item -> "Your trips" list -> trip-detail
 * timeline). Per-concern stylesheet (tokens.css / chat.css / trip-sheet.css
 * pattern) — uses the shared --aw-* design tokens exclusively so both the
 * dark app default and the light theme (tokens.css's [data-theme="light"]
 * block) render correctly with no theme logic of its own.
 *
 * body.view-trips show/hide plumbing (hiding the chat surface, sizing
 * #tripsView full-height) lives in chat.css alongside the sibling
 * .saved-view/.alerts-view blocks, per that file's source-order convention.
 * Everything below is the Trips-specific visual language only.
 */

/* ---------------------------------------------------------------------
 * "Your trips" list
 * ------------------------------------------------------------------- */

.trips-list-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-bottom: 14px;
}

.trips-list-title {
    font-size: 1.3rem;
    margin: 0;
    color: var(--aw-ink);
}

.trips-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
}

.trips-card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    width: 240px;
    padding: 14px 16px;
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius);
    background: var(--aw-surface);
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color 0.15s, box-shadow 0.15s;
}

.trips-card:hover,
.trips-card:focus-visible {
    border-color: var(--aw-accent);
    box-shadow: var(--aw-shadow);
}

.trips-card-name {
    font-weight: 600;
    color: var(--aw-ink);
}

.trips-card-meta {
    font-size: 0.82rem;
    color: var(--aw-muted);
}

.trips-card-chip {
    margin-top: 4px;
    padding: 2px 9px;
    border-radius: var(--aw-radius-pill);
    font-size: 0.68rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--aw-structure);
    background: var(--aw-structure-wash);
}

/* The owner's read-only Budapest sample (owner-caught, PR-B2 round 2). A
   DISTINCT chip from `planning`: the sample is not one of the user's trips and
   is not editable, so it must not wear the same badge as a trip that is both.
   Muted rather than branded — it is a demo, not a call to action. */
.trips-card-chip-sample {
    color: var(--aw-muted);
    background: color-mix(in srgb, var(--aw-muted) 14%, transparent);
}

.trips-sample-section {
    margin-top: 22px;
    padding-top: 14px;
    border-top: 1px dashed var(--aw-hairline);
}

.trips-sample-heading {
    margin: 0 0 2px;
    font-size: 0.74rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--aw-muted);
}

.trips-sample-note {
    margin: 0 0 10px;
    font-size: 0.82rem;
    color: var(--aw-muted);
}

.trips-empty-state {
    padding: 32px 16px;
    text-align: center;
    border: 1px dashed var(--aw-hairline-strong);
    border-radius: var(--aw-radius);
    background: var(--aw-surface);
}

.trips-empty-heading {
    margin: 0 0 6px;
    font-weight: 600;
    color: var(--aw-ink);
}

.trips-empty-body {
    margin: 0;
    font-size: 0.86rem;
    color: var(--aw-muted);
}

/* ---------------------------------------------------------------------
 * Detail view — loading / error states
 * ------------------------------------------------------------------- */

.trips-detail-loading {
    padding: 24px 0;
    color: var(--aw-muted);
    text-align: center;
}

.trips-detail-error {
    padding: 24px 16px;
    text-align: center;
}

.trips-detail-error-heading {
    font-weight: 600;
    color: var(--aw-ink);
    margin: 10px 0 4px;
}

.trips-detail-error-body {
    color: var(--aw-muted);
    font-size: 0.88rem;
    margin: 0 0 14px;
}

.trips-detail-back,
.trips-detail-error-retry {
    border: 1px solid var(--aw-hairline-strong);
    background: var(--aw-elevated);
    color: var(--aw-accent);
    border-radius: var(--aw-radius-sm);
    padding: 6px 12px;
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
}

/* ---------------------------------------------------------------------
 * Detail view — header + sticky verdict bar
 * ------------------------------------------------------------------- */

.trips-detail-breadcrumb {
    font-size: 0.82rem;
    color: var(--aw-muted);
    margin-bottom: 4px;
}

.trips-detail-breadcrumb .trips-detail-back {
    padding: 2px 8px;
}

.trips-detail-title {
    margin: 0 0 2px;
    font-size: 1.4rem;
    color: var(--aw-ink);
}

/* The trip's own ⋯ sits beside the name it acts on (#289 owner QA), the same
   grammar the slot pencils use. */
.trips-detail-titlerow {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* THE MERGED ROW (owner-ruled, QA item 4). On the canvas the breadcrumb row
   and the h1 are one line: the "‹ Trips" chip, the name at title size, the ✎
   and the ⋯. The breadcrumb's own tail ("› Budapest RTW") goes with it — the
   name is right there at 1.4rem, so repeating it in grey 20px above was the
   definition of saying it twice.

   Spine-only rules are left exactly where they were: below 1100px trips.js
   renders the two-row arrangement and none of this applies. */
.trips-detail-titlerow-merged {
    margin-bottom: 2px;
}

.trips-detail-titlerow-merged .trips-detail-back {
    flex: none;
    padding: 3px 10px;
    font-size: 0.78rem;
}

.trips-detail-titlerow-merged .trips-detail-title {
    margin: 0;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The ✎ is quiet at rest and lights on hover — the same grammar the slot
   rename pencils use, so one glyph means one thing across the page. */
.trips-title-rename-btn {
    flex: none;
    font-family: inherit;
    font-size: 0.85rem;
    line-height: 1;
    padding: 4px 7px;
    color: var(--aw-muted);
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--aw-radius-sm);
    cursor: pointer;
}

.trips-title-rename-btn:hover,
.trips-title-rename-btn:focus-visible {
    color: var(--aw-ink);
    border-color: var(--aw-hairline-strong);
}

.trips-title-rename {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    min-width: 0;
}

.trips-title-rename-input {
    font-family: inherit;
    font-size: 1.05rem;
    font-weight: 600;
    padding: 4px 8px;
    min-width: 220px;
    color: var(--aw-ink);
    background: var(--aw-surface);
    border: 1px solid color-mix(in srgb, var(--aw-choice) 45%, transparent);
    border-radius: var(--aw-radius-sm);
}

.trips-title-rename-save,
.trips-title-rename-cancel {
    font-family: inherit;
    font-size: 0.75rem;
    font-weight: 600;
    padding: 4px 10px;
    border-radius: var(--aw-radius-pill);
    cursor: pointer;
}

.trips-title-rename-save {
    color: var(--aw-choice);
    background: var(--aw-choice-wash);
    border: 1px solid color-mix(in srgb, var(--aw-choice) 45%, transparent);
}

.trips-title-rename-cancel {
    color: var(--aw-muted);
    background: transparent;
    border: 1px solid var(--aw-hairline-strong);
}

.trips-title-rename-error {
    font-size: 0.75rem;
    color: var(--aw-bad-ink);
}

/* ---- deleting a trip: the per-card / per-page ⋯ --------------------- */

.trips-card-wrap,
.trips-card-menu {
    position: relative;
    display: inline-flex;
}

.trips-card-menu-btn {
    appearance: none;
    align-self: center;
    padding: 2px 8px;
    border: 1px solid transparent;
    border-radius: var(--aw-radius-sm);
    background: none;
    color: var(--aw-muted);
    font: inherit;
    line-height: 1.2;
    cursor: pointer;
}

/* On a LIST card the ⋯ overlays the card's own top-right corner: the card is
   a full-size button, so the menu cannot be a child of it. */
.trips-card-wrap > .trips-card-menu-btn {
    position: absolute;
    top: 8px;
    right: 8px;
}

.trips-card-menu-btn:hover {
    border-color: var(--aw-hairline-strong);
    color: var(--aw-ink);
}

.trips-card-menu-btn:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

.trips-card-menu-pop {
    position: absolute;
    top: 34px;
    right: 0;
    /* ABOVE the sticky trip header (`.trips-header`, z-index 5), which sits
       right below the title and painted straight over this confirm at an equal
       z-index — caught in the proof capture, not in jsdom, which has no
       stacking contexts to get wrong. Matched to the trip-picker popover's own
       layer so transient overlays sit on one plane. */
    z-index: 41;
    min-width: 230px;
    padding: 8px;
    border: 1px solid var(--aw-hairline-strong);
    border-radius: var(--aw-radius-sm);
    background: var(--aw-surface);
    box-shadow: var(--aw-shadow);
    text-align: left;
}

.trips-card-menu-item {
    appearance: none;
    display: block;
    width: 100%;
    padding: 6px 8px;
    border: none;
    border-radius: var(--aw-radius-sm);
    background: none;
    color: var(--aw-ink);
    font: inherit;
    font-size: 0.82rem;
    text-align: left;
    cursor: pointer;
}

.trips-card-menu-item:hover { background: var(--aw-ground-2); }

.trips-card-menu-danger { color: var(--aw-bad, #e04b4b); }

.trips-card-menu-confirm {
    margin: 0 0 8px;
    padding: 0 4px;
    font-size: 0.8rem;
    line-height: 1.45;
    color: var(--aw-ink);
}

.trips-card-menu-actions {
    display: flex;
    gap: 6px;
}

.trips-card-menu-actions .trips-card-menu-item { width: auto; }

.trips-card-menu-error {
    margin-top: 6px;
    padding: 0 4px;
    font-size: 0.78rem;
    color: var(--aw-bad, #e04b4b);
}

.trips-detail-freshness {
    font-size: 0.78rem;
    color: var(--aw-muted);
    margin-bottom: 14px;
}

/* The band itself is `.trips-header` (T3-D section A, frame-7). Everything
   below is the verdict's own type scale, which the compact header's left zone
   reuses item for item — the CONTENT did not change, only the container. */

.trips-verdict-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.trips-verdict-label {
    font-size: 0.68rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--aw-muted);
}

.trips-verdict-value {
    font-size: 1.3rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--aw-ink);
}

.trips-verdict-value-miles {
    color: var(--aw-best);
}

.trips-verdict-value-cash {
    color: var(--aw-good);
}

.trips-verdict-value small {
    font-size: 0.78rem;
    color: var(--aw-muted);
    font-weight: 500;
}

/* Verdict v2 (Trip OS T2): the Trip Effective Cost headline leads the bar,
   each item carrying a small sub-line that qualifies its number (which
   programs, how many legs are timed, why a figure is missing). */
.trips-verdict-item-hero .trips-verdict-value {
    font-size: 1.55rem;
}

.trips-verdict-value-ec {
    color: var(--aw-ink);
}

.trips-verdict-sub {
    font-size: 0.7rem;
    line-height: 1.35;
    color: var(--aw-muted);
}

.trips-verdict-sub:empty {
    display: none;
}

.trips-verdict-staleness {
    flex-basis: 100%;
    font-size: 0.7rem;
    color: var(--aw-muted);
    border-top: 1px solid var(--aw-hairline);
    padding-top: 8px;
}

.trips-verdict-staleness:empty {
    display: none;
    border-top: none;
    padding-top: 0;
}

.trips-verdict-delta {
    margin-left: auto;
    font-size: 0.78rem;
    font-weight: 600;
    padding: 6px 12px;
    border-radius: var(--aw-radius-pill);
    opacity: 0;
    transform: translateY(-4px);
    transition: opacity 0.35s, transform 0.35s;
    white-space: nowrap;
}

.trips-verdict-delta-show {
    opacity: 1;
    transform: none;
}

.trips-verdict-delta-up {
    background: var(--aw-bad-dim);
    color: var(--aw-bad);
    border: 1px solid var(--aw-bad-dim);
}

.trips-verdict-delta-down {
    background: var(--aw-good-dim);
    color: var(--aw-good);
    border: 1px solid var(--aw-good-dim);
}

.trips-verdict-delta-flat {
    background: color-mix(in srgb, var(--aw-muted) 14%, transparent);
    color: var(--aw-muted);
    border: 1px solid var(--aw-hairline);
}

/* ---------------------------------------------------------------------
 * Timeline
 * ------------------------------------------------------------------- */

.trips-timeline {
    display: flex;
    flex-direction: column;
}

.trips-leg {
    position: relative;
    padding: 0 0 14px 30px;
}

.trips-leg::before {
    content: "";
    position: absolute;
    left: 9px;
    top: 6px;
    bottom: -6px;
    width: 2px;
    background: var(--aw-hairline-strong);
}

.trips-leg:last-child::before {
    display: none;
}

.trips-leg-dot {
    position: absolute;
    left: 2px;
    top: 4px;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--aw-surface);
    border: 2px solid var(--aw-structure);
}

.trips-leg-dot-rail {
    border-color: var(--aw-good);
}

.trips-leg-dot-fixed {
    border-color: var(--aw-muted);
    background: var(--aw-muted);
}

.trips-leg-dot-anchor {
    border-color: var(--aw-best);
    background: var(--aw-best);
}

.trips-leg-dot-stop {
    border-color: var(--aw-hairline-strong);
    width: 10px;
    height: 10px;
    left: 4px;
    top: 5px;
}

.trips-leg-card {
    background: var(--aw-surface);
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-sm);
    padding: 12px 14px;
    transition: box-shadow 0.2s, border-color 0.2s;
}

.trips-leg-card-flash {
    border-color: var(--aw-choice);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--aw-choice) 35%, transparent);
}

.trips-leg-card-stop {
    background: transparent;
    border-style: dashed;
    color: var(--aw-muted);
    padding: 8px 14px;
}

.trips-leg-card-fixed {
    background: var(--aw-ground-2);
}

.trips-leg-head {
    display: flex;
    align-items: flex-start;
    gap: 10px;
}

.trips-leg-route {
    font-size: 0.95rem;
    font-weight: 650;
    color: var(--aw-ink);
}

.trips-arrow {
    color: var(--aw-muted);
    margin: 0 6px;
}

.trips-leg-meta {
    font-size: 0.76rem;
    color: var(--aw-muted);
    margin-top: 2px;
}

.trips-leg-row2 {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    align-items: center;
    margin-top: 8px;
}

.trips-leg-price {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.trips-leg-price-miles {
    color: var(--aw-best);
}

.trips-leg-price-free {
    color: var(--aw-good);
}

.trips-chip {
    font-size: 0.66rem;
    font-weight: 600;
    padding: 3px 9px;
    border-radius: var(--aw-radius-pill);
    border: 1px solid var(--aw-hairline-strong);
    color: var(--aw-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.trips-chip-prog {
    color: var(--aw-ink-dim);
    border-color: var(--aw-hairline-strong);
}

.trips-chip-rec {
    color: var(--aw-good);
    border-color: color-mix(in srgb, var(--aw-good) 40%, transparent);
}

.trips-chip-tkt {
    color: var(--aw-muted);
}

.trips-chip-seats {
    color: var(--aw-accent);
    border-color: color-mix(in srgb, var(--aw-accent) 35%, transparent);
}

.trips-unknown {
    color: var(--aw-bad);
}

/* T4-F cut 10: an absence that is NORMAL, not a gap. An award trip with no
   captured cash fare is the expected case, and the alarm colour was making
   "nothing spent in cash" read as "something is missing here". */
.trips-unknown-quiet {
    color: var(--aw-muted);
}

/* ---------------------------------------------------------------------
 * Swap ▾ trays
 * ------------------------------------------------------------------- */

.trips-swap {
    margin-left: auto;
}

/* R1 (color-system §2b): a commit control is neutral at rest and choice-colored
   on hover/focus — the choice mark (cyan), not purple. */
.trips-swap-btn {
    background: transparent;
    border: 1px solid var(--aw-structure-dim);
    color: var(--aw-ink-dim);
    font-weight: 600;
    font-size: 0.76rem;
    padding: 5px 11px;
    border-radius: var(--aw-radius-sm);
    cursor: pointer;
}

.trips-swap-btn:hover,
.trips-swap-btn:focus-visible {
    background: var(--aw-choice-wash);
    border-color: var(--aw-choice);
    color: var(--aw-choice);
}

.trips-tray {
    display: none;
    margin-top: 10px;
    border-top: 1px dashed var(--aw-hairline);
    padding-top: 10px;
    flex-direction: column;
    gap: 8px;
}

.trips-tray-open {
    display: flex;
}

.trips-opt {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-sm);
    cursor: pointer;
    background: var(--aw-ground-2);
}

.trips-opt:hover {
    border-color: var(--aw-choice);
}

/* Keyboard focus ring for the role="radio" option divs (Copilot #238 rd1 —
   these are click-only <div>s made keyboard-operable; the browser's default
   outline is suppressed nowhere in this file, but an explicit ring matches
   the codebase's :focus-visible convention, see flight-table.css). */
.trips-opt:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

.trips-opt-active {
    border-color: var(--aw-choice);
    background: var(--aw-choice-wash);
}

.trips-opt-radio {
    width: 13px;
    height: 13px;
    border-radius: 50%;
    border: 2px solid var(--aw-muted);
    flex: none;
}

.trips-opt-active .trips-opt-radio {
    border-color: var(--aw-choice);
    background: var(--aw-choice);
}

.trips-opt-label {
    font-weight: 600;
    color: var(--aw-ink);
}

.trips-opt-sub {
    font-size: 0.76rem;
    color: var(--aw-muted);
}

.trips-opt-price {
    margin-left: auto;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--aw-ink);
}

/* ---------------------------------------------------------------------
 * Trip OS PR-B2 — AXIS CHIPS (the trip's decision variables).
 *
 * Replaces the retired hub-tension band, and keeps its one hard rule: every
 * choice renders through ONE shared selector (.trips-axes-chip) whose only
 * modifier (-on) says which one the USER picked. There is deliberately no
 * "winner"/"recommended" styling an axis could apply — the app does not vote
 * on a decision it is asking the user to make.
 *
 * Two variants of the same component:
 *   -bar  under the verdict: the axis title, the choices, and each choice's
 *         sourced note (the retired band's "why").
 *   -leg  inline beside an affected leg: same chips, no notes, tighter — it
 *         is a reminder of what moves this card, not a second explanation.
 *
 * Class names are `trips-axes-*` (plural). The date CANVAS owns `trips-axis-*`
 * (singular); the two are different concepts that unfortunately share an
 * English word, so they get different prefixes rather than a shared one.
 * ------------------------------------------------------------------- */

.trips-axes {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.trips-axes:empty {
    display: none;
}

.trips-axes-group {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
}

.trips-axes-group-bar {
    flex: 1 1 320px;
    padding: 10px 12px;
    margin-top: 8px;
    border: 1px solid var(--aw-hairline-strong);
    border-radius: var(--aw-radius-sm);
    background: var(--aw-surface);
}

.trips-axes-title {
    font-size: 0.74rem;
    color: var(--aw-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.trips-axes-chips {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.trips-axes-chip {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    max-width: 260px;
    padding: 6px 10px;
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-sm);
    background: var(--aw-elevated);
    color: var(--aw-ink);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

/* R2 (color-system §2b): the hub decision is painted once, in ink — not purple.
   Text (--aw-ink) on --aw-elevated is already set on the base rule; the ON state
   firms the border and adds a crisp ink ring. */
.trips-axes-chip-on {
    border-color: var(--aw-hairline-strong);
    box-shadow: inset 0 0 0 1px var(--aw-ink);
}

.trips-axes-chip:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

.trips-axes-chip-label {
    font-weight: 600;
    font-size: 0.82rem;
}

.trips-axes-chip-note {
    font-size: 0.72rem;
    color: var(--aw-muted);
    white-space: normal;
}

/* Inline, beside a leg: no card of its own — it belongs TO the leg card. */
.trips-axes-inline {
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px dashed var(--aw-hairline);
}

.trips-axes-group-leg .trips-axes-title {
    font-size: 0.68rem;
}

.trips-axes-group-leg .trips-axes-chip {
    padding: 3px 8px;
}

.trips-axes-group-leg .trips-axes-chip-label {
    font-size: 0.76rem;
    font-weight: 500;
}

/* The honest "why is this leg unpriced" line under an axis-affected leg. */
.trips-axes-gap {
    margin-top: 6px;
    font-size: 0.76rem;
    color: var(--aw-muted);
    font-style: italic;
}

/* ---------------------------------------------------------------------
 * Trips Phase B3 — per-leg freshness (G1) + list header "+ New" + new-trip
 * inline form
 * ------------------------------------------------------------------- */

.trips-leg-freshness {
    font-size: 0.74rem;
    color: var(--aw-muted);
    margin-top: 4px;
}

/* WCAG AA fix (color-system §228): red-as-text was 3.65:1; --aw-bad-ink is the
   text-safe red (6.05:1) on the same red tint. Background stays --aw-bad. */
.trips-leg-freshness-stale {
    color: var(--aw-bad-ink);
}

.trips-stale-badge {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--aw-bad, #e04b4b) 18%, transparent);
    color: var(--aw-bad-ink);
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    vertical-align: middle;
}

/* B-3 Booked lifecycle (frame 15) — one card, three states. Booked = cyan
   (--aw-choice, the pick/booked family); Held = gold (--aw-best, the
   holds/derived family). Booking removes, never adds: the card only gains a
   badge, a receipt line, and (Held) one advisory. */
.trips-leg-booked {
    border-color: var(--aw-choice);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--aw-choice) 45%, transparent);
    background: color-mix(in srgb, var(--aw-choice) 8%, var(--aw-surface));
}

.trips-leg-held {
    border-color: color-mix(in srgb, var(--aw-best) 55%, var(--aw-hairline));
}

.trips-book-badge {
    display: inline-block;
    margin-left: 8px;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    vertical-align: middle;
    white-space: nowrap;
}

.trips-book-badge-booked {
    background: color-mix(in srgb, var(--aw-choice) 20%, transparent);
    color: var(--aw-choice);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--aw-choice) 25%, transparent);
}

.trips-book-badge-held {
    background: color-mix(in srgb, var(--aw-best) 18%, transparent);
    color: var(--aw-best);
}

/* The receipt REPLACES the freshness slot on a booked leg (claim 2). */
.trips-leg-receipt {
    font-size: 0.74rem;
    color: var(--aw-choice);
    font-weight: 600;
    margin-top: 4px;
}

.trips-leg-held-advisory {
    font-size: 0.74rem;
    color: var(--aw-best);
    margin-top: 4px;
}

.trips-list-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.trips-new-btn {
    background: var(--aw-accent-btn);
    color: var(--aw-on-accent);
    border: none;
    border-radius: var(--aw-radius-sm);
    font-weight: 600;
    font-size: 0.82rem;
    padding: 7px 14px;
    cursor: pointer;
}
.trips-new-btn:hover { background: var(--aw-accent-btn-hover); }

.trips-empty-cta {
    margin-top: 12px;
}

.trips-new-trip-form {
    display: flex;
    gap: 8px;
    margin: 10px 0 18px;
    flex-wrap: wrap;
}

.trips-new-trip-input {
    flex: 1 1 220px;
    box-sizing: border-box;
    padding: 8px 10px;
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-sm);
    font-size: 0.85rem;
    background: var(--aw-surface);
    color: var(--aw-ink);
}

.trips-new-trip-error {
    width: 100%;
    font-size: 0.78rem;
    color: var(--aw-bad, #e04b4b);
    margin: 0;
}

/* ---------------------------------------------------------------------
 * TripPicker popover (Trips Phase B2 — "Save to trip ▾", triggered from
 * flight-table.js's row-expand .fd-actions). Anchored under .fd-save-wrap
 * (position:relative, flight-table.css) — this file owns the popover's own
 * look since it's conceptually part of the Trips surface, even though the
 * trigger button lives in the results table.
 * ------------------------------------------------------------------- */

.trip-picker-popover {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 40;
    min-width: 220px;
    max-width: 280px;
    background: var(--aw-surface);
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-sm);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.24);
    padding: 6px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

/* Owner-caught live on #289 (defect 6): the popover the one-click save
   reports failures into painted NOTHING. The result containers
   (.award-container / .cash-container / .value-comparison-container,
   flight-table.css) are bounded scrollboxes — `max-height: 72vh;
   overflow-y: auto; overflow-x: auto` — so a popover absolutely positioned
   inside .fd-save-wrap is a descendant of that clip, and the part of it that
   falls past the visible rows simply is not painted. `elementFromPoint` at
   its centre returned the table cell behind it. A clip cannot be out-ranked
   by a z-index, so trip-picker.js's `_mountPopover` reparents every popover
   to <body> and this modifier gives it the coordinate space to match (the
   inline top/left it writes are viewport coordinates).

   Declared AFTER the base rule on purpose: same specificity, so source order
   is what makes `position: fixed` win (the chat.css cascade lesson).

   The layer: above everything the results table can raise (frozen cells 4,
   sticky header 5/6, the scroll buttons 60, the value-badge tooltip 100) and
   above the trips page's own sticky verdict bar, but below the save toast
   (999) and the app's modals (1000+), which must still cover it. */
.trip-picker-popover-fixed {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 990;
}

.trip-picker-item {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: none;
    padding: 8px 10px;
    border-radius: var(--aw-radius-sm);
    font-size: 0.82rem;
    color: var(--aw-ink);
    cursor: pointer;
}
.trip-picker-item:hover, .trip-picker-item:focus-visible {
    background: var(--aw-ground-2);
}

.trip-picker-new {
    font-weight: 600;
    color: var(--aw-accent);
}

.trip-picker-divider {
    border-top: 1px solid var(--aw-hairline);
    margin: 4px 0;
}

/* The "Add to which leg?" step (Trip OS T2): a saved row can start a new
   leg or join an existing leg's candidate pool. */
.trip-picker-heading {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--aw-muted);
    padding: 6px 10px 2px;
}

.trip-picker-leg {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.trip-picker-leg-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
}

.trip-picker-leg-count {
    flex: none;
    font-size: 0.72rem;
    color: var(--aw-muted);
}

/* Route matching ADVISES, never blocks: legs the saved row doesn't match
   stay reachable under a collapsed disclosure, each stating plainly what
   adding the row there would widen. */
.trip-picker-other-legs {
    display: flex;
    flex-direction: column;
    gap: 2px;
    border-top: 1px solid var(--aw-hairline);
    margin-top: 4px;
    padding-top: 4px;
}

.trip-picker-other-toggle {
    color: var(--aw-muted);
    font-size: 0.76rem;
}

.trip-picker-other-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.trip-picker-other-list[hidden] {
    display: none;
}

.trip-picker-leg-note {
    font-size: 0.7rem;
    line-height: 1.35;
    color: var(--aw-muted);
    white-space: normal;
}

/* T3-A: the slot these results were hunted for. Led, not preselected — the
   save is still a deliberate click, so this marks the obvious choice rather
   than dressing the row up as already-chosen. */
.trip-picker-leg-hunted {
    border-color: color-mix(in srgb, var(--aw-accent) 45%, transparent);
    background: color-mix(in srgb, var(--aw-accent) 8%, transparent);
}

.trip-picker-loading,
.trip-picker-error p {
    font-size: 0.8rem;
    color: var(--aw-muted);
    padding: 8px 10px;
    margin: 0;
}

.trip-picker-error {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.trip-picker-retry {
    align-self: flex-start;
    font-size: 0.78rem;
    background: none;
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-sm);
    padding: 5px 10px;
    cursor: pointer;
    color: var(--aw-ink);
}

.trip-picker-input {
    width: 100%;
    box-sizing: border-box;
    padding: 8px 10px;
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-sm);
    font-size: 0.82rem;
    margin-bottom: 4px;
    background: var(--aw-surface);
    color: var(--aw-ink);
}

.trip-picker-create {
    background: var(--aw-accent-btn);
    color: var(--aw-on-accent);
    font-weight: 600;
}
.trip-picker-create:hover { background: var(--aw-accent-btn-hover); }

/* Save-to-trip confirmation toast (Trips Phase B2 — flight-table.js's
   showSaveToTripToast, triggered by the row-expand "Save to trip ▾"
   button) — deliberately separate from the app's generic #statusIndicator
   (window.showStatus): this one needs a real click-through ("View trip →"
   -> switchTab('trips') + Trips.openDetail), which the generic status bar
   doesn't support. B2-only — nothing in trips.js/trip-picker.js renders
   this. */
.aw-save-toast {
    position: fixed;
    left: 50%;
    bottom: 24px;
    transform: translateX(-50%);
    z-index: 999;
    display: flex;
    align-items: center;
    gap: 12px;
    background: var(--aw-surface);
    color: var(--aw-ink);
    border: 1px solid var(--aw-hairline-strong);
    padding: 10px 16px;
    border-radius: var(--aw-radius-sm);
    font-size: 0.85rem;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.24);
    max-width: calc(100vw - 32px);
}
.aw-save-toast-link {
    background: none;
    border: none;
    color: var(--aw-accent);
    font-weight: 700;
    cursor: pointer;
    padding: 0;
    white-space: nowrap;
}

/* ---------------------------------------------------------------------
 * Trip leg enrichment (PR1) — flight identity, honest booking link, and
 * the "Flight details ▾" disclosure. round-0-design.md §3a/§3b. Every
 * element here is additive and independently omitted when its backing
 * field is null (never-fabricate) — a pre-PR1 leg (Leg.options entries
 * with none of these fields) renders none of this, byte-identical to
 * before this file changed.
 * ------------------------------------------------------------------- */

.trips-leg-flightno {
    font-family: var(--aw-font-mono);
    font-size: 0.78rem;
    color: var(--aw-ink-dim);
    margin-top: 2px;
}

.trips-leg-row3 {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
}

/* Deliberately NOT the filled .fd-book pill flight-table.js uses for its
   "Book on X →" link (flight-table.css) — this is a secondary-weight,
   bordered affordance on purpose: an award booking_url usually opens the
   program's SEARCH page, not this exact itinerary, and it should not look
   as confident as a real checkout button (round-0-design.md §3a). */
.trips-leg-book {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-family: var(--aw-font-mono);
    font-size: 0.72rem;
    font-weight: 600;
    padding: 5px 10px;
    border-radius: var(--aw-radius-sm);
    border: 1px solid var(--aw-hairline-strong);
    color: var(--aw-accent);
    text-decoration: none;
    background: var(--aw-elevated);
}

.trips-leg-book:hover {
    border-color: var(--aw-accent);
}

.trips-leg-book:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

/* "Flight details ▾" toggle — reuses the SAME .trips-tray-open toggle
   mechanism as the Swap ▾ trays (_toggleTray in trips.js just flips this
   one class by element id; no new JS action type needed). */
.trips-leg-details-toggle {
    background: transparent;
    border: none;
    color: var(--aw-accent);
    font-size: 0.72rem;
    font-weight: 600;
    cursor: pointer;
    padding: 4px 2px;
    font-family: var(--aw-font-sans);
}

.trips-leg-details-toggle:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

.trips-leg-details {
    display: none;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px dashed var(--aw-hairline);
    flex-direction: column;
    gap: 5px;
    font-size: 0.78rem;
    color: var(--aw-ink-dim);
}

.trips-leg-details.trips-tray-open {
    display: flex;
}

.trips-leg-details .mono {
    font-family: var(--aw-font-mono);
}

/* Stale-leg booking caveat — promoted OUT of the disclosure onto the
   always-visible card (round-0-design.md §3b, owner-approved copy
   verbatim) exactly when G1 freshness has already flagged the leg STALE
   (trips.js's own ageDays >= 7 threshold) — quiet when fresh, loud when
   the warning actually matters. */
.trips-leg-caveat {
    margin-top: 7px;
    font-size: 0.72rem;
    color: var(--aw-bad);
    display: flex;
    align-items: flex-start;
    gap: 5px;
}

/* ---------------------------------------------------------------------
 * Trip OS T2 — the candidate POOL tray (PR-A: render + judgment notes).
 * Reuses the SAME .trips-tray / .trips-tray-open mechanism as the Swap ▾
 * and "Flight details ▾" disclosures (one toggle implementation for the
 * whole surface). Every rule here is reached only through markup trips.js
 * emits when a leg actually HAS a pool (`_hasPool`) — a leg saved before
 * T2 renders none of it. Base rules first, media queries last.
 * ------------------------------------------------------------------- */

.trips-leg-row4 {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 6px;
}

.trips-pool-toggle {
    background: transparent;
    border: none;
    color: var(--aw-accent);
    font-size: 0.72rem;
    font-weight: 600;
    cursor: pointer;
    padding: 4px 2px;
    font-family: var(--aw-font-sans);
}

.trips-pool-toggle:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

.trips-pool-opt {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 8px 10px;
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-sm);
    background: var(--aw-ground-2);
}

/* The selected candidate is MARKED, not styled as a winner: the others are
   equally real options the user saved (the same discipline the hub tension
   band follows). */
.trips-pool-opt-selected {
    border-color: var(--aw-accent);
}

.trips-pool-opt-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 8px;
}

.trips-pool-opt-title {
    font-family: var(--aw-font-mono);
    font-size: 0.78rem;
    color: var(--aw-ink);
}

.trips-pool-marker {
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    color: var(--aw-accent);
}

.trips-pool-opt-value {
    margin-left: auto;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--aw-ink);
}

.trips-pool-opt-meta,
.trips-pool-opt-freshness {
    font-size: 0.72rem;
    color: var(--aw-muted);
}

.trips-pool-note {
    font-size: 0.76rem;
    color: var(--aw-ink-dim);
    border-left: 2px solid var(--aw-hairline-strong);
    padding-left: 8px;
    white-space: pre-wrap;
}

.trips-pool-note-slot {
    display: flex;
    flex-direction: column;
    gap: 4px;
    align-items: flex-start;
}

.trips-pool-note-btn {
    background: transparent;
    border: none;
    color: var(--aw-accent);
    font-size: 0.72rem;
    font-weight: 600;
    cursor: pointer;
    padding: 2px;
    font-family: var(--aw-font-sans);
}

.trips-pool-note-btn:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

.trips-pool-note-input {
    width: 100%;
    box-sizing: border-box;
    font-family: var(--aw-font-sans);
    font-size: 0.76rem;
    padding: 6px 8px;
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-sm);
    background: var(--aw-surface);
    color: var(--aw-ink);
    resize: vertical;
}

.trips-pool-note-actions {
    display: flex;
    gap: 10px;
}

.trips-pool-note-error:empty {
    display: none;
}

.trips-pool-note-error {
    font-size: 0.72rem;
    color: var(--aw-bad);
}

/* ---------------------------------------------------------------------
 * Trip OS T1 — anchors, derived windows, and the Trip Health rail.
 * Adapted (selectively, NOT imported) from the approved mockups'
 * trip-os-mockup.css: docs/product/mockups/trip-os-page/frame-1-spine.png
 * (target render) + trip-os-creation/frame-2-skeleton.png (initial state).
 * Design ref: agent-lab/docs/design/2026-08-14-trip-os-anchor-first.md
 * §3/§4.3. --aw-* tokens only, like the rest of this file.
 *
 * Every rule here is reached only through markup trips.js emits when the
 * OPTIONAL `windows`/`health`/`anchors` envelope fields are present — a
 * payload without them renders none of these elements, so none of this can
 * touch the shipped view. Base rules first, media queries LAST (chat.css's
 * inverted order silently lost three equal-specificity overrides in one
 * week — see CLAUDE.md).
 * ------------------------------------------------------------------- */

/* --- two-column workspace: spine + sticky health rail --- */

.trips-cols {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 340px;
    gap: 22px;
    align-items: start;
}

.trips-rail {
    position: sticky;
    top: 72px;
}

/* --- fly-in / fly-out window bands --- */

.trips-window-band {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
    margin: 0 0 12px 30px;
    padding: 7px 12px;
    border: 1px solid color-mix(in srgb, var(--aw-best) 32%, transparent);
    border-radius: var(--aw-radius-sm);
    background: color-mix(in srgb, var(--aw-best) 7%, transparent);
}

.trips-leg + .trips-window-band {
    margin-top: 4px;
}

.trips-window-label {
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--aw-best);
}

.trips-window-range {
    font-family: var(--aw-font-mono);
    font-size: 0.86rem;
    font-weight: 700;
    color: var(--aw-ink);
}

.trips-window-derivations {
    margin: -4px 0 14px 30px;
    padding: 8px 12px;
    border-left: 2px solid var(--aw-hairline-strong);
    font-size: 0.74rem;
    color: var(--aw-muted);
    line-height: 1.55;
}

.trips-window-derivations-label {
    display: block;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--aw-muted);
    margin-bottom: 3px;
}

.trips-window-derivation-src {
    font-family: var(--aw-font-mono);
    font-size: 0.68rem;
    opacity: 0.7;
}

/* --- the pinned event-anchor card --- */

/* Longhands, not the `border-left:` shorthand: a shorthand carrying a
   var()/color-mix() value is unresolvable to any parser that doesn't run the
   custom-property substitution (jsdom drops the whole declaration), which
   would make the computed-style probe in tests/trips-health-rail.test.js
   blind to the very rule it guards. Longhands keep the width/style
   verifiable and the token where it belongs. */
.trips-leg-card-anchor {
    border-color: color-mix(in srgb, var(--aw-best) 45%, transparent);
    background: color-mix(in srgb, var(--aw-best) 6%, var(--aw-surface));
    border-left-width: 3px;
    border-left-style: solid;
    border-left-color: var(--aw-best);
}

.trips-anchor-kind {
    font-size: 0.64rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--aw-muted);
    margin-bottom: 3px;
}

.trips-anchor-place {
    font-weight: 500;
    color: var(--aw-ink-dim);
}

.trips-anchor-derives {
    margin-top: 7px;
    font-family: var(--aw-font-mono);
    font-size: 0.74rem;
    color: var(--aw-ink-dim);
}

.trips-chip-anchor {
    color: var(--aw-best);
    border-color: color-mix(in srgb, var(--aw-best) 45%, transparent);
    text-transform: none;
    letter-spacing: 0.02em;
}

.trips-chip-anchor-state {
    text-transform: none;
    letter-spacing: 0.02em;
}

/* --- 🔒 locked (ticketed) legs — a constraint anchor's own leg --- */

.trips-leg-card-locked {
    border-left-width: 3px;
    border-left-style: solid;
    border-left-color: var(--aw-hairline-strong);
}

.trips-chip-locked {
    color: var(--aw-ink-dim);
    border-color: var(--aw-hairline-strong);
    text-transform: none;
    letter-spacing: 0.02em;
}

/* --- the Trip Health rail (IDE "Problems panel" shape) --- */

.trips-health-panel {
    background: var(--aw-surface);
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius);
    overflow: hidden;
}

.trips-health-tabs {
    display: flex;
    border-bottom: 1px solid var(--aw-hairline);
    background: var(--aw-ground-2);
}

.trips-health-tab {
    flex: 1;
    padding: 10px 12px;
    text-align: center;
    font-family: inherit;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--aw-muted);
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    cursor: pointer;
}

/* Kept for any tab that is genuinely inert. The Ledger tab was such a stub
   in T1; Verdict v2 (T2) activated it, so nothing sets [disabled] today. */
.trips-health-tab[disabled] {
    cursor: not-allowed;
    opacity: 0.55;
}

.trips-health-tab-active {
    color: var(--aw-ink);
    border-bottom-color: var(--aw-ink);
    background: var(--aw-surface);
}

/* T4-F cut 3: ONE badge, carrying the fix-first count, and only when there is
   one. The four bare numbers it replaces were a legend you had to already know
   how to read, above four tier heads that each print their own count. */
.trips-health-tab-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 17px;
    height: 17px;
    margin-left: 6px;
    padding: 0 5px;
    border-radius: var(--aw-radius-pill);
    font-family: var(--aw-font-mono);
    font-size: 0.66rem;
    font-weight: 700;
    line-height: 1;
    /* A filled stamp, not red text: the badge is the one alarm on the strip,
       and #fff on both themes' `--aw-bad` clears AA at this weight. */
    color: #fff;
    background: var(--aw-bad);
}

.trips-health-summary {
    padding: 10px 14px;
    border-bottom: 1px solid var(--aw-hairline);
    font-size: 0.76rem;
    line-height: 1.5;
    color: var(--aw-muted);
}

.trips-health-tier {
    border-bottom: 1px solid var(--aw-hairline);
}

.trips-health-tier:last-child {
    border-bottom: none;
}

.trips-health-tier-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 14px 7px;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
}

.trips-health-tier-count {
    font-family: var(--aw-font-mono);
    font-size: 0.66rem;
    font-weight: 700;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: var(--aw-radius-pill);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.trips-health-tier-blocker .trips-health-tier-head { color: var(--aw-bad); }
.trips-health-tier-blocker .trips-health-tier-count { background: var(--aw-bad-dim); color: var(--aw-bad); }
.trips-health-tier-warning .trips-health-tier-head { color: var(--aw-tl-mid); }
.trips-health-tier-warning .trips-health-tier-count { background: color-mix(in srgb, var(--aw-tl-mid) 16%, transparent); color: var(--aw-tl-mid); }
.trips-health-tier-todo .trips-health-tier-head { color: var(--aw-accent); }
.trips-health-tier-todo .trips-health-tier-count { background: color-mix(in srgb, var(--aw-accent) 14%, transparent); color: var(--aw-accent); }
.trips-health-tier-passing .trips-health-tier-head { color: var(--aw-good); }
.trips-health-tier-passing .trips-health-tier-count { background: var(--aw-good-dim); color: var(--aw-good); }
.trips-health-tier-other .trips-health-tier-head { color: var(--aw-muted); }
.trips-health-tier-other .trips-health-tier-count { background: color-mix(in srgb, var(--aw-muted) 16%, transparent); color: var(--aw-muted); }

/* Severity icons (color-system §2b, finding f: every health tier reads color +
   word + ICON). Pure CSS ::before — a flex item spaced by the head's gap:8px,
   inheriting the per-tier color above. Scoped through the tier ancestor so it
   never leaks into _ledgerSectionHtml's unrelated reuse of .trips-health-tier-head. */
.trips-health-tier-blocker .trips-health-tier-head::before { content: "!"; font-weight: 900; }
.trips-health-tier-warning .trips-health-tier-head::before { content: "\25b2"; } /* ▲ */
.trips-health-tier-todo    .trips-health-tier-head::before { content: "\25cb"; } /* ○ */
.trips-health-tier-passing .trips-health-tier-head::before { content: "\2713"; } /* ✓ */

/* An empty tier is a real, useful answer ("no blockers") — rendered, not
   hidden, but visually quiet so the tiers that DO have items lead. */
.trips-health-empty {
    padding: 0 14px 10px;
    font-size: 0.76rem;
    font-style: italic;
    color: var(--aw-muted);
}

/* --- the Ledger tab (Trip OS T2) --- */

.trips-ledger-section {
    border-bottom: 1px solid var(--aw-hairline);
    padding-bottom: 8px;
}

.trips-ledger-section:last-child {
    border-bottom: none;
}

.trips-ledger-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    padding: 4px 14px;
    font-size: 0.78rem;
}

.trips-ledger-row-label {
    color: var(--aw-muted);
}

.trips-ledger-row-value {
    color: var(--aw-ink);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    text-align: right;
}

.trips-health-item {
    padding: 8px 14px 12px;
    display: flex;
    flex-direction: column;
    gap: 7px;
}

/* T4-F cut 8: the item IS the "show on timeline" control, so it wears a quiet
   affordance rather than a gray button repeated under every finding. Quiet is
   the point — a rail of ten items must not read as a rail of ten buttons. */
.trips-health-item[role="button"] {
    cursor: pointer;
    border-left: 2px solid transparent;
    transition: background 120ms ease, border-color 120ms ease;
}

.trips-health-item[role="button"]:hover,
.trips-health-item[role="button"]:focus-visible {
    background: var(--aw-ground-2);
    border-left-color: var(--aw-hairline-strong);
}

.trips-health-item[role="button"]:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: -2px;
}

.trips-health-item + .trips-health-item {
    border-top: 1px dashed var(--aw-hairline);
    padding-top: 12px;
}

.trips-health-item-msg {
    font-size: 0.78rem;
    line-height: 1.5;
    color: var(--aw-muted);
}

.trips-health-item-msg b {
    color: var(--aw-ink);
    font-weight: 650;
}

.trips-health-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.trips-health-btn {
    background: transparent;
    border: 1px solid var(--aw-hairline-strong);
    color: var(--aw-ink-dim);
    font-family: inherit;
    font-size: 0.7rem;
    font-weight: 600;
    padding: 4px 10px;
    border-radius: var(--aw-radius-sm);
    cursor: pointer;
    white-space: nowrap;
}

.trips-health-btn:hover {
    border-color: var(--aw-accent);
    color: var(--aw-accent);
}

.trips-health-btn:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

.trips-health-btn-fix {
    color: var(--aw-accent);
    border-color: color-mix(in srgb, var(--aw-accent) 45%, transparent);
    background: color-mix(in srgb, var(--aw-accent) 9%, transparent);
}

/* ---------------------------------------------------------------------
 * Trip OS — the DATE-AXIS Trip page view.
 * Adapted (selectively, NOT imported) from the approved mockup
 * docs/product/mockups/trip-os-page/frame-3-date-axis.html/.png; design ref
 * agent-lab/docs/design/2026-08-14-trip-os-anchor-first.md §2b/§3.
 *
 * y = calendar date flowing down. A central axis runs the length of the
 * canvas, each band drawing its own segment so a tinted window band paints
 * BEHIND both the axis and the cards. Legs alternate sides; multi-day
 * anchors span the axis full width; empty time is empty space.
 *
 * Every rule here is reached only through markup trips.js emits when the
 * axis is active (>=1100px, no `?axis=0` / `tripsAxis=off` kill switch) —
 * the narrow spine renders none of it. --aw-* tokens only. Base rules
 * first, media queries LAST (see this file's T1 header note).
 * ------------------------------------------------------------------- */

/* The full-width claim. TWO caps bind, both MEASURED in Chrome (walking the
   real ancestor chain body > .chat-container > .app-shell > .app-main >
   #tripsView > #tripsViewBody), not inferred from the markup:

   1. `.trips-view-body { max-width: 720px }` (chat.css) — the reading measure
      for a single column. Two classes beat one, so this wins on specificity
      regardless of stylesheet order.
   2. `.chat-container { width: 97%; max-width: 2000px; margin: 10px auto }`
      (chat.css:79) — the app-wide card. This one is the reason the owner still
      saw a large empty right margin on #281: at a 2400px viewport the cap
      pinned the card to 2000px and centred it, so the canvas measured 1712px
      (71% of the viewport) with 232px of dead space to its right. Releasing it
      takes the canvas to 2336px there, i.e. the viewport minus the 210px nav
      column and a 32px gutter.

   Every rule below is double-scoped to `body.view-trips.trips-axis-wide`:
   `trips-axis-wide` is armed by trips.js only while a trip DETAIL view is
   open, and `view-trips` means switching to any other tab disarms the whole
   block on its own — there is no teardown for a future edit to forget, and
   chat/Saved/Alerts keep their reading measure untouched. */
.trips-view-body.trips-axis-active {
    max-width: none;
}

body.view-trips.trips-axis-wide .chat-container {
    width: auto;
    max-width: none;
    /* Longhands, not the `margin` shorthand: the base rule's 10px top/bottom
       is still wanted, only the `auto` side-centring has to go. */
    margin-left: 16px;
    margin-right: 16px;
}

/* `.header` mirrors the card's own 2000px cap + auto margins (chat.css:111).
   Left alone it would stay centred inside a now-wider card, so the app title
   and account cluster would drift out of line with the shell beneath them. */
body.view-trips.trips-axis-wide .header {
    max-width: none;
    margin-left: 0;
    margin-right: 0;
}

/* With the card at the viewport edge, the view's own 16px side padding is a
   third gutter stacked on the card's margin and padding. Dropping it keeps
   the canvas 32px from the screen edge instead of 48px. */
body.view-trips.trips-axis-wide .trips-view {
    padding-left: 0;
    padding-right: 0;
}

/* THE THIRD CAP — the tf=1 shell (owner-caught after #284 went green).
   #281 measured the DEFAULT shell's binders (the two above) and lifted them.
   There is a SECOND shell: `?tf=1` swaps `.app-shell` into
   `.app-shell.tf-shell`, a three-column grid `210px minmax(0,1fr) 336px`
   (table-first.css:29) whose `chat` column belongs to the /chat surface's
   chat rail. On the Trips tab table-first.js hides `.table-window` AND
   `.chat-rail` (setShellVisibleForTab), so that 336px track — plus the grid's
   own 14px gap — stands EMPTY while `.app-main` (`grid-area: table`,
   table-first.css:45) stays boxed inside the middle track.

   MEASURED in Chrome on the live app, walking the chain from
   `.trips-axis-cols` up (not inferred). At a 2000px viewport, before this
   rule: `.app-shell.tf-shell` computed `210px 1362px 336px`, `.app-main` ran
   256 -> 1618, and the canvas stopped 382px short of the right edge. The
   default shell at the same width measured `210px 1712px`, canvas 256 -> 1968
   (a 32px gutter) — so this is the tf shell alone, and #281's two lifts are
   intact under BOTH (verified with `body.is-authed` on and off, i.e. with
   #283's rail/header chrome active: it re-binds nothing here).

   The fix is one longhand, and deliberately NOT a re-declaration of
   `grid-template-columns`: overriding the template would fight table-first.css
   for the whole grid (and silently re-place `.tab-bar`/`.chat-rail`, which
   are BUILD's). Extending `.app-main`'s column END to the last line lets the
   trips workspace span the table AND chat tracks while every other item stays
   exactly where the TF shell put it. The trips page is a workspace: the chat
   rail is a /chat-surface concept and reserves nothing here.

   Specificity: (0,5,1) against table-first.css's (0,3,0) — it wins on
   specificity alone, never on load order (this file's own T1 lesson).
   Disarming is automatic and total: `trips-axis-wide` comes off when the
   detail view closes or the viewport drops under the axis threshold, and
   `view-trips` comes off on any tab switch (index.html's closeTripsView), so
   the TF grid returns to `210px 1fr 336px` with nothing to tear down. */
body.view-trips.trips-axis-wide .app-shell.tf-shell > .app-main {
    grid-column-end: -1;
}

/* T4-G section A (frame 12): 344px -> 360px. The 16px is the honest cost of
   moving the four verdict tiles into the rail, and it is bought back many
   times over by the band that left: 113px plus its 20px margin, spent at
   EVERY scroll position because the band was sticky. Measured in the real
   engine, not read off the diff — see proof-rail-strip/. */
.trips-axis-cols {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 360px;
    gap: 20px;
    align-items: start;
}

.trips-axis-stage {
    min-width: 0;
}

/* --- THE APPRAISAL RAIL (frame 12) ------------------------------------
   Its own sticky scroll column, so the appraisal is legible at every scroll
   position without a band claiming the page's full width. It scrolls INSIDE
   itself past the viewport's height rather than pushing the page: frame 12
   measured the rail at 975px on the owner's trip, which does not fit a 900px
   laptop, and a rail that grew the page would undo the height the band's
   death just bought.

   `top` is 0 rather than the health rail's 72px: with the band gone there is
   nothing above it to clear. It still comes to rest 20px below the viewport
   edge, and deliberately so — a sticky element pins to its scrollport's
   PADDING box, and `.trips-view` carries 20px of top padding, which is the
   16px breathing space frame 12 drew above the rail. Measured in Chrome, not
   assumed: `.trips-header-wrap` had to CANCEL exactly this to sit flush,
   because it was chrome hugging the top edge; a column of cards is not.

   That published padding is also why the max-height is expressed against it
   rather than as a bare `100vh - 32px`: the rail starts below it, so a
   hard-coded figure would silently overshoot the day the padding is tuned
   (the same drift `--trips-scrollport-pad-top` exists to prevent). */
.trips-axis-cols .trips-rail {
    position: sticky;
    top: 0;
    display: flex;
    flex-direction: column;
    gap: 14px;
    max-height: calc(100vh - var(--trips-scrollport-pad-top, 0px) - 20px);
    overflow-y: auto;
}

.trips-rail-block {
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius);
    background: var(--aw-surface);
    overflow: hidden;
}

/* The verdict is the answer to "what is this trip costing me", so it is the
   one block drawn on the elevated surface the band used to occupy. */
.trips-rail-block-verdict {
    background: var(--aw-elevated);
    box-shadow: var(--aw-shadow);
}

.trips-rail-block-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 13px 0;
}

.trips-rail-block-title {
    margin: 0;
    font-size: 0.66rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--aw-muted);
}

.trips-rail-verdict-body {
    padding: 8px 13px 0;
}

/* The tiles STACK — one per row, each hairlined off the one above, so the
   hero reads as the headline and the three below it as its qualifications. */
.trips-rail-verdict-body .trips-verdict-item {
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: 9px 0;
    border-top: 1px solid var(--aw-hairline);
}

.trips-rail-verdict-body .trips-verdict-item:first-child {
    border-top: 0;
    padding-top: 4px;
}

.trips-rail-verdict-body .trips-verdict-value {
    font-size: 1.22rem;
}

.trips-rail-verdict-body .trips-verdict-item-hero .trips-verdict-value {
    font-size: 1.62rem;
}

/* The line that qualifies the numbers sits on the block's floor, under a
   rule, exactly as it did on the band it left. */
.trips-rail-stale {
    margin: 4px 0 0;
    padding: 8px 13px 10px;
    border-top: 1px solid var(--aw-hairline);
    font-size: 0.69rem;
    line-height: 1.4;
    color: var(--aw-muted);
}

/* Until a server verdict lands there is nothing to qualify, and a rule with
   nothing under it is a divider that divides nothing. Caught in the real
   engine — an empty element with padding and a border draws perfectly well. */
.trips-rail-stale:empty {
    display: none;
}

/* The relocated anchors zone keeps its own rules; what changes is that it no
   longer sits in a two-column band, so the divider it carried there goes. */
.trips-rail-block-anchors .trips-header-anchors {
    border-left: 0;
    border-top: 0;
    padding: 0;
}

.trips-rail-block-anchors .trips-header-anchors-head {
    padding: 9px 13px 0;
}

/* The zone keeps its own title ELEMENT (it moved whole), so the two block
   heads are made to agree here rather than by rewriting its markup. */
.trips-rail-block-anchors .trips-header-anchors-title {
    font-size: 0.66rem;
    letter-spacing: 0.08em;
}

.trips-rail-block-anchors .trips-header-chips {
    padding: 9px 13px 12px;
}

.trips-rail-block-anchors .trips-header-anchors-empty {
    padding: 6px 13px 12px;
}

.trips-rail-block-anchors .trips-anchor-form:not([hidden]),
.trips-rail-block-anchors .trips-anchors-error:not(:empty) {
    padding: 0 13px 12px;
}

/* --- THE MAP STRIP (T4-G section B, frame 13's METRIC grammar) ---------
   A thin, to-scale overview between the title row and the working canvas.
   Days per pixel is constant and written in INLINE styles by trips.js: a
   metric layout's whole claim is that its widths are lengths, and a length
   cannot be expressed in a stylesheet that does not know the trip's span. */
/* STICKY, and it condenses (owner QA item 2, revised). The owner overruled
   the non-sticky ruling with the argument that settles it: a viewport
   indicator exists FOR scrolling, so a strip that scrolls away kills its own
   indicator. Pinned to the top of the STAGE column, it stays a map of the
   canvas it sits on rather than becoming a page-wide band again.

   `top: 0` pins it to the scrollport's PADDING box, which is the same 20px of
   air the rail rests in — the two columns line up without either naming a
   number the other has to match. The shipped value is an INLINE negative
   offset (`_stripDrop`): the band slides up by exactly the height the
   condensation gives back, in the compositor, so condensing never changes
   layout. `top: 0` here is only the pre-paint fallback. `overflow-anchor:
   none` is the second half of the same fix — the mini repaint replaces the
   strip's subtree mid-scroll, and Chrome must not pick a scroll anchor
   inside it (anchoring against the first build's height change is what made
   the page eat every small-delta trackpad gesture — the owner's scroll-trap
   report, live session 2026-08-17). */
.trips-strip {
    position: sticky;
    top: 0;
    overflow-anchor: none;
    z-index: 6;
    margin: 0 0 16px;
    padding: 0;
    /* The transparent padding zone (the mini state's slid-away area) must
       not swallow clicks meant for the canvas scrolling beneath it — the
       verifier found the Leg rename pencil dead under it. The outer box is
       click-through; the painted band re-arms itself just below. */
    pointer-events: none;
}

/* The INK lives on the scroll box (below), not on the sticky outer: the
   outer box keeps the full-band height in both states (the scroll-trap
   invariant), so in the mini its upper region is empty space the canvas
   scrolls through — paint there would dim the very content sliding under
   the band. */

/* A zero-height probe that does NOT stick, immediately above the strip: a
   pinned element's own rect cannot answer "have we scrolled past you". */
.trips-strip-sentinel {
    height: 0;
}

/* THE CONDENSED STATE. The geometry is written inline by `_stripLayout` (one
   source for both states); what belongs here is the ink — a slimmer, quieter
   ruler that reads as chrome rather than as content, and marks small enough
   to keep the whole thing near 40px. */
/* (The stuck state's drop shadow lives just after the scroll box's own block
   below, so that block stays the first `.trips-strip-scroll` rule in the
   file for everything that reads the base rule.) */

.trips-strip-mini .trips-strip-num,
.trips-strip-mini .trips-strip-mon {
    display: none;
}

.trips-strip-mini .trips-strip-ruler {
    border-bottom-width: 1px;
}

/* The bracket pills become compact ticks: the deadline is still marked, and
   its words move to the tooltip the full strip already carries. */
.trips-strip-mini .trips-strip-brk {
    width: 2px;
    height: 9px;
    padding: 0;
    font-size: 0;
    border-radius: 1px;
    border: 0;
    background: var(--aw-window);
    transform: none;
    margin: 0;
}

.trips-strip-mini .trips-strip-bar {
    padding: 0;
    gap: 0;
    border-radius: 2px;
    font-size: 0;
}

/* The names go, the LANES stay: two durations that share dates still get
   their own rows, which is the whole of what the collision fix bought. */
.trips-strip-mini .trips-strip-bar-name,
.trips-strip-mini .trips-strip-bar-pin {
    display: none;
}

.trips-strip-mini .trips-strip-dot {
    width: 6px;
    height: 6px;
    margin-left: -3px;
    border-width: 1px;
}

/* The tier ring survives the shrink — it is a fact, not an ornament — and it
   keeps the TIER's ink. `currentcolor` was the first draft and computed to
   black: a dot inherits its colour from the page, not from its severity, so
   the ring drew as a black halo that read as a rendering artifact. Caught by
   reading `boxShadow` in the real engine, which is the only place it is
   visible at 6px. */
.trips-strip-mini .trips-strip-dot-blocker {
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--aw-bad) 55%, transparent);
}

.trips-strip-mini .trips-strip-dot-warning {
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--aw-warn) 55%, transparent);
}

/* Past the legibility floor the strip scrolls in its OWN box, never the page:
   the map moving under the reader is the point, the page jumping is not. */
.trips-strip-scroll {
    pointer-events: auto;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: thin;
    /* The painted band, in both states (see the .trips-strip comment). */
    border: 1px solid var(--aw-hairline-strong);
    border-radius: var(--aw-radius-sm);
    background: var(--aw-ground-2);
}

/* The stuck state casts a shadow — the band floats over content there. */
.trips-strip-mini .trips-strip-scroll {
    box-shadow: 0 6px 14px rgb(0 0 0 / 22%);
}

.trips-strip-track {
    position: relative;
    height: 108px;
    min-width: 100%;
}

/* --- the deadline brackets, on the ruler they name --- */

.trips-strip-brks {
    position: absolute;
    inset: 0;
    pointer-events: none;
}

.trips-strip-brk {
    position: absolute;
    z-index: 5;
    display: inline-flex;
    align-items: center;
    white-space: nowrap;
    font-size: 0.62rem;
    font-weight: 700;
    color: var(--aw-window);
    background: var(--aw-ground-2);
    border: 1px solid var(--aw-window-edge);
    border-radius: var(--aw-radius-pill);
    padding: 2px 8px;
}

/* The bracket points AT its edge: the arrive-by flag hangs to the left of the
   date it names, the leave-after flag to the right, so neither covers it. */
.trips-strip-brk-in {
    transform: translateX(-100%);
    margin-left: -4px;
}

.trips-strip-brk-out {
    margin-left: 4px;
}

/* --- the ruler --- */

/* `top` and `height` are written inline: the strip has two states and the
   rows below this one are a function of the data (see `_stripLayout`). */
.trips-strip-ruler {
    position: absolute;
    left: 0;
    right: 0;
    border-bottom: 2px solid var(--aw-hairline-strong);
}

.trips-strip-day {
    position: absolute;
    top: 0;
    height: 100%;
    box-sizing: border-box;
    border-left: 1px solid var(--aw-hairline);
    text-align: center;
    overflow: hidden;
}

.trips-strip-day:first-child {
    border-left: none;
}

.trips-strip-mon {
    display: block;
    font-family: var(--aw-font-mono);
    font-size: 0.52rem;
    font-weight: 700;
    font-style: normal;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--aw-structure);
}

.trips-strip-num {
    display: block;
    font-size: 0.68rem;
    font-weight: 700;
    color: var(--aw-ink-dim);
}

/* The tolerance: a thickened gold segment of the ruler's own baseline, from
   the SAME published ticks the canvas draws. 62px, not 60: the ruler's own
   2px baseline sits OUTSIDE its 30px height, and at 60 the gold run hid
   under it. Measured in the real engine (`tol.top` vs `ruler.bottom`), which
   is the only place that difference is visible at all. */
.trips-strip-tol {
    position: absolute;
    height: 4px;
    cursor: help;
    border-radius: 3px;
    background: var(--aw-window-line);
    z-index: 4;
}

/* --- the line, and the flight legs on it --- */

.trips-strip-spine {
    position: absolute;
    left: 0;
    right: 0;
    height: 2px;
    background: var(--aw-hairline-strong);
    z-index: 1;
}

.trips-strip-dot {
    position: absolute;
    width: 12px;
    height: 12px;
    margin-left: -6px;
    padding: 0;
    border-radius: 50%;
    background: var(--aw-surface);
    border: 2px solid var(--aw-structure);
    cursor: pointer;
    z-index: 3;
}

.trips-strip-dot-picked {
    border-color: var(--aw-choice);
    background: var(--aw-choice-wash);
}

/* A leg the rail wants work on wears the tier's ink as a ring — the strip
   states the tier, it never restates the sentence. */
.trips-strip-dot-blocker {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--aw-bad) 45%, transparent);
}

.trips-strip-dot-warning {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--aw-warn) 45%, transparent);
}

.trips-strip-dot:hover,
.trips-strip-dot:focus-visible {
    border-color: var(--aw-choice);
}

/* --- the duration bars: the whole reason the strip exists --- */

.trips-strip-lane {
    position: absolute;
    inset: 0;
    pointer-events: none;
}

.trips-strip-bar {
    position: absolute;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 0 7px;
    border-radius: var(--aw-radius-sm);
    font-family: inherit;
    font-size: 0.66rem;
    line-height: 1;
    text-align: left;
    overflow: hidden;
    white-space: nowrap;
    pointer-events: auto;
    z-index: 2;
}

button.trips-strip-bar {
    cursor: pointer;
}

.trips-strip-bar-anchor {
    background: var(--aw-window-wash-strong);
    border: 1px solid var(--aw-window-line);
    color: var(--aw-ink);
}

.trips-strip-bar-stay {
    background: var(--aw-structure-wash);
    border: 1px dashed var(--aw-hairline-strong);
    color: var(--aw-ink-dim);
}

.trips-strip-bar-name {
    overflow: hidden;
    text-overflow: ellipsis;
    font-weight: 650;
}

.trips-strip-bar-pin {
    flex: none;
}

.trips-strip-bar:hover,
.trips-strip-bar:focus-visible {
    border-color: var(--aw-choice);
}

/* --- which slice of the trip the canvas is showing --- */

/* THE VIEWPORT INDICATOR (owner QA item 2). He read the old cyan underline as
   "a bar connecting Leg 1 and Leg 2" — it sat directly under the dot line at
   the same weight, so it looked like part of the trip rather than a statement
   about the view. It now rides in a GUTTER of its own, below the dots and
   visually separated from them, and it is drawn as a scrollbar thumb: the one
   shape every reader already knows means "this is where you are looking".
   It also says so, in a title that follows the scroll. */
.trips-strip-gutter {
    position: absolute;
    left: 0;
    right: 0;
    height: 6px;
    border-radius: 3px;
    background: var(--aw-structure-wash);
    border-top: 1px solid var(--aw-hairline);
    z-index: 5;
}

.trips-strip-viewport {
    position: absolute;
    left: 0;
    height: 6px;
    border-radius: 3px;
    background: var(--aw-structure);
    opacity: 0.85;
    cursor: help;
    z-index: 6;
}

.trips-strip-viewport[hidden] {
    display: none;
}

.trips-axis {
    position: relative;
}

/* --- a band: one calendar date (or one clamped run of them) --- */

.trips-axis-band {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr) 112px minmax(0, 1fr);
    border-top: 1px solid var(--aw-hairline);
    min-height: 96px;
    padding-bottom: 10px;
}

.trips-axis-band:first-child {
    border-top: none;
}

/* Clamped, never proportional: an empty date is a short band and a busy one
   grows to its content. The data supports ORDER and ALIGNMENT honestly; a
   pixels-per-day scale would imply a precision it does not have. */
.trips-axis-band-empty {
    min-height: 52px;
    padding-bottom: 0;
}

.trips-axis-band-stretch {
    min-height: 132px;
}

/* T4-F section B (frame-11 panel D): the fly-in / fly-out band TINTS are gone.
   A window binds exactly one leg, so a wash across every band it covered made
   the innocent legs look guilty of a deadline with no authority over them. The
   window family now paints the axis (`.trips-axis-wtick` / `.trips-axis-wflag`)
   and the ONE leg each window binds (`.trips-axis-slot-bound`). */

/* A date that falls INSIDE an event anchor's span and carries legs of its own
   (a side trip during the conference). The anchor band spans visually and
   these follow it, so they borrow its tint and its left rule to read as that
   anchor's time rather than as ordinary open days after it. */
.trips-axis-band-inanchor {
    background: color-mix(in srgb, var(--aw-best) 5%, transparent);
    border-left: 3px solid color-mix(in srgb, var(--aw-best) 45%, transparent);
}

/* --- the axis column --- */

.trips-axis-line {
    position: relative;
}

.trips-axis-line::before {
    content: "";
    position: absolute;
    left: 50%;
    margin-left: -1px;
    top: 0;
    bottom: -10px;
    width: 2px;
    background: var(--aw-hairline-strong);
}

/* Uncovered time: the axis itself goes dashed. */
.trips-axis-line-dashed::before {
    background: repeating-linear-gradient(
        to bottom,
        var(--aw-hairline-strong) 0 6px,
        transparent 6px 12px
    );
}

.trips-axis-date {
    position: absolute;
    left: 50%;
    top: -12px;
    transform: translateX(-50%);
    z-index: 3;
    font-family: var(--aw-font-mono);
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    color: var(--aw-ink-dim);
    background: var(--aw-ground-2);
    border: 1px solid var(--aw-hairline-strong);
    border-radius: var(--aw-radius-pill);
    padding: 2px 10px;
    white-space: nowrap;
}

.trips-axis-date-quiet {
    color: var(--aw-muted);
    font-weight: 600;
    opacity: 0.8;
}

/* --- the two sides --- */

.trips-axis-cell {
    position: relative;
    padding-top: 20px;
}

.trips-axis-cell-left {
    grid-column: 1;
    padding-right: 22px;
}

.trips-axis-cell-right {
    grid-column: 3;
    padding-left: 22px;
}

/* Only a cell that actually carries a slot draws a connector — an empty side
   stays empty space, which is the whole point of a date canvas. */
.trips-axis-cell-filled::before {
    content: "";
    position: absolute;
    top: 42px;
    height: 2px;
    width: 78px;
    background: var(--aw-hairline-strong);
}

.trips-axis-cell-right.trips-axis-cell-filled::before {
    left: -56px;
}

.trips-axis-cell-left.trips-axis-cell-filled::before {
    right: -56px;
}

.trips-axis-dot {
    position: absolute;
    top: 37px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--aw-surface);
    border: 2px solid var(--aw-structure);
    z-index: 2;
}

.trips-axis-cell-right .trips-axis-dot {
    left: -62px;
}

.trips-axis-cell-left .trips-axis-dot {
    right: -62px;
}

.trips-axis-slot + .trips-axis-slot {
    margin-top: 14px;
}

/* --- full-width bands: the event anchor's own span, and undated legs --- */

.trips-axis-band-full {
    display: block;
    padding: 26px 0 56px;
}

.trips-axis-datepill {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    z-index: 3;
    font-family: var(--aw-font-mono);
    font-size: 0.68rem;
    font-weight: 700;
    color: var(--aw-best);
    background: var(--aw-ground-2);
    border: 1px solid color-mix(in srgb, var(--aw-best) 45%, transparent);
    border-radius: var(--aw-radius-pill);
    padding: 2px 10px;
    white-space: nowrap;
}

.trips-axis-datepill-top { top: -12px; }
.trips-axis-datepill-bot { bottom: 26px; }

.trips-axis-anchor {
    padding: 14px 18px;
}

/* --- the fixed thing as a SIDE CARD (frame-9, owner correction 1) ---------

   It sits in one of the two ordinary cells and takes its turn in the
   alternation. Only two things are special, and both are about DURATION —
   which is the one thing a side card cannot say by its own width:

   1. the axis draws a GOLD SPAN over the anchor's days, between the pills;
   2. the pills sit on the LINE (not on the band, as the full-width version had
      them), so they mark the ends of that span rather than the ends of a row.

   The band keeps a floor tall enough for the span to read as a span at a
   one-day anchor. The window bands are NOT here: they stay full width. */
.trips-axis-band-anchor {
    min-height: 128px;
}

.trips-axis-anchor-span {
    position: absolute;
    left: 50%;
    margin-left: -3px;
    top: 4px;
    bottom: 4px;
    width: 6px;
    border-radius: 3px;
    z-index: 2;
    background: color-mix(in srgb, var(--aw-best) 78%, transparent);
}

/* On the LINE, the pills mark the span's own ends.

   The bottom one sits INSIDE the band, unlike the frame's, and that is not a
   deviation for its own sake: frame-9's anchor is followed by a window bar,
   while the real canvas puts the next DATED band directly under it — and a
   pill hanging -11px below the band landed exactly on that band's own date.
   The real-engine shot caught the two overlapping. Inside, the span still
   reads as running pill-to-pill, because the pill is opaque and z-indexed
   above it. */
.trips-axis-line .trips-axis-datepill-top { top: -11px; }
.trips-axis-line .trips-axis-datepill-bot { top: auto; bottom: 6px; }

.trips-axis-dot-anchor {
    border-color: var(--aw-best);
    background: var(--aw-best);
}

.trips-axis-cell-anchor.trips-axis-cell-filled::before {
    background: color-mix(in srgb, var(--aw-best) 65%, transparent);
}

.trips-axis-band-undated {
    padding: 22px 0 14px;
}

/* An inherited or missing date is SAID, never drawn as if it were known. */
.trips-axis-nodate {
    display: inline-block;
    margin-bottom: 6px;
    font-family: var(--aw-font-mono);
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--aw-muted);
    border: 1px dashed var(--aw-hairline-strong);
    border-radius: var(--aw-radius-pill);
    padding: 1px 8px;
}

/* ---------------------------------------------------------------------------
   T4-F section B — DEADLINE BRACKETS + HALOS (frame-11 panel D, owner-ruled
   2026-08-17). The FLY-IN WINDOW / FLY-OUT WINDOW band labels are gone with
   the bands themselves.

   The window family is GOLD throughout, one step weaker than the anchor's own
   frame: a window is the anchor's derivation, not its own idea.
   --------------------------------------------------------------------------- */

/* T4-G section B: the STRIP is a sibling of the canvas, not a descendant, so
   it needs the same tokens declared where it can see them. Found in the real
   engine, where `getComputedStyle(tolerance).backgroundColor` came back
   `rgba(0, 0, 0, 0)` — an undefined custom property resolves to nothing and
   the gold run drew as clear glass, which no screenshot read would have
   caught and no jsdom test can evaluate. Two selectors rather than a hoist to
   `.trips-detail`: the window family belongs to the two surfaces that draw
   windows, and naming them keeps that true. */
.trips-axis,
.trips-strip {
    --aw-window: var(--aw-best);
    --aw-window-line: color-mix(in srgb, var(--aw-best) 62%, transparent);
    --aw-window-edge: color-mix(in srgb, var(--aw-best) 38%, transparent);
    --aw-window-wash: color-mix(in srgb, var(--aw-best) 8%, transparent);
    --aw-window-wash-strong: color-mix(in srgb, var(--aw-best) 13%, transparent);
}

/* The tolerance: a thickened segment of the spine itself, with no words on it.
   The date pill and the dot paint ON TOP (they carry their own stacking
   context below), so the tick reads as the line being thicker rather than as a
   new object beside it. */
.trips-axis-wtick {
    position: absolute;
    left: 50%;
    margin-left: -2.5px;
    top: 0;
    bottom: 0;
    width: 5px;
    border-radius: 3px;
    background: var(--aw-window-line);
    z-index: 1;
}

/* The last date INSIDE the tolerance, and no further. */
.trips-axis-wtick-close {
    border-bottom: 1px solid var(--aw-window-edge);
}

/* The deadline itself, flagged on the row it names and pointing at the side of
   the axis it governs. Absolutely positioned off the axis line so it cannot
   push the band's own date pill around. */
/* The band RESERVES the strip its bracket hangs in. Without this the flag sat
   on top of the leg card in the same cell — a collision the real-engine
   rect-intersection assertion caught and no screenshot read would have, since
   both marks report perfectly healthy rects. */
.trips-axis-band-wflag {
    padding-top: 30px;
}

.trips-axis-wflag {
    position: absolute;
    top: -26px;
    z-index: 5;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    white-space: nowrap;
    font-size: 0.68rem;
    font-weight: 700;
    color: var(--aw-window);
    background: var(--aw-ground-2);
    border: 1px solid var(--aw-window-edge);
    border-radius: var(--aw-radius-pill);
    padding: 3px 10px;
}

.trips-axis-wflag-in {
    right: 50%;
    margin-right: 44px;
}

.trips-axis-wflag-out {
    left: 50%;
    margin-left: 44px;
}

/* THE HALO — jurisdiction drawn as extent. It paints the ONE leg the window
   binds, and nothing else on the page. */
.trips-axis-slot-bound {
    position: relative;
    border-left: 3px solid var(--aw-window);
    border-radius: 4px;
    background: var(--aw-window-wash);
    padding-left: 9px;
}

/* A refusal is the same halo at the check's own severity: the window ADVISES
   and never blocks, so the canvas must not shout where the rail only notes. */
.trips-axis-slot-bound-warning {
    border-left-color: var(--aw-warn);
    background: color-mix(in srgb, var(--aw-warn) 8%, transparent);
}

.trips-axis-wreceipt {
    margin-top: 6px;
}

.trips-axis-wtag {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    color: var(--aw-window);
    border: 1px solid var(--aw-window-edge);
    background: var(--aw-window-wash-strong);
    border-radius: var(--aw-radius-pill);
    padding: 3px 9px;
}

.trips-axis-slot-bound-warning .trips-axis-wtag {
    color: var(--aw-warn);
    border-color: color-mix(in srgb, var(--aw-warn) 38%, transparent);
    background: color-mix(in srgb, var(--aw-warn) 13%, transparent);
}

/* The check's own sentence, verbatim, under the tag. */
.trips-axis-wsaid {
    margin-top: 4px;
    font-size: 0.72rem;
    color: var(--aw-muted);
}

/* --- the open-nights marker, pinned to the axis inside the empty space --- */

.trips-axis-open {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    z-index: 3;
    display: flex;
    align-items: center;
    gap: 8px;
    white-space: nowrap;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--aw-muted);
    background: var(--aw-ground);
    border: 1px dashed var(--aw-hairline-strong);
    border-radius: var(--aw-radius-pill);
    padding: 6px 14px;
}

.trips-axis-open b {
    color: var(--aw-ink-dim);
    font-weight: 700;
}

.trips-axis-open-sub {
    position: absolute;
    left: 50%;
    top: calc(50% + 26px);
    transform: translateX(-50%);
    z-index: 3;
    font-size: 0.68rem;
    color: var(--aw-muted);
    white-space: nowrap;
}

/* --- the same-slot candidate cluster --- */

.trips-axis-cluster {
    border-left: 2px solid var(--aw-structure-dim);
    border-radius: 10px 0 0 10px;
    background: var(--aw-structure-wash);
    padding: 10px 0 10px 12px;
}

.trips-axis-slot-head {
    display: flex;
    align-items: baseline;
    gap: 9px;
    flex-wrap: wrap;
}

.trips-axis-slot-label {
    font-size: 0.86rem;
    font-weight: 700;
    color: var(--aw-ink);
    letter-spacing: 0.01em;
}

.trips-axis-slot-sub {
    font-size: 0.74rem;
    color: var(--aw-muted);
    margin: 3px 0 10px;
}

/* A flex row, not a block: `.trips-leg-menu`'s `margin-left: auto` is inert in
   a block formatting context, which left the ⋯ trigger mid-card and gave the
   popup 115px of overhang past the canvas on a left-side slot (#282, measured
   in Chrome at 1440). The measured flip in trips.js is the general guard; this
   is the layout the trigger should have had. */
/* `flex-wrap` for the same measured reason as `.trips-anchors-item`: the
   rename editor (#288) mounts into this row as an extra flex item and must be
   able to take its own line inside a ~400px axis card instead of squeezing the
   candidate count and the ⋯ out of the box. */
.trips-axis-slot-foot {
    margin-top: 6px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

/* The rename editor lives inside the title now (round 3), so it wraps to its
   own line within the title rather than fighting the count pill for room. */
.trips-slot-title .trips-slot-rename {
    flex-basis: 100%;
}

/* --- Pruning a pool (round 3) ------------------------------------------ */

.trips-pool-purge,
.trips-pool-opt-remove {
    font-family: inherit;
    font-size: 0.7rem;
    font-weight: 600;
    padding: 2px 8px;
    color: var(--aw-muted);
    background: transparent;
    border: 1px solid var(--aw-hairline-strong);
    border-radius: var(--aw-radius-pill);
    cursor: pointer;
}

.trips-pool-purge {
    margin-left: auto;
}

.trips-pool-purge:hover,
.trips-pool-opt-remove:hover {
    color: var(--aw-bad);
    border-color: var(--aw-bad);
}

.trips-pool-purge:focus-visible,
.trips-pool-opt-remove:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

/* Both confirms take their own full-width row under what they are about —
   a consequence is a sentence, not a chip (the measured lesson from
   `.trips-anchors-item`). */
.trips-pool-purge-confirm,
.trips-pool-opt-confirm {
    flex-basis: 100%;
    width: 100%;
    margin-top: 6px;
}

.trips-pool-opt-confirm[hidden] {
    display: none;
}

.trips-pool-purge-text,
.trips-pool-opt-confirm-text {
    margin: 0 0 6px;
    font-size: 0.72rem;
    line-height: 1.5;
    color: var(--aw-ink);
}

.trips-pool-purge-actions,
.trips-pool-opt-confirm-actions {
    display: flex;
    gap: 8px;
}

.trips-pool-opt-danger,
.trips-pool-opt-cancel {
    font-family: inherit;
    font-size: 0.72rem;
    font-weight: 600;
    padding: 3px 10px;
    color: var(--aw-ink);
    background: transparent;
    border: 1px solid var(--aw-hairline-strong);
    border-radius: var(--aw-radius-pill);
    cursor: pointer;
}

.trips-pool-opt-danger:hover {
    color: var(--aw-bad);
    border-color: var(--aw-bad);
}

.trips-pool-purge-error,
.trips-pool-opt-error {
    margin-top: 6px;
    font-size: 0.72rem;
    line-height: 1.45;
    color: var(--aw-bad);
}

.trips-pool-purge-error:empty,
.trips-pool-opt-error:empty {
    display: none;
}

/* The pool row's head is a flex row; the confirm needs to wrap beneath it. */
.trips-pool-opt-head {
    flex-wrap: wrap;
}

/* T4-E (owner ruling): the pill reads "2 options · from 70,000 miles", in the
   case it is written in. Uppercase was how it shouted "2 CANDIDATES · 1 SLOT",
   and the count is a fact about the pool, not a heading. Size goes 0.62 ->
   0.68rem and the tracking closes, because lowercase at 0.62rem sets visibly
   smaller than uppercase did at the same size, and the pill is a control. */
.trips-axis-slot-count {
    font-family: inherit;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--aw-structure);
    background: transparent;
    border: 1px solid var(--aw-structure-dim);
    border-radius: var(--aw-radius-pill);
    padding: 2px 8px;
    cursor: pointer;
}

.trips-axis-slot-count:hover {
    background: color-mix(in srgb, var(--aw-accent) 12%, transparent);
}

.trips-axis-slot-count:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

/* The expanded cluster's door onto the drill-in (round 3). It sits UNDER the
   siblings it compares, right-aligned and quiet: the candidates are the
   subject, and this is where you go having read them — not a second control
   competing with the count pill for the same press. */
.trips-axis-cluster-foot {
    display: flex;
    justify-content: flex-end;
    margin-top: 6px;
}

.trips-axis-cluster-table {
    font-family: inherit;
    font-size: 0.68rem;
    font-weight: 600;
    color: var(--aw-ink-dim);
    background: transparent;
    border: 1px solid var(--aw-hairline-strong);
    border-radius: var(--aw-radius-pill);
    padding: 3px 10px;
    cursor: pointer;
}

.trips-axis-cluster-table:hover {
    color: var(--aw-ink);
    background: color-mix(in srgb, var(--aw-accent) 12%, transparent);
}

.trips-axis-cluster-table:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

.trips-axis-cand {
    position: relative;
}

/* The selected candidate — THE choice. Cyan ring (color-system §2b: the choice
   gets the brightest mark), not purple. Frame 6. */
.trips-axis-cand-selected {
    border-color: var(--aw-choice);
}

/* The sibling is attached and recessed — same slot, not a second leg. It is
   NOT styled as a loser: it is an option the user saved, waiting on a
   selection control this PR deliberately does not ship (that is PR-B). */
.trips-axis-cand-ghost {
    margin: 8px 0 0 18px;
    border-style: dashed;
    background: var(--aw-ground-2);
    opacity: 0.78;
    padding: 10px 13px;
}

.trips-axis-cand-ghost::before {
    content: "";
    position: absolute;
    left: -18px;
    top: -8px;
    bottom: 50%;
    width: 2px;
    background: var(--aw-hairline-strong);
}

.trips-axis-cand-ghost::after {
    content: "";
    position: absolute;
    left: -18px;
    top: 50%;
    width: 18px;
    height: 2px;
    background: var(--aw-hairline-strong);
}

.trips-axis-cand-head {
    display: flex;
    align-items: baseline;
    gap: 10px;
}

.trips-axis-cand-title {
    font-family: var(--aw-font-mono);
    font-size: 0.78rem;
    color: var(--aw-ink);
}

.trips-axis-cand-title .trips-leg-flightno {
    margin-top: 0;
}

.trips-axis-flag {
    margin-left: auto;
    flex: none;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    border-radius: var(--aw-radius-pill);
    padding: 2px 9px;
}

/* The ✓ Selected flag — a solid cyan stamp under near-black text (13.17:1),
   "a label that was applied" (color-system §2b, frame 6). Was purple text on a
   purple wash (3.70:1, below AA); now a filled choice-mark. */
.trips-axis-flag-selected {
    color: var(--aw-on-choice);
    border: 1px solid var(--aw-choice);
    background: var(--aw-choice);
}

.trips-axis-flag-alt {
    color: var(--aw-muted);
    border: 1px solid var(--aw-hairline-strong);
}

.trips-axis-delta {
    color: var(--aw-muted);
    font-weight: 600;
    font-size: 0.78rem;
    font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------------
 * The slot -> table drill-in: one leg's ENTIRE candidate pool as a
 * comparison table, full width across the canvas. Reuses
 * flight-table.css's `.flight-table-container` / `.flight-table` (deliberately NOT `.award-table`: its min-width pushes columns off the canvas)
 * conventions (flight-table.js itself is untouched — see
 * `_slotTableHtml`'s note for why its renderer could not be reused).
 * View only: no selection, no re-hunt, no save.
 * ------------------------------------------------------------------- */

.trips-slot-table-band {
    border-top: 1px solid var(--aw-hairline-strong);
    border-bottom: 1px solid var(--aw-hairline-strong);
    background: var(--aw-elevated);
    padding: 10px 0 14px;
    margin-bottom: 10px;
}

.trips-slot-table-head {
    display: flex;
    align-items: baseline;
    gap: 10px;
    padding: 0 4px 8px;
}

.trips-slot-table-title {
    font-size: 0.86rem;
    font-weight: 700;
    color: var(--aw-ink);
}

.trips-slot-table-sub {
    font-size: 0.72rem;
    color: var(--aw-muted);
}

.trips-slot-table-close {
    margin-left: auto;
    background: transparent;
    border: 1px solid var(--aw-hairline-strong);
    border-radius: var(--aw-radius-sm);
    color: var(--aw-ink-dim);
    font-size: 0.8rem;
    line-height: 1;
    padding: 4px 8px;
    cursor: pointer;
}

.trips-slot-table-close:hover {
    border-color: var(--aw-accent);
    color: var(--aw-accent);
}

.trips-slot-table-close:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

.trips-slot-table-scroll {
    overflow-x: auto;
    max-width: 100%;
    margin: 0;
}

.trips-slot-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.74rem;
}

/* Twelve columns is a lot for one canvas track, so the headers WRAP rather
   than push the last two off the edge (real-engine check at 1440: with
   nowrap, "Data freshness" and "Your note" fell outside the band).
   The compound selector is deliberate: flight-table.css's `.flight-table th`
   sets `white-space: nowrap` and a single class could not outrank it — the
   cascade lesson in CLAUDE.md, measured rather than assumed. */
.trips-slot-table th.trips-slot-th {
    text-align: left;
    white-space: normal;
    padding: 6px 8px;
    border-bottom: 1px solid var(--aw-hairline-strong);
    font-size: 0.64rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--aw-muted);
    cursor: pointer;
}

.trips-slot-table th.trips-slot-th:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: -2px;
}

.trips-slot-table th.trips-slot-th-asc,
.trips-slot-table th.trips-slot-th-desc {
    color: var(--aw-accent);
}

.trips-slot-table td.trips-slot-td {
    padding: 6px 8px;
    border-bottom: 1px solid var(--aw-hairline);
    color: var(--aw-ink-dim);
    font-variant-numeric: tabular-nums;
    vertical-align: top;
    white-space: normal;
}

/* The selection is MARKED, not crowned — the other rows are equally real
   options the user saved (the same discipline the pool tray follows). */
.trips-slot-table .trips-slot-row-selected td.trips-slot-td {
    color: var(--aw-ink);
    background: var(--aw-choice-wash);
}

/* Media queries LAST, after every base rule they override (see the header
   comment) — the rail drops under the spine before the two columns get too
   narrow to read. */
@media (max-width: 900px) {
    .trips-cols {
        grid-template-columns: minmax(0, 1fr);
        gap: 16px;
    }

    .trips-rail {
        position: static;
    }
}

/* ---------------------------------------------------------------------
 * Trip OS PR-B1 — selection, undo, slot labels, leg deletion.
 *
 * Placed BEFORE the @media block below on purpose: this file's media
 * queries live at the end, so a base rule written after one would still
 * win, but keeping base rules above the breakpoint block is what makes
 * the cascade readable (the chat.css lesson, inverted).
 * ------------------------------------------------------------------- */

/* R1 (color-system §2b): a commit control is neutral (structure) at rest and
   choice-colored (cyan) on hover/focus — not purple. */
.trips-select-btn {
    font-family: inherit;
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--aw-structure);
    background: transparent;
    border: 1px solid var(--aw-structure-dim);
    border-radius: var(--aw-radius-pill);
    padding: 2px 9px;
    cursor: pointer;
    white-space: nowrap;
}

.trips-select-btn:hover {
    color: var(--aw-choice);
    border-color: var(--aw-choice);
    background: var(--aw-choice-wash);
}

.trips-select-btn:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

/* In a cluster the control gets its own row at the foot of the recessed
   sibling. Measured at 1440 in Chrome: sharing the head row with the title and
   the ALTERNATIVE flag wrapped a flight identity ("DE2033 · Condor") across
   two lines mid-token. */
.trips-axis-cand-actions {
    margin-top: 8px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

/* T4-F (frame-10 Option A): the verb row is a FIELD of the option card and is
   always emitted, so the card's anatomy is constant. An option that offers no
   verb costs no space — the anatomy is fixed, the ink is not. */
.trips-axis-cand-actions:empty {
    display: none;
}

/* ---------------------------------------------------------------------------
   T4-F section A — the option card's two fixed fact lines (frame-10 Option A).

   Both hold their positions when the value is unknown ("seats —", a lone "—"
   on the times line): a field that vanishes is what let the pooled and the
   single renderer print different shapes for the same leg, and constancy here
   is exactly what makes a pool of one and a pool of five one object.
   --------------------------------------------------------------------------- */

.trips-axis-opt-facts {
    margin-top: 4px;
    font-size: 0.72rem;
    color: var(--aw-ink-dim);
}

.trips-axis-opt-times {
    margin-top: 2px;
    font-family: var(--aw-font-mono);
    font-size: 0.7rem;
    color: var(--aw-muted);
}

/* The multi-origin outbound's gateway pills, kept under the one grammar. They
   sit on the LEG's own lines (above the options), because boarding the same
   flight somewhere else is a fact about the leg, not about an option. */
.trips-axis-gateway {
    margin-top: 6px;
}

.trips-slot-td .trips-select-btn {
    font-size: 0.62rem;
    padding: 1px 7px;
}

/* ---------------------------------------------------------------------------
   Trip OS T3-D section C — the drill-in table's per-row actions.
   --------------------------------------------------------------------------- */

.trips-slot-actions {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
}

/* The confirm is IN FLOW, deliberately. `.flight-table-container` is a
   bounded scrollbox on both axes, and an absolutely-positioned popover inside
   it is CLIPPED — the exact failure T3-C round 2 measured, which a z-index
   cannot fix. Growing the row is the version that cannot be swallowed. */
.trips-slot-td .trips-pool-opt-confirm {
    width: max-content;
    max-width: 260px;
    white-space: normal;
}

.trips-slot-td .trips-pool-opt-confirm[hidden] {
    display: none;
}

.trips-slot-td .trips-pool-opt-remove,
.trips-slot-td .trips-pool-note-btn {
    font-size: 0.62rem;
    padding: 1px 7px;
}

/* The note cell is prose, not a figure: it must not inherit the table's
   tabular numerals or its own column's width pressure. */
.trips-slot-td[data-slot-col="note"] {
    font-variant-numeric: normal;
    min-width: 130px;
}

.trips-slot-td .trips-pool-note-input {
    width: 100%;
    min-width: 120px;
}

/* The Undo that rides in the delta badge. It inherits the badge's own colour
   (up/down/error), so it never looks like a separate, unrelated control. */
.trips-verdict-delta {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.trips-verdict-delta-error {
    background: var(--aw-bad-dim);
    color: var(--aw-bad);
    border: 1px solid var(--aw-bad-dim);
    white-space: normal;
}

.trips-verdict-undo {
    font-family: inherit;
    font-size: 0.7rem;
    font-weight: 700;
    color: inherit;
    background: transparent;
    border: 1px solid currentColor;
    border-radius: var(--aw-radius-pill);
    padding: 1px 9px;
    cursor: pointer;
}

.trips-verdict-undo:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

/* The slot label on a health item: the quiet identity line above the check's
   own wording, matching what the canvas calls that leg. */
.trips-health-item-slot {
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--aw-muted);
    margin-bottom: 3px;
}

.trips-pool-headrow {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-bottom: 8px;
}

.trips-pool-head {
    font-size: 0.76rem;
    font-weight: 700;
    color: var(--aw-ink);
}

/* The leg overflow menu. Anchored to its trigger, and the pop is the only
   part that ever overlays anything. */
.trips-leg-menu {
    position: relative;
    display: inline-flex;
    margin-left: auto;
}

.trips-leg-menu-btn {
    font-family: inherit;
    font-size: 0.8rem;
    line-height: 1;
    color: var(--aw-muted);
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--aw-radius-pill);
    padding: 2px 8px;
    cursor: pointer;
}

.trips-leg-menu-btn:hover {
    color: var(--aw-ink);
    border-color: var(--aw-hairline-strong);
}

.trips-leg-menu-btn:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

.trips-leg-menu-pop {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    z-index: 30;
    min-width: 220px;
    max-width: 280px;
    padding: 8px;
    text-align: left;
    background: var(--aw-surface);
    border: 1px solid var(--aw-hairline-strong);
    border-radius: var(--aw-radius);
    box-shadow: 0 10px 28px rgb(0 0 0 / 18%);
}

/* The flip (#282): left-aligned to the trigger, opening rightward/inward.
   Written AFTER the base rule so equal-specificity `left`/`right` longhands
   win the cascade — trips.css puts its media queries last, so ordinary rules
   read top to bottom here (the chat.css hazard, avoided). Armed only by
   `_placeLegMenu`'s measurement, never by a side class. */
.trips-leg-menu-pop-flip {
    right: auto;
    left: 0;
}

.trips-leg-menu-pop[hidden] {
    display: none;
}

.trips-leg-menu-item {
    font-family: inherit;
    font-size: 0.74rem;
    font-weight: 600;
    color: var(--aw-ink);
    background: transparent;
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-sm);
    padding: 5px 10px;
    cursor: pointer;
}

.trips-leg-menu-item:hover {
    background: color-mix(in srgb, var(--aw-muted) 10%, transparent);
}

.trips-leg-menu-item:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

.trips-leg-menu-danger {
    color: var(--aw-bad);
    border-color: color-mix(in srgb, var(--aw-bad) 45%, transparent);
}

.trips-leg-menu-confirm {
    margin: 0 0 8px;
    font-size: 0.74rem;
    line-height: 1.45;
    color: var(--aw-ink);
}

.trips-leg-menu-actions {
    display: flex;
    gap: 8px;
}

.trips-leg-menu-error {
    font-size: 0.72rem;
    line-height: 1.45;
    color: var(--aw-bad);
}

.trips-leg-menu-error:empty {
    display: none;
}

/* ---------------------------------------------------------------------
   Trip OS T3-A — the re-hunt panel. It replaces the leg menu's contents
   inside the SAME popup, so it inherits the popup's surface, border and
   placement (including #282's measured flip) and adds only its own width
   and internals. Written after `.trips-leg-menu-pop` so the width override
   wins at equal specificity — trips.css keeps media queries last, so rules
   here read top to bottom (the chat.css cascade hazard, avoided).
   --------------------------------------------------------------------- */
.trips-leg-menu-pop-hunt {
    min-width: 288px;
    max-width: 320px;
}

.trips-hunt-head {
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--aw-ink);
}

.trips-hunt-scope {
    margin-top: 2px;
    font-size: 0.7rem;
    line-height: 1.45;
    color: var(--aw-muted);
}

/* The G2 date strip: one chip per date across the slot's date +/- 3. Wraps
   rather than scrolls — seven short chips fit two rows at the popup's width
   on every viewport this panel can open on. */
.trips-hunt-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 8px;
}

.trips-hunt-chip {
    font-family: inherit;
    font-size: 0.68rem;
    line-height: 1;
    color: var(--aw-muted);
    background: transparent;
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-pill);
    padding: 5px 8px;
    cursor: pointer;
}

.trips-hunt-chip:hover {
    color: var(--aw-ink);
    border-color: var(--aw-hairline-strong);
}

.trips-hunt-chip:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

/* The slot's OWN date, so the centre of the strip is findable at a glance
   even after the user has moved the selection off it. */
.trips-hunt-chip-base {
    font-weight: 700;
}

/* Defect 7 (#289): the slot's DECLARED fly range, leading the same
   radiogroup the days are in. It takes the whole first line so it reads as
   the answer the strip's days NARROW, not as an eighth date. */
.trips-hunt-chip-span {
    flex: 1 0 100%;
    font-weight: 700;
    color: var(--aw-ink);
    border-color: var(--aw-hairline-strong);
}

.trips-hunt-chip-on {
    color: var(--aw-surface);
    background: var(--aw-ink);
    border-color: var(--aw-ink);
}

/* Says what the days below the span chip are FOR — without it the strip
   reads as a question again, which is the defect. */
.trips-hunt-narrow {
    margin-top: 4px;
    font-size: 0.66rem;
    line-height: 1.45;
    color: var(--aw-muted);
}

.trips-hunt-summary {
    margin-top: 8px;
    font-size: 0.7rem;
    line-height: 1.45;
    color: var(--aw-ink);
}

/* Where the button goes. The hunt LEAVES this page, so the panel says so
   before it does — a control that navigates without warning reads as a bug. */
.trips-hunt-where {
    margin-top: 6px;
    font-size: 0.68rem;
    line-height: 1.45;
    color: var(--aw-muted);
}

.trips-hunt-quota {
    margin-top: 2px;
    font-size: 0.66rem;
    line-height: 1.45;
    color: var(--aw-muted);
}

/* The context chip that rides on the RESULTS (owner ruling: the table is the
   hunting surface). It mounts into whichever shell rendered them — the
   table-first body mount or the last chat bubble — so it is styled to sit
   above a results card in either, and it is the only piece of trips.css that
   ever paints outside the Trips view. */
.trips-hunt-context {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin: 0 0 10px;
    padding: 7px 10px;
    background: color-mix(in srgb, var(--aw-accent) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--aw-accent) 35%, transparent);
    border-radius: var(--aw-radius);
}

.trips-hunt-context-label {
    font-size: 0.74rem;
    font-weight: 700;
    line-height: 1.4;
    color: var(--aw-ink);
}

.trips-hunt-context-back {
    font-family: inherit;
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 1;
    color: var(--aw-accent);
    background: transparent;
    border: 1px solid color-mix(in srgb, var(--aw-accent) 45%, transparent);
    border-radius: var(--aw-radius-pill);
    padding: 5px 10px;
    margin-left: auto;
    cursor: pointer;
}

.trips-hunt-context-back:hover {
    background: color-mix(in srgb, var(--aw-accent) 16%, transparent);
}

.trips-hunt-context-back:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

.trips-hunt-actions {
    display: flex;
    gap: 8px;
    margin-top: 10px;
}

.trips-hunt-run[disabled] {
    cursor: progress;
    opacity: 0.6;
}

.trips-hunt-status,
.trips-hunt-error {
    margin-top: 8px;
    font-size: 0.7rem;
    line-height: 1.45;
}

.trips-hunt-status {
    color: var(--aw-muted);
}

.trips-hunt-error {
    color: var(--aw-bad);
}

.trips-hunt-status:empty,
.trips-hunt-error:empty {
    display: none;
}

/* ---------------------------------------------------------------------------
   Trip OS T3-D section A — the COMPACT TRIP HEADER (frame-7), which replaced
   T3-B's stacked verdict band + Anchors panel.

   Base rules only, and deliberately placed with the rest of them, BEFORE this
   file's media queries: trips.css keeps every @media last so an equal-
   specificity override reads top to bottom (the chat.css cascade hazard this
   codebase has been bitten by three times). The one @container block is the
   exception the rule permits and sits with the media queries at the foot.
   --------------------------------------------------------------------------- */

/* The band wraps on ITS OWN inline width, not the viewport's, so a narrow rail
   or a split pane gets the behaviour a narrow phone gets. The wrap exists for
   exactly that: `@container` styles a container's DESCENDANTS, never the
   container itself, so the band cannot be its own query container.

   THE PIN LIVES HERE, NOT ON THE BAND (Copilot r1 on #301). A sticky element
   only travels inside its own containing block, and the band's is this wrap —
   which hugs it, since its only other children are a hidden form host and an
   `:empty` error slot. Zero slack, so `position: sticky` on the band computed
   correctly, reported correctly, and pinned nothing: a silent regression of
   the pre-T3-D `.trips-verdict`, which was a direct child of the tall
   `.trips-detail`. Moved up one level, the wrap's containing block IS that
   tall container again and the pin works.

   `container-type` and `position: sticky` coexist on this element — measured
   by actually scrolling a real Chrome, not assumed: containment governs the
   element's descendants, not where the element itself sits in its parent.
   Both properties are asserted in ONE scroll, because the reason the wrap
   exists is the query and the reason it is sticky is the pin.

   The open anchor form pins WITH the band, since it is inside the wrap. That
   is deliberate: it is a transient editing state, and keeping the trip in view
   while its anchor is edited is the better half of the trade. */
.trips-header-wrap {
    container-type: inline-size;
    position: sticky;
    /* NOT 0. A sticky element pins to its scrollport's PADDING box, and the
       scrollport here is `.trips-view`, which carries 20px of top padding
       (chat.css). At `top: 0` the pinned band therefore floated 20px down and
       the timeline scrolled through the strip above it — measured at 1440:
       `GAP 20px`, with `elementFromPoint` in the strip returning
       `DIV.trips-axis-cell`, i.e. real content, not a rendering artifact.
       Cancelling the scrollport's own padding puts the band on the top edge.
       The fallback keeps any other host (the proof harness, a future embed)
       behaving exactly as before. */
    top: calc(-1 * var(--trips-scrollport-pad-top, 0px));
    z-index: 5;
    margin: 0 0 20px;
}

/* Mobile polish item 2 (2026-08-23 brief §2, owner ruling "collapse to the
   top"): the one-line summary that takes over the sticky duty from the full
   panel above once it scrolls out of the `.trips-view` scrollport. `display:
   none` here — the base rule, evaluated everywhere — is what keeps this
   inert off mobile; the `@media (max-width: 700px)` block at the foot of
   this file (after every base rule, so it wins the equal-specificity tie —
   see the `.trips-header-wrap` cascade note there) is the ONLY place that
   turns it on and the ONLY place `.trips-header-wrap` itself stops being
   sticky. A SIBLING of `.trips-header-wrap`, not its child (trips.js
   `_renderDetailShell`) — its containing block has to be `.trips-detail`,
   the same tall box the wrap's own pin depends on, or it has almost no room
   to travel before running out of parent. */
.trips-verdict-condensed {
    display: none;
}

.trips-header {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(380px, 520px);
    column-gap: 18px;
    padding: 14px 16px;
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius);
    background: var(--aw-elevated);
    box-shadow: var(--aw-shadow);
}

/* No anchors zone (the read-only sample trip): the metrics take the band. */
.trips-header-solo {
    grid-template-columns: minmax(0, 1fr);
}

/* --- zone 1: the verdict. Content unchanged, item for item. --------------- */

.trips-header-verdict {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.trips-header-metrics {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 18px;
}

/* `margin-top: auto` parks the staleness line on the band's floor, which is
   what equalises the two zones and keeps the one band shorter than the verdict
   band alone used to be. */
.trips-header-stale {
    margin-top: auto;
}

/* --- zone 2: the anchors -------------------------------------------------- */

.trips-header-anchors {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
    padding-left: 18px;
    border-left: 1px solid var(--aw-hairline);
}

.trips-header-anchors-head {
    display: flex;
    align-items: center;
    gap: 10px;
}

.trips-header-anchors-title {
    margin: 0;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--aw-muted);
}

.trips-header-anchors-empty {
    margin: 0;
    font-size: 0.7rem;
    line-height: 1.4;
    color: var(--aw-muted);
}

.trips-header-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

/* An anchor is the fixed spine of a trip, so it takes the spine's gold. The
   left rail is the same 3px inset the axis anchor card uses. */
.trips-anchor-chip {
    position: relative;
    flex: 1 1 240px;
    min-width: 0;
    padding: 7px 10px 7px 12px;
    border: 1px solid color-mix(in srgb, var(--aw-best) 34%, transparent);
    border-radius: var(--aw-radius-sm);
    background: color-mix(in srgb, var(--aw-best) 7%, transparent);
    box-shadow: inset 3px 0 0 0 color-mix(in srgb, var(--aw-best) 70%, transparent);
}

.trips-anchor-chip-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.trips-anchor-chip-title {
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--aw-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The TYPE lives here, on the chip — never in the action label, which is why
   "+ Add an event" became "+ Add ▾ → Anchor". */
/* Right-aligned (round 3), and that is load-bearing rather than cosmetic: the
   Unlink is absolute at the chip's right edge, so parking the tag there too
   means the button always lands on exactly ONE thing — the tag's own slot,
   which it then swaps with. Left-packed, the tag sat mid-row on a short title
   and at the row's end on a long one, so the same button covered nothing in
   one chip and half the tag in the next. */
.trips-anchor-chip-tag {
    flex: none;
    margin-left: auto;
    min-width: 3.4rem;
    text-align: center;
    font-size: 0.58rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--aw-best);
    padding: 1px 6px;
    border: 1px solid color-mix(in srgb, var(--aw-best) 40%, transparent);
    border-radius: var(--aw-radius-pill);
}

/* Unlink is demoted: revealed on hover / focus-within, so the resting chip is
   the fact and nothing else. Keyboard reaches it through :focus-within.

   T3-D round 3: it is ABSOLUTE, and that is the point. `opacity: 0` hides a
   control without releasing its box, so an in-flow Unlink charged every chip
   48px + an 8px gap it never showed anything in — 56px taken from the one
   thing a chip exists to say. Out of flow, its resting state costs nothing;
   revealed, it lands on the type tag's own slot (below), so nothing reflows
   and nothing is covered that is still being read. */
.trips-anchor-chip-unlink {
    position: absolute;
    top: 6px;
    right: 10px;
    z-index: 1;
    flex: none;
    font-family: inherit;
    font-size: 0.66rem;
    font-weight: 600;
    padding: 1px 7px;
    color: var(--aw-muted);
    background: transparent;
    border: 1px solid var(--aw-hairline-strong);
    border-radius: var(--aw-radius-pill);
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.12s;
}

.trips-anchor-chip:hover .trips-anchor-chip-unlink,
.trips-anchor-chip:focus-within .trips-anchor-chip-unlink {
    opacity: 1;
}

/* The tag yields its slot to the action that lands on it. `visibility` and not
   `display`, so the row's geometry is identical in both states: the title is
   never re-measured, so it can never re-truncate under the pointer. */
.trips-anchor-chip:hover .trips-anchor-chip-tag,
.trips-anchor-chip:focus-within .trips-anchor-chip-tag {
    visibility: hidden;
}

.trips-anchor-chip-unlink:hover {
    color: var(--aw-ink);
}

.trips-anchor-chip-sub {
    margin-top: 2px;
    font-size: 0.68rem;
    line-height: 1.3;
    color: var(--aw-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* 2+ anchors: every chip collapses to one line and the propagation moves to
   the tooltip.
   T3-D round 3 — THE STARVATION FIX. Rounds 1-2 fought the band's height by
   narrowing the chips (`flex: 1 1 150px`), and won the number while losing the
   point: two chips sharing a 520px column are ~248px wide, of which the type
   tag and the (invisible, in-flow) Unlink took 160px, leaving the anchor's
   NAME 64px. Every two-anchor trip rendered "📌 EMN…", and multi mode hides
   the sub-line, so the zone named none of its anchors.
   One chip per row is the version that can be read: a zone titled "Anchors" is
   a LIST of them, and the full column (~500px at 1440, ~900px stacked) fits
   the name, its dates and the tag with room to spare. The second row is bought
   back from the tighter padding below and from the "+N more" pill, which moved
   up into the zone's head row — it is a view control about the zone, not a
   chip, and out of the flow it cannot claim a row of its own. */
.trips-header-chips-multi .trips-anchor-chip {
    flex: 1 1 100%;
    padding-top: 5px;
    padding-bottom: 5px;
}

.trips-header-chips-multi {
    gap: 5px;
}

.trips-header-chips-multi .trips-anchor-chip-sub {
    display: none;
}

/* In the zone's head row (round 3), beside the "Anchors" title it counts. */
.trips-anchor-chip-more {
    flex: none;
    align-self: center;
    font-family: inherit;
    font-size: 0.66rem;
    font-weight: 600;
    padding: 2px 8px;
    color: var(--aw-ink);
    background: transparent;
    border: 1px solid var(--aw-hairline-strong);
    border-radius: var(--aw-radius-pill);
    cursor: pointer;
}

/* --- the ONE add cluster -------------------------------------------------- */

.trips-add-wrap {
    position: relative;
    margin-left: auto;
}

.trips-add {
    font-family: inherit;
    font-size: 0.74rem;
    font-weight: 600;
    padding: 3px 10px;
    color: var(--aw-ink);
    background: transparent;
    border: 1px solid var(--aw-hairline-strong);
    border-radius: var(--aw-radius-pill);
    cursor: pointer;
}

.trips-add:hover {
    border-color: var(--aw-accent);
}

.trips-add-caret {
    margin-left: 4px;
    opacity: 0.75;
}

/* Right-edge aligned: the cluster it hangs from is the band's top-right. The
   layer is the trip menu's (41), above the leg cards and the axis bands; the
   handler closes any leg ⋯ first, so two popups never race. */
.trips-add-menu {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 41;
    width: 250px;
    padding: 5px;
    border: 1px solid var(--aw-hairline-strong);
    border-radius: var(--aw-radius-sm);
    background: var(--aw-surface);
    box-shadow: var(--aw-shadow);
}

.trips-add-menu[hidden] {
    display: none;
}

/* THE MOUNTED STATE (independent verifier D1 on #308). In the rail the
   cluster sits inside `.trips-rail-block` (`overflow: hidden`, to clip its own
   rounded corners) inside a rail that is `overflow-y: auto`. Both CLIP, and a
   clip cannot be out-ranked by a z-index — measured, the level-2 type menu
   overflowed by 25px and its third row was not painted at all, with
   `elementFromPoint` at that row's centre returning the rail behind it.

   So trips.js reparents the open menu to <body> (the `_mountPopover` pattern
   trip-picker.js established for the same failure inside the results table's
   scrollbox) and writes VIEWPORT coordinates into `top`/`left`, which is what
   this modifier gives it the coordinate space for.

   Declared AFTER the base rule on purpose: same specificity, so source order
   is what makes `position: fixed` win (the chat.css cascade lesson).

   The layer sits with trip-picker's own popover at 990 — above everything the
   trips page can raise, below the save toast (999) and the app's modals. */
.trips-add-menu-fixed {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 990;
}

.trips-add-menu-item {
    display: flex;
    align-items: baseline;
    gap: 8px;
    width: 100%;
    padding: 7px 9px;
    font-family: inherit;
    font-size: 0.8rem;
    font-weight: 600;
    text-align: left;
    color: var(--aw-ink);
    background: transparent;
    border: 0;
    border-radius: 6px;
    cursor: pointer;
}

.trips-add-menu-item:hover {
    background: var(--aw-surface-2);
}

.trips-add-menu-item[disabled] {
    color: var(--aw-muted);
    cursor: default;
}

.trips-add-menu-item[disabled]:hover {
    background: transparent;
}

.trips-add-menu-note {
    font-size: 0.68rem;
    font-weight: 400;
    color: var(--aw-muted);
}

.trips-add-menu-caret {
    margin-left: auto;
    color: var(--aw-muted);
}

.trips-add-menu-head {
    padding: 6px 9px 4px;
    font-size: 0.62rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--aw-muted);
}

/* --- the unlink confirm, as a popover under its chip ---------------------- */

.trips-anchor-confirm {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    z-index: 41;
    padding: 9px 11px;
    border: 1px solid var(--aw-hairline-strong);
    border-radius: var(--aw-radius-sm);
    background: var(--aw-surface);
    box-shadow: var(--aw-shadow);
}

.trips-anchor-confirm[hidden] {
    display: none;
}

.trips-anchor-confirm-text {
    margin: 0 0 8px;
    font-size: 0.72rem;
    line-height: 1.45;
    color: var(--aw-ink);
}

.trips-anchor-confirm-actions {
    display: flex;
    gap: 8px;
}

.trips-anchor-confirm-danger,
.trips-anchor-confirm-keep,
.trips-anchor-save,
.trips-anchor-cancel {
    font-family: inherit;
    font-size: 0.74rem;
    font-weight: 600;
    padding: 4px 12px;
    border-radius: var(--aw-radius-pill);
    border: 1px solid var(--aw-hairline-strong);
    background: transparent;
    color: var(--aw-ink);
    cursor: pointer;
}

.trips-anchor-confirm-danger:hover {
    color: var(--aw-bad);
    border-color: var(--aw-bad);
}

.trips-add:focus-visible,
.trips-anchor-chip-unlink:focus-visible,
.trips-anchor-chip-more:focus-visible,
.trips-slot-rename-btn:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

.trips-anchors-error,
.trips-anchor-confirm-error,
.trips-anchor-form-error,
.trips-slot-rename-error {
    font-size: 0.72rem;
    line-height: 1.45;
    color: var(--aw-bad);
}

.trips-anchors-error:empty,
.trips-anchor-confirm-error:empty,
.trips-anchor-form-error:empty,
.trips-slot-rename-error:empty {
    display: none;
}

/* The add-anchor form hangs UNDER the band, full width: its five fields have
   no business inside a 520px column. */
.trips-anchor-form {
    margin-top: 10px;
    padding: 12px 14px;
    background: var(--aw-surface);
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius);
}

.trips-anchor-form[hidden] {
    display: none;
}

/* T3-D section B: the TYPE this form is collecting, so its event-named fields
   read as one way of declaring an anchor rather than as anchor vocabulary. */
.trips-anchor-form-type {
    margin-bottom: 10px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--aw-best);
}

/* auto-fit, not a fixed column count: the panel is the same component on a
   phone and on the 1440 canvas. */
.trips-anchor-form-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 10px;
}

.trips-anchor-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--aw-muted);
}

.trips-anchor-input {
    font-family: inherit;
    font-size: 0.8rem;
    font-weight: 400;
    text-transform: none;
    letter-spacing: normal;
    padding: 6px 8px;
    color: var(--aw-ink);
    background: var(--aw-surface);
    border: 1px solid var(--aw-hairline-strong);
    border-radius: var(--aw-radius-sm);
}

.trips-anchor-form-note {
    margin: 8px 0 0;
    font-size: 0.72rem;
    line-height: 1.45;
    color: var(--aw-muted);
}

.trips-anchor-form-actions {
    display: flex;
    gap: 8px;
    margin-top: 10px;
}

/* The slot title: "Leg 1 ·" as fixed chrome, the name beside it, and the ✎
   that edits ONLY the name — one component on every surface that names a leg
   (round 3, owner-caught: the ✎ had been parked in the card foot, away from
   the title it renames). `inline-flex` + `wrap` so the rename editor, which
   replaces the name inside this same element, can take its own line in a
   narrow axis card without pushing the ordinal off. */
.trips-slot-title {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    min-width: 0;
}

/* The ordinal is systemic, never editable, and deliberately quieter than the
   name the user owns. */
.trips-slot-ordinal {
    color: var(--aw-muted);
    font-weight: 600;
    white-space: nowrap;
}

.trips-slot-name {
    min-width: 0;
    overflow-wrap: anywhere;
}

/* The rename pencil sits beside the name it renames, inside the title. */
.trips-slot-rename-btn {
    font-family: inherit;
    font-size: 0.72rem;
    line-height: 1;
    padding: 2px 6px;
    color: var(--aw-muted);
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--aw-radius-pill);
    cursor: pointer;
}

.trips-slot-rename-btn:hover {
    color: var(--aw-ink);
    border-color: var(--aw-hairline-strong);
}

.trips-slot-rename {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

.trips-slot-rename-input {
    font-family: inherit;
    font-size: 0.78rem;
    padding: 4px 8px;
    min-width: 180px;
    color: var(--aw-ink);
    background: var(--aw-surface);
    border: 1px solid var(--aw-accent);
    border-radius: var(--aw-radius-sm);
}

.trips-slot-rename-save,
.trips-slot-rename-cancel {
    font-family: inherit;
    font-size: 0.72rem;
    font-weight: 600;
    padding: 3px 10px;
    color: var(--aw-ink);
    background: transparent;
    border: 1px solid var(--aw-hairline-strong);
    border-radius: var(--aw-radius-pill);
    cursor: pointer;
}

/* The axis is a >=1100px layout and trips.js will not paint it below that.
   This is the belt-and-braces half of the same rule: if a viewport ever gets
   here with axis markup already in the DOM (a resize mid-render), the canvas
   degrades to a single readable column instead of three unusable slivers. */
@media (max-width: 1099px) {
    .trips-axis-cols {
        grid-template-columns: minmax(0, 1fr);
    }

    .trips-axis-band {
        grid-template-columns: minmax(0, 1fr);
        min-height: 0;
    }

    .trips-axis-cell-left,
    .trips-axis-cell-right {
        grid-column: 1;
        padding-left: 0;
        padding-right: 0;
    }

    .trips-axis-cell-filled::before,
    .trips-axis-dot,
    .trips-axis-line::before {
        display: none;
    }
}

/* =====================================================================
 * Trip OS T3-C — anchor-first creation, empty slots, collapsed clusters.
 * Follows docs/product/mockups/trip-os-creation/_trip-os.css (frames 1
 * and 2), translated onto this file's own class names and tokens.
 * =================================================================== */

.trips-new-crumb {
    margin-bottom: 6px;
}

.trips-new-title {
    margin: 0 0 4px;
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--aw-ink);
}

.trips-new-sub {
    margin: 0 0 20px;
    font-size: 0.85rem;
    line-height: 1.5;
    color: var(--aw-muted);
    max-width: 62ch;
}

.trips-anchor-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 14px;
    margin-bottom: 24px;
}

.trips-anchor-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 18px 18px 16px;
    background: var(--aw-surface);
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius);
}

.trips-anchor-glyph { font-size: 1.5rem; line-height: 1; }

.trips-anchor-name {
    font-weight: 650;
    font-size: 1rem;
    color: var(--aw-ink);
}

.trips-anchor-desc {
    font-size: 0.82rem;
    line-height: 1.45;
    color: var(--aw-muted);
}

.trips-anchor-card.is-active {
    border-color: var(--aw-brand);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--aw-brand) 30%, transparent);
    background: color-mix(in srgb, var(--aw-brand) 6%, var(--aw-surface));
}

.trips-anchor-check {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--aw-brand);
    color: var(--aw-on-accent);
    font-size: 0.72rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* "coming later" is a STATE, not a button: recessed, uninteractive, and
   labelled — the vision stays visible without pretending to be built. */
.trips-anchor-card.is-later {
    opacity: 0.55;
    cursor: default;
}

.trips-anchor-later {
    position: absolute;
    top: 12px;
    right: 12px;
    font-size: 0.62rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--aw-muted);
    border: 1px dashed var(--aw-hairline-strong);
    border-radius: var(--aw-radius-pill);
    padding: 2px 8px;
}

.trips-event-form {
    background: var(--aw-surface);
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius);
    padding: 22px 24px 24px;
}

.trips-event-head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 18px;
}

.trips-event-title {
    margin: 0;
    font-size: 1.05rem;
    color: var(--aw-ink);
}

.trips-event-hint {
    font-size: 0.78rem;
    color: var(--aw-muted);
}

.trips-new-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px 22px;
}

.trips-new-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.trips-new-label {
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--aw-muted);
}

.trips-new-input {
    box-sizing: border-box;
    width: 100%;
    padding: 9px 12px;
    background: var(--aw-ground-2);
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-sm);
    font-family: inherit;
    font-size: 0.92rem;
    color: var(--aw-ink);
}

.trips-new-input:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 1px;
}

.trips-new-datepair {
    display: flex;
    align-items: center;
    gap: 8px;
}

.trips-new-to {
    color: var(--aw-muted);
    font-size: 0.82rem;
}

.trips-new-seg {
    display: inline-flex;
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-sm);
    overflow: hidden;
    background: var(--aw-ground-2);
    align-self: flex-start;
}

.trips-new-seg-btn {
    appearance: none;
    border: none;
    background: transparent;
    color: var(--aw-muted);
    font: inherit;
    font-size: 0.84rem;
    font-weight: 600;
    padding: 8px 14px;
    cursor: pointer;
    border-right: 1px solid var(--aw-hairline);
}

.trips-new-seg-btn:last-child { border-right: none; }

.trips-new-seg-btn.is-active {
    background: color-mix(in srgb, var(--aw-brand) 18%, transparent);
    color: var(--aw-ink);
}

/* The derived blocks span the grid: they are OUTPUTS, and they read as ones. */
.trips-new-preview-slot,
.trips-new-derived-slot {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.trips-new-derived {
    border-left: 3px solid var(--aw-best);
    background: var(--aw-best-dim);
    border-radius: 0 var(--aw-radius-sm) var(--aw-radius-sm) 0;
    padding: 12px 16px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

/* T4-E: the label is now the sentence opener "So:", not a shouted section
   heading — so the uppercase transform (which would render it "SO:") goes with
   the old wording. Size and weight stay: it is still the block's lead. */
.trips-new-derived-label {
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--aw-best);
}

.trips-new-derived-line {
    font-family: var(--aw-font-mono);
    font-size: 0.85rem;
    color: var(--aw-ink);
}

.trips-new-derived-empty {
    border-left-color: var(--aw-hairline-strong);
    background: var(--aw-ground-2);
    color: var(--aw-muted);
    font-size: 0.82rem;
}

.trips-new-derived-error {
    border-left-color: var(--aw-bad, #e04b4b);
    background: color-mix(in srgb, var(--aw-bad, #e04b4b) 8%, transparent);
    color: var(--aw-ink);
    font-size: 0.82rem;
}

.trips-new-windows {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
}

.trips-new-window-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 7px 14px;
    border: 1px dashed var(--aw-hairline-strong);
    border-radius: var(--aw-radius-pill);
    font-size: 0.8rem;
    color: var(--aw-ink-dim);
    background: var(--aw-ground-2);
}

.trips-new-window-k {
    font-size: 0.66rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--aw-accent);
}

.trips-new-window-v { font-family: var(--aw-font-mono); }

.trips-new-slots {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.trips-new-slots-label {
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--aw-muted);
}

.trips-new-slot-row {
    font-size: 0.82rem;
    color: var(--aw-ink-dim);
}

.trips-new-actions {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 14px;
    margin-top: 6px;
}

.trips-new-create {
    font-size: 0.92rem;
    padding: 11px 22px;
}

.trips-new-create[disabled] {
    opacity: 0.6;
    cursor: default;
}

.trips-new-afternote {
    font-size: 0.78rem;
    color: var(--aw-muted);
    max-width: 46ch;
}

.trips-new-escape {
    grid-column: 1 / -1;
    justify-self: start;
    appearance: none;
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    font-size: 0.8rem;
    color: var(--aw-muted);
    text-decoration: underline;
    cursor: pointer;
}

.trips-new-error {
    grid-column: 1 / -1;
    margin: 0;
    font-size: 0.8rem;
    color: var(--aw-bad, #e04b4b);
}

/* ---- the empty slot's hunt door (frame 2) --------------------------- */

.trips-slot-hunt {
    position: relative;
    display: block;
    margin-top: 10px;
}

.trips-slot-hunt-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 12px;
    border: 1px solid color-mix(in srgb, var(--aw-accent) 45%, transparent);
    border-radius: var(--aw-radius-sm);
    background: color-mix(in srgb, var(--aw-accent) 10%, transparent);
    color: var(--aw-accent);
    font: inherit;
    font-size: 0.78rem;
    font-weight: 600;
    cursor: pointer;
}

.trips-slot-hunt-btn:hover { border-color: var(--aw-accent); }

.trips-slot-hunt-btn:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

/* An empty slot says so beside its "—": the price is unknown because
   nothing has been hunted, which is a state, not a missing value. */
.trips-chip-unhunted {
    color: var(--aw-muted);
    border-color: var(--aw-hairline-strong);
}

/* ---- editing a slot's dates and declaring its route (#289) ---------- */

.trips-slot-date-btn {
    appearance: none;
    background: none;
    border: none;
    padding: 0 0 0 4px;
    font: inherit;
    font-size: 0.78em;
    line-height: 1;
    color: var(--aw-muted);
    cursor: pointer;
}

.trips-slot-date-btn:hover { color: var(--aw-accent); }

.trips-slot-date-btn:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

/* The same pencil, beside the route it edits (owner QA round 2, #289 — a
   declared route is the traveller's own statement, so it stays editable).
   Sized off the route line's own type, which is larger than the meta line's,
   so it reads as the route's pencil rather than a second control. */
.trips-slot-route-btn {
    appearance: none;
    background: none;
    border: none;
    padding: 0 0 0 6px;
    font: inherit;
    font-size: 0.7em;
    line-height: 1;
    color: var(--aw-muted);
    cursor: pointer;
    vertical-align: middle;
}

.trips-slot-route-btn:hover { color: var(--aw-accent); }

.trips-slot-route-btn:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

/* Why an edit was refused, said where the control would have been. */
.trips-slot-refusal {
    display: block;
    margin-top: 4px;
    font-size: 0.78rem;
    font-weight: 400;
    line-height: 1.45;
    color: var(--aw-muted);
}

/* An undeclared route is a CONTROL, not a "— → —": it states the absence and
   offers the way to fill it in the same place. */
.trips-slot-declare {
    appearance: none;
    padding: 4px 10px;
    border: 1px dashed color-mix(in srgb, var(--aw-accent) 50%, transparent);
    border-radius: var(--aw-radius-sm);
    background: transparent;
    color: var(--aw-accent);
    font: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
}

.trips-slot-declare:hover { border-style: solid; }

.trips-slot-declare:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

.trips-slot-editor {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
}

.trips-slot-editor-input {
    box-sizing: border-box;
    width: 9.5rem;
    padding: 4px 8px;
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-sm);
    background: var(--aw-ground-2);
    color: var(--aw-ink);
    font: inherit;
    font-size: 0.85rem;
}

/* A DATE is picked, not typed as a caption (owner QA round 2, #289). The
   native control carries its own calendar, so the field only has to be wide
   enough for it and to sit on the card's own type scale. */
.trips-slot-editor-date {
    width: auto;
    min-width: 8.5rem;
    font-size: 0.8rem;
}

.trips-slot-editor-save,
.trips-slot-editor-cancel {
    appearance: none;
    padding: 4px 10px;
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-sm);
    background: var(--aw-surface);
    color: var(--aw-ink);
    font: inherit;
    font-size: 0.8rem;
    cursor: pointer;
}

.trips-slot-editor-save {
    border-color: color-mix(in srgb, var(--aw-accent) 45%, transparent);
    color: var(--aw-accent);
}

.trips-slot-editor-error {
    flex-basis: 100%;
    font-size: 0.78rem;
    color: var(--aw-bad, #e04b4b);
}

/* One line saying what the save actually does. The date edit moves the hunt
   window with it, and an editor that changes more than the words it replaced
   has to say so. */
.trips-slot-editor-hint {
    flex-basis: 100%;
    font-size: 0.75rem;
    line-height: 1.4;
    color: var(--aw-muted);
}

/* ---- adding a slot to the trip (#289, owner-caught mid-round) ------- */

.trips-slot-add {
    margin: 18px 0 4px;
}

/* T3-D round 2: on a trip that HAS legs this block is the declare form's mount
   point directly under the header band, and it holds nothing else. Closed, it
   must occupy NOTHING — an 18px gap between the header and the first leg,
   present only on a legged trip, would be a layout change nobody asked for.
   `:has()` keeps the empty state's own copy of the block (which always has
   visible content) at its normal spacing. */
.trips-slot-add:not(:has(.trips-slot-empty)) {
    margin: 0;
}

.trips-slot-add:not(:has(.trips-slot-empty)) .trips-slot-add-form:not([hidden]) {
    margin-top: 18px;
    margin-bottom: 18px;
}

.trips-slot-add-btn,
.trips-slot-derive-btn {
    appearance: none;
    padding: 7px 14px;
    border: 1px dashed color-mix(in srgb, var(--aw-accent) 50%, transparent);
    border-radius: var(--aw-radius-sm);
    background: transparent;
    color: var(--aw-accent);
    font: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
}

.trips-slot-add-btn:hover,
.trips-slot-derive-btn:hover { border-style: solid; }

.trips-slot-add-btn:focus-visible,
.trips-slot-derive-btn:focus-visible {
    outline: 2px solid var(--aw-accent);
    outline-offset: 2px;
}

/* The offer is the SECOND choice on an anchored empty trip: solid where the
   declare door is dashed, because it writes a whole frame at once. */
.trips-slot-derive-btn {
    border-style: solid;
    border-color: var(--aw-hairline-strong);
    color: var(--aw-ink);
}

/* An empty trip's only content: what a slot is, and the two ways to get one. */
.trips-slot-empty {
    padding: 18px 18px 20px;
    border: 1px dashed var(--aw-hairline-strong);
    border-radius: var(--aw-radius-md, 10px);
    background: var(--aw-ground-2);
}

.trips-slot-empty-lead {
    margin: 0 0 14px;
    max-width: 56ch;
    font-size: 0.86rem;
    line-height: 1.55;
    color: var(--aw-muted);
}

.trips-slot-empty-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.trips-slot-add-form {
    display: flex;
    flex-wrap: wrap;
    gap: 10px 14px;
    margin-top: 12px;
    padding: 14px;
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-sm);
    background: var(--aw-surface);
}

/* T3-C SHIPPED THIS CLOSED FORM VISIBLE. `display: flex` above is an AUTHOR
   rule and beats the UA sheet's `[hidden] { display: none }`, so `form.hidden =
   true` hid nothing: every trip page has been carrying an empty bordered 30px
   box since #289. It sat below the last leg at the foot of a long spine, which
   is why nobody saw it — round 2 moved the block under the header band and the
   proof capture measured `closed form host: 1408x30` immediately.
   `.trips-anchor-form[hidden]` already carries exactly this rule, which is why
   THAT form really is hidden. */
.trips-slot-add-form[hidden] {
    display: none;
}

.trips-slot-add-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 0.72rem;
    color: var(--aw-muted);
}

.trips-slot-add-input {
    box-sizing: border-box;
    width: 11rem;
    padding: 5px 8px;
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-sm);
    background: var(--aw-ground-2);
    color: var(--aw-ink);
    font: inherit;
    font-size: 0.85rem;
}

.trips-slot-add-actions {
    display: flex;
    align-items: flex-end;
    gap: 8px;
}

/* T3-D section B: what a slot IS, once, before the fields that declare one.
   It leads the form; the hint below answers the different question of what
   happens after you press Add. */
.trips-slot-add-teach {
    flex-basis: 100%;
    margin: 0 0 4px;
    font-size: 0.78rem;
    line-height: 1.45;
    color: var(--aw-ink-dim, var(--aw-ink));
}

.trips-slot-add-hint {
    flex-basis: 100%;
    margin: 0;
    font-size: 0.75rem;
    line-height: 1.45;
    color: var(--aw-muted);
}

.trips-slot-add-error {
    margin-top: 8px;
    font-size: 0.78rem;
    color: var(--aw-bad, #e04b4b);
}

/* T3-D round 2: an empty error slot still cost its line-height and its 8px,
   which was invisible at the foot of the spine and is a 30px hole between the
   header band and the first leg now that the block lives there. Measured in
   real Chromium, not inferred. Same `:empty` collapse the anchors' own error
   slots use. */
.trips-slot-add-error:empty {
    display: none;
}

/* A stay slot gets a sentence, never a control — lodging is not built. */
.trips-slot-hunt-note {
    margin-top: 8px;
    font-size: 0.78rem;
    line-height: 1.45;
    color: var(--aw-muted);
}

/* ---- collapsed cluster --------------------------------------------- */

/* The toggle carries a caret so the pill reads as expandable, not as a
   label that happens to be clickable. */
.trips-axis-slot-toggle::after {
    content: ' ▾';
    font-size: 0.7em;
}

.trips-axis-cluster-open .trips-axis-slot-toggle::after {
    content: ' ▴';
}

/* The card's own route line, when the slot's TITLE right above already
   says it (an unnamed slot's proposed name IS its route). Recedes; never
   disappears, so the airports stay readable.

   F1 added the same line to the CLUSTER (a pooled slot had no route line and
   therefore no route ✎ at all), where it is a direct child of
   `.trips-axis-cluster` rather than of a `.trips-leg-card` — so the recession
   has to name that placement too or the pooled slot would shout its route
   twice. */
.trips-axis-slot-dup .trips-leg-card > .trips-leg-route,
.trips-axis-slot-dup .trips-axis-cluster > .trips-leg-route {
    font-size: 0.86rem;
    font-weight: 500;
    color: var(--aw-muted);
}

/* F1: the slot's own two declarations on the pooled surfaces. The route line
   sits directly under the head row (which is `align-items: baseline`, so it
   needs its own top margin to clear the pill) and the date line is the
   existing `.trips-axis-slot-sub`, whose margins already hold. */
.trips-axis-cluster > .trips-leg-route,
.trips-slot-table-identity > .trips-leg-route {
    margin-top: 2px;
}

/* The drill-in is a full-width takeover: while it is open it is the ONLY
   place the slot reads, so it states the same identity the cluster does. */
.trips-slot-table-identity {
    padding: 0 4px 10px;
}
.trips-slot-table-identity .trips-axis-slot-sub {
    margin-bottom: 0;
}

@media (max-width: 720px) {
    .trips-new-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .trips-new-datepair {
        flex-wrap: wrap;
    }
}

/* ---------------------------------------------------------------------------
   Trip OS T3-D section A — the compact header's wrap rule.

   A CONTAINER query, not a media query: the band wraps on its own inline
   width, so a narrow rail or a split pane behaves the way a phone does and the
   rule cannot be defeated by a wide viewport holding a narrow column. Placed
   at the foot with the media queries, after every base rule it overrides.
   --------------------------------------------------------------------------- */
@container (max-width: 1000px) {
    .trips-header {
        grid-template-columns: minmax(0, 1fr);
    }

    /* The staleness line stops being the floor and sits under the numbers. */
    .trips-header-stale {
        margin-top: 8px;
    }

    .trips-header-anchors {
        padding-left: 0;
        border-left: 0;
        margin-top: 10px;
        padding-top: 10px;
        border-top: 1px solid var(--aw-hairline);
    }
}

/* B-3 Booked lifecycle — the Mark-booked sheet (a centered modal). */
.trips-booking-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: rgba(0, 0, 0, 0.5);
}

.trips-booking-sheet {
    width: min(420px, 100%);
    max-height: 90vh;
    overflow-y: auto;
    background: var(--aw-surface);
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-md, 12px);
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
    padding: 20px;
}

.trips-booking-head {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--aw-ink);
    margin-bottom: 14px;
}

.trips-booking-seg {
    display: flex;
    gap: 6px;
    background: var(--aw-ground-2);
    border-radius: 999px;
    padding: 3px;
    margin-bottom: 14px;
}

.trips-booking-seg-btn {
    flex: 1;
    border: 0;
    background: transparent;
    color: var(--aw-muted);
    font-size: 0.82rem;
    font-weight: 650;
    padding: 7px 10px;
    border-radius: 999px;
    cursor: pointer;
}

.trips-booking-seg-on {
    background: var(--aw-choice);
    color: var(--aw-ground);
}

.trips-booking-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 0.76rem;
    color: var(--aw-muted);
    margin-bottom: 10px;
}

.trips-booking-input {
    font-size: 0.9rem;
    color: var(--aw-ink);
    background: var(--aw-ground-2);
    border: 1px solid var(--aw-hairline);
    border-radius: var(--aw-radius-sm);
    padding: 8px 10px;
}

.trips-booking-input:focus {
    outline: 2px solid var(--aw-choice);
    outline-offset: -1px;
}

.trips-booking-pay {
    display: flex;
    gap: 6px;
    margin-bottom: 10px;
}

.trips-booking-pay-btn {
    flex: 1;
    border: 1px solid var(--aw-hairline);
    background: transparent;
    color: var(--aw-muted);
    font-size: 0.78rem;
    font-weight: 650;
    padding: 6px 10px;
    border-radius: var(--aw-radius-sm);
    cursor: pointer;
}

.trips-booking-pay-on {
    border-color: var(--aw-best);
    color: var(--aw-best);
    background: color-mix(in srgb, var(--aw-best) 12%, transparent);
}

.trips-booking-note {
    font-size: 0.74rem;
    color: var(--aw-muted);
    margin: 8px 0 14px;
}

.trips-booking-actions {
    display: flex;
    gap: 10px;
}

.trips-booking-submit {
    flex: 1;
    border: 0;
    background: var(--aw-choice);
    color: var(--aw-ground);
    font-size: 0.9rem;
    font-weight: 700;
    padding: 10px;
    border-radius: var(--aw-radius-sm);
    cursor: pointer;
}

.trips-booking-cancel {
    border: 1px solid var(--aw-hairline);
    background: transparent;
    color: var(--aw-muted);
    font-size: 0.9rem;
    padding: 10px 16px;
    border-radius: var(--aw-radius-sm);
    cursor: pointer;
}

.trips-booking-error {
    color: var(--aw-bad-ink);
    font-size: 0.76rem;
    margin-top: 10px;
    min-height: 1em;
}

/* B-3 (claim 5) — the committed/planned sub-line + two-tone fill bar under the
   Trip Effective Cost headline. Miles-dollars only; cash split is separate. */
.trips-verdict-commit {
    margin-top: 6px;
}

.trips-commit-line {
    font-size: 0.74rem;
    color: var(--aw-muted);
}

.trips-commit-done {
    color: var(--aw-choice);
    font-weight: 650;
}

.trips-commit-bar {
    margin-top: 4px;
    height: 4px;
    border-radius: 999px;
    background: var(--aw-ground-2);
    overflow: hidden;
}

.trips-commit-bar-fill {
    height: 100%;
    background: var(--aw-choice);
    border-radius: 999px;
}

.trips-verdict-cash-split {
    margin-top: 2px;
    font-size: 0.72rem;
    color: var(--aw-muted);
}

/* ---------------------------------------------------------------------------
   Mobile polish item 2 (2026-08-23 brief §2) — "Trips: verdict panel freezes
   the screen (owner ruling: collapse to top)".

   THE BUG: `.trips-header-wrap` (above) is `position: sticky`, unconditionally,
   at every width. On a ~375x812 phone the full panel is roughly 75% of the
   viewport tall, so pinning it PERMANENTLY at the scrollport's top leaves the
   spine a letterbox for the rest of the scroll — not a one-time cost at the
   top of the page, a standing one for the whole read.

   THE FIX, mobile-only: the full panel goes back to `position: static` here,
   so it scrolls away in normal flow exactly like any other content "at the
   top of the page" (the owner's own phrase) — and a NEW one-line bar
   (`.trips-verdict-condensed`, a SIBLING of the wrap, not its child — see the
   base-rule comment above) takes over the sticky duty. Placed immediately
   after the wrap's own slot-add host in `.trips-detail`'s markup
   (`_renderDetailShell`), its containing block is the same tall
   `.trips-detail` box the wrap's pin already relies on, so `position: sticky`
   here actually has room to travel — the SAME lesson Copilot r1 on #301
   already taught this file once (`.trips-header-wrap`'s own comment above).

   Appended at the foot of the file, after every base rule it overrides
   (`.trips-header-wrap`, `.trips-verdict-condensed`) — this file's own
   established convention (see the T3-D section-A comment mid-file) for
   winning an equal-specificity cascade tie. jsdom evaluates no media
   queries at all, so what the jsdom suite pins is markup/wiring (the bar
   exists, carries the right ids, the tap handler is wired); the sticky
   hand-off itself — full panel scrolls away, condensed bar appears with
   matching values, tap returns to top, no overlap with the header or the
   toast — is proved in a real engine at 375x812
   (docs/product/mockups/mobile-polish/item2-verdict-condense/). */
@media (max-width: 700px) {
    .trips-header-wrap {
        position: static;
    }

    .trips-verdict-condensed {
        display: block;
        position: sticky;
        /* Same cancellation as `.trips-header-wrap` above, and for the same
           reason: the scrollport's own top padding (chat.css
           `--trips-scrollport-pad-top`), or this bar pins 20px below the
           edge with the spine visible in the gap above it. */
        top: calc(-1 * var(--trips-scrollport-pad-top, 0px));
        z-index: 5; /* the wrap's own layer — the two are never pinned at
                       once, so there is nothing to out-rank */
        margin: 0 0 20px;
        /* Hidden until trips.js's IntersectionObserver says the full panel
           has actually scrolled past (`.trips-verdict-condensed-visible`).
           `display` alone can't carry that toggle — flipping this element's
           OWN display would drop it out of the sticky flow it needs to stay
           in to know when to reappear — so the hidden state is
           opacity/visibility instead, with the box always present. */
        opacity: 0;
        visibility: hidden;
        pointer-events: none;
        transition: opacity 0.15s ease;
    }

    .trips-verdict-condensed-visible {
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
    }

    .trips-verdict-condensed-btn {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 10px;
        width: 100%;
        padding: 10px 14px;
        border: 1px solid var(--aw-hairline);
        border-radius: var(--aw-radius);
        background: var(--aw-elevated);
        box-shadow: var(--aw-shadow);
        color: var(--aw-ink);
        font: inherit;
        text-align: left;
        cursor: pointer;
    }

    .trips-verdict-condensed-text {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        font-size: 0.85rem;
        font-weight: 650;
    }

    .trips-verdict-condensed-chevron {
        flex: 0 0 auto;
        color: var(--aw-muted);
        /* "^" already points up unrotated — no transform needed. This bar's
           one action is "back to the top", so up is the correct direction
           (a rotate(180deg) here was measured rendering a DOWN chevron,
           backwards from the comment that used to sit on it). */
    }
}
