/*
 * page_bar.css — the persistent page utility bar.
 *
 * Pairs with templates/components/seo/page_bar.html and
 * static/js/controllers/esm/page_bar_controller.js.
 *
 * COLOUR: chippie-marketing.css :root owns the palette. No raw hex here; the
 * css_literals ratchet caps them per file and this file starts at zero. Tints
 * use colour-mix() against a token.
 *
 * TWO THINGS HERE ARE LOAD-BEARING, and both are about not moving the page.
 *
 * The collapsed height is a variable used in exactly two places: the bar's own
 * height and .page-bar-spacer's height. The spacer is what keeps the last of
 * the footer reachable instead of sitting under a fixed strip. If the two ever
 * disagree, either content hides behind the bar or the page grows a dead gap,
 * so they read from one token and are never set independently.
 *
 * The panel reveals by animating its own height, which is safe ONLY because of
 * where it sits. The usual objection -- animating height relayouts the document
 * every frame -- does not apply inside a position:fixed bar: the panel is out
 * of flow, so the work is confined to the bar's own subtree, and .page-bar-spacer
 * holds the document's height constant regardless of what the panel is doing.
 * Height is also the only property that produces the effect wanted here, since
 * the bar is pinned to the bottom edge and the input row has to travel with it.
 * A transform would slide the panel while leaving the input stranded mid-air.
 */

:root {
    --page-bar-h: 56px;
    --page-bar-z: 60;   /* above landing.css .sticky-cta (50), below the toasts */
}

@media (max-width: 640px) {
    :root { --page-bar-h: 52px; }
}

/* Reserves the bar's height at the end of the document. Height is fixed and
   known before paint, so the bar costs no layout shift. */
.page-bar-spacer {
    height: calc(var(--page-bar-h) + env(safe-area-inset-bottom));
}

.page-bar {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: var(--page-bar-z);
    background: var(--sandstone);
    border-top: 1px solid var(--border);
    padding-bottom: env(safe-area-inset-bottom);
    box-shadow: 0 -2px 12px color-mix(in srgb, var(--black) 8%, transparent);
}

/* ---------- The input row ---------- */

.page-bar-form {
    display: flex;
    align-items: center;
    gap: 8px;
    height: var(--page-bar-h);
    max-width: 1120px;
    margin: 0 auto;
    padding: 0 16px;
}

/* Present for screen readers, absent for everyone else. The placeholder is not
   a label: it disappears the moment anyone types. */
.page-bar-label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.page-bar-input {
    flex: 1 1 auto;
    min-width: 0;
    height: 38px;
    padding: 0 12px;
    font-size: 1rem;   /* under 16px iOS Safari zooms the page on focus */
    color: var(--black);
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: 8px;
    appearance: none;
}

.page-bar-input:focus {
    outline: 2px solid var(--orange);
    outline-offset: 1px;
}

/* The keyboard hint is a lie on a touch device: there is no "/" key to press. */
.page-bar-kbd {
    display: none;
    padding: 2px 7px;
    font-size: 0.8rem;
    color: var(--text-2);
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: 5px;
}

@media (pointer: fine) {
    .page-bar-kbd { display: inline-block; }
}

.page-bar-send {
    flex: 0 0 auto;
    width: 38px;
    height: 38px;
    display: grid;
    place-items: center;
    color: var(--white);
    background: var(--black);
    border: 0;
    border-radius: 8px;
    cursor: pointer;
}

.page-bar-send:hover { background: var(--green-deep); }

/* ---------- The panel ---------- */

/* Closed. The bar is pinned to the bottom of the viewport, so animating the
   panel's height is what makes the input row glide down as it shuts instead of
   snapping. visibility is switched at the END of the close (0s delayed by the
   duration) and at the START of the open, which keeps the contents out of the
   tab order while closed without cutting the animation short. */
.page-bar-panel {
    max-height: 0;
    opacity: 0;
    visibility: hidden;
    overflow: hidden;
    /* Reading the transcript is not leaving it. Without this, hitting the top
       or bottom of the panel chains the remaining scroll to the page, which
       moves window.scrollY and trips the collapse -- so reading to the end of
       a long answer would dismiss the answer. */
    overscroll-behavior: contain;
    max-width: 1120px;
    margin: 0 auto;
    padding: 0 16px 12px;
    border-top: 1px solid var(--border);
    transition: max-height 220ms ease, opacity 150ms ease,
                transform 160ms ease-out, visibility 0s linear 220ms;
}

.page-bar-panel.is-open {
    max-height: 60dvh;
    opacity: 1;
    visibility: visible;
    overflow-y: auto;
    transition: max-height 220ms ease, opacity 150ms ease,
                transform 160ms ease-out, visibility 0s;
}

/* ---------- Dismissal ---------- */

/* Sticky against the panel's own scroll so the way out does not scroll away
   under a long answer. */
.page-bar-dismiss {
    position: sticky;
    top: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 0 4px;
    background: var(--sandstone);
}

/* The drag affordance: a phone reader reaches for this before any button. */
.page-bar-grip {
    flex: 1 1 auto;
    height: 4px;
    max-width: 48px;
    margin: 0 auto;
    border-radius: 2px;
    background: var(--border);
}

.page-bar-close {
    flex: 0 0 auto;
    border: 0;
    background: none;
    padding: 4px 6px;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text-2);
    cursor: pointer;
}

.page-bar-close:hover { color: var(--text-1); }

/* While a finger is on it the panel tracks the finger exactly; the transition
   above is what springs it back when the drag was too short to dismiss. */
.page-bar-panel[data-dragging="true"] { transition: none; }

/* Reduced motion still needs the visibility switch to happen at the right end
   of the change, or a closed panel stays in the tab order. */
@media (prefers-reduced-motion: reduce) {
    .page-bar-panel,
    .page-bar-panel.is-open { transition: visibility 0s; }
}

.page-bar-results {
    list-style: none;
    margin: 0;
    padding: 8px 0 0;
}

.page-bar-results:empty { display: none; }

.page-bar-result {
    display: block;
    width: 100%;
    padding: 9px 10px;
    text-align: left;
    font-size: 0.95rem;
    line-height: 1.45;
    color: var(--black);
    background: none;
    border: 0;
    border-radius: 6px;
    cursor: pointer;
}

.page-bar-result:hover,
.page-bar-result[aria-selected="true"] {
    background: color-mix(in srgb, var(--orange) 12%, transparent);
}

/* An h3 result is indented so the result list reads as the document's shape
   rather than a flat list of strings. */
.page-bar-result--h3 { padding-left: 26px; }

.page-bar-result__kind {
    display: inline-block;
    margin-right: 8px;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-2);
}

.page-bar-result mark {
    padding: 0 1px;
    color: inherit;
    background: color-mix(in srgb, var(--yellow) 45%, transparent);
}

.page-bar-empty {
    padding: 12px 10px;
    font-size: 0.95rem;
    color: var(--text-2);
}

/* ---------- The ask row ---------- */

/* Offered inside the results list rather than beside the input, so the reader
   never has to choose a mode before they have finished typing. Styled as the
   one primary thing in the list because by the time it appears, it is. */
.page-bar-askrow {
    display: block;
    width: 100%;
    margin-top: 6px;
    padding: 10px;
    text-align: left;
    font-size: 0.95rem;
    color: var(--black);
    background: color-mix(in srgb, var(--orange) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--orange) 35%, transparent);
    border-radius: 6px;
    cursor: pointer;
}

.page-bar-askrow:hover {
    background: color-mix(in srgb, var(--orange) 18%, transparent);
}

.page-bar-askrow__lead {
    margin-right: 8px;
    font-weight: 600;
    color: var(--orange-deep);
}

/* ---------- The answer ---------- */

.page-bar-ask {
    padding: 12px 0 4px;
    border-top: 1px solid var(--border);
    margin-top: 10px;
}

/* One selector for both the streaming answer and every archived one: the live
   bubble carries .page-bar-answer as well, but the shared class is what makes
   history look identical to the turn that just happened. */
.page-bar-msg--ai p {
    margin: 0 0 8px;
    font-size: 0.97rem;
    line-height: 1.55;
    color: var(--black);
}

.page-bar-msg--ai ul {
    margin: 0 0 8px;
    padding-left: 20px;
    font-size: 0.97rem;
    line-height: 1.55;
}

.page-bar-msg--ai a { color: var(--green-deep); }

/* The two states where the assistant could not answer from this page. A quiet
   left rule, never a red error: not finding something is a normal outcome and
   styling it as a fault teaches the reader to distrust the answers that did
   work. */
.page-bar-ask[data-grounding="none"],
.page-bar-ask[data-grounding="related"],
.page-bar-ask[data-grounding="failed"] {
    padding-left: 12px;
    border-left: 3px solid color-mix(in srgb, var(--orange) 45%, transparent);
}

.page-bar-failed {
    margin: 0 0 8px;
    font-size: 0.95rem;
    color: var(--text-2);
}

.page-bar-retry {
    padding: 6px 12px;
    font-size: 0.9rem;
    color: var(--black);
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: 6px;
    cursor: pointer;
}

/* The wait, as a messenger renders it: three dots, one bubble's worth of room.
   This replaced three shimmer bars sized to the answer that was coming. The
   bars were the right call when the answer had no bubble around it and the
   layout shift was the whole cost; inside a bubble they read as a broken
   paragraph, and the bubble already holds its own shape. */
.page-bar-typing {
    display: flex;
    align-items: center;
    gap: 4px;
    height: 1.55em;
}

.page-bar-typing span {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--black) 32%, transparent);
    animation: page-bar-typing 1.3s ease-in-out infinite;
}

.page-bar-typing span:nth-child(2) { animation-delay: 0.18s; }
.page-bar-typing span:nth-child(3) { animation-delay: 0.36s; }

@keyframes page-bar-typing {
    0%, 60%, 100% { opacity: 0.28; transform: translateY(0); }
    30% { opacity: 1; transform: translateY(-3px); }
}

/* ---------- Earlier turns ---------- */

/* An earlier exchange. No divider rule and no dimming now that the bubbles
   separate the turns themselves: a messenger thread does not fade what was
   said a minute ago, and the reader scrolls back through it to re-read. */
.page-bar-turn {
    margin-bottom: 6px;
}

/* Announced, never drawn. The bubble's side says who is speaking to anyone who
   can see it; a screen reader gets the name instead. */
.page-bar-speaker {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* ---------- Messages ---------- */

.page-bar-msg {
    max-width: 80%;
    width: fit-content;
    margin: 8px 0 0;
    padding: 8px 12px;
    border-radius: 14px;
    font-size: 0.95rem;
}

/* The reader, right, in the accent the bar already uses for its own controls. */
.page-bar-msg--you {
    margin-left: auto;
    border-bottom-right-radius: 4px;
    background: color-mix(in srgb, var(--orange) 18%, var(--white));
    color: var(--text-1);
    font-weight: 500;
}

/* Chip AI, left, on the neutral card colour so long answers stay readable. */
.page-bar-msg--ai {
    margin-right: auto;
    border-bottom-left-radius: 4px;
    background: var(--white);
    border: 1px solid var(--border);
    color: var(--text-1);
}

/* The bubble supplies the spacing; stacked markdown inside it must not add
   another gap at the ends. */
.page-bar-msg--ai > :first-child { margin-top: 0; }
.page-bar-msg--ai > :last-child { margin-bottom: 0; }

/* ---------- Somewhere else on the site ---------- */

.page-bar-elsewhere {
    margin-top: 10px;
}

.page-bar-cards {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

/* A card, not a chip. A chip scrolls this page; this leaves it, and the two
   must not look like the same act. */
.page-bar-card {
    display: block;
    padding: 8px 12px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--white);
    text-decoration: none;
}

.page-bar-card:hover {
    border-color: var(--green);
    background: color-mix(in srgb, var(--green) 6%, var(--white));
}

.page-bar-card__title {
    display: block;
    font-weight: 700;
    font-size: 0.92rem;
    color: var(--green-deep);
}

.page-bar-card__blurb {
    display: block;
    margin-top: 2px;
    font-size: 0.85rem;
    line-height: 1.4;
    color: var(--text-2);
}

/* ---------- Source chips ---------- */

.page-bar-sources {
    padding-top: 4px;
}

.page-bar-sources__label {
    margin: 0 0 6px;
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-2);
}

.page-bar-chip {
    display: inline-block;
    margin: 0 6px 6px 0;
    padding: 6px 11px;
    font-size: 0.88rem;
    color: var(--black);
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: 999px;
    cursor: pointer;
}

.page-bar-chip::before {
    content: "↑ ";
    color: var(--text-2);
}

.page-bar-chip:hover { border-color: var(--orange); }

/* ---------- After the answer ---------- */

.page-bar-after {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-top: 8px;
}

.page-bar-vote {
    display: flex;
    align-items: center;
    gap: 4px;
}

.page-bar-vote__btn {
    padding: 4px 8px;
    font-size: 0.95rem;
    color: var(--text-2);
    background: none;
    border: 1px solid transparent;
    border-radius: 6px;
    cursor: pointer;
}

.page-bar-vote__btn:hover:not(:disabled) {
    color: var(--black);
    border-color: var(--border);
}

.page-bar-vote__btn:disabled { cursor: default; opacity: 0.4; }

.page-bar-vote__thanks {
    font-size: 0.85rem;
    color: var(--text-2);
}

.page-bar-again {
    margin-left: auto;
    padding: 0;
    font-size: 0.88rem;
    color: var(--green-deep);
    background: none;
    border: 0;
    cursor: pointer;
    text-decoration: underline;
}

.page-bar-fallback {
    padding-top: 10px;
}

.page-bar-cta {
    display: inline-block;
    padding: 8px 16px;
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--white);
    background: var(--green);
    border-radius: 6px;
    text-decoration: none;
}

/* ---------- Disclosure ---------- */

/* Disclosure lives in the chrome, never in the assistant's first sentence.
   A bot that opens by announcing itself loses the reader before it has said
   anything useful; a label under the input is there for anyone who looks. */
.page-bar-disclosure {
    margin: 10px 0 0;
    font-size: 0.78rem;
    line-height: 1.5;
    color: var(--text-2);
}

.page-bar-caution {
    margin: 8px 0 0;
    padding: 8px 10px;
    font-size: 0.8rem;
    line-height: 1.5;
    color: var(--text-2);
    background: color-mix(in srgb, var(--yellow) 12%, transparent);
    border-radius: 6px;
}

.page-bar-beta {
    display: inline-block;
    margin-right: 6px;
    padding: 1px 6px;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--white);
    background: var(--text-2);
    border-radius: 3px;
}

/* ---------- Starter questions ---------- */

.page-bar-starters {
    padding: 10px 0 2px;
}

.page-bar-starters__label {
    margin: 0 0 8px;
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-2);
}

.page-bar-starter {
    display: inline-block;
    margin: 0 6px 6px 0;
    padding: 7px 12px;
    font-size: 0.9rem;
    color: var(--black);
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: 999px;
    cursor: pointer;
}

.page-bar-starter:hover { border-color: var(--orange); }

/* Once a search is running the chips are stale suggestions competing with real
   results, so they go away rather than pushing the results down the panel. */
.page-bar--searching .page-bar-starters { display: none; }

/* ---------- The jump target ---------- */

/* A jump that only scrolls leaves the reader hunting for what moved. Two
   seconds of tint says "this is the thing you asked for" and then gets out of
   the way. */
.page-bar-target {
    animation: page-bar-flash 2s ease-out 1;
}

@keyframes page-bar-flash {
    from { background: color-mix(in srgb, var(--yellow) 40%, transparent); }
    to   { background: transparent; }
}

/* ---------- Motion and print ---------- */

@media (prefers-reduced-motion: reduce) {
    /* The dots stop moving but stay visible and evenly lit, so the wait is
       still legible as a wait rather than three dead circles. */
    .page-bar-target,
    .page-bar-typing span { animation: none; }

    .page-bar-typing span { opacity: 0.6; }
}

@media print {
    .page-bar,
    .page-bar-spacer { display: none; }
}
