/*
   Arabic first. Tajawal is a humanist sans with a full Arabic set and real weights; Noto Naskh
   is the fallback for readers who have it and prefer naskh forms in long legal passages, and
   Segoe UI / Tahoma cover a Windows box with neither webfont available. Latin glyphs come from
   the same stack, so a mixed sentence does not change typeface mid-line.
*/
:root {
    --font-arabic: "Tajawal", "Noto Naskh Arabic", "Segoe UI", Tahoma, sans-serif;
    --font-mono: "Cascadia Mono", Consolas, "Courier New", monospace;

    --bg: #f7f7f8;
    --surface: #ffffff;
    --surface-2: #f1f2f4;
    --sidebar-bg: #14161a;
    --sidebar-fg: #e7e9ee;
    --sidebar-muted: #9aa1ad;
    --ink: #16181d;
    --ink-muted: #5c6270;
    --line: #e2e4e9;
    --accent: #1f6feb;
    --accent-soft: #e8f0fe;
    /* The question bubble, ChatGPT-style: a filled blue with its own text colour, borderless on
       screen. Its own tokens rather than --accent because print must restore a dark-on-white
       bubble — browsers drop backgrounds on paper, and white text alone would vanish. */
    --user-bubble-bg: #1f6feb;
    --user-bubble-fg: #ffffff;
    --user-bubble-line: transparent;
    --danger: #b4232a;
    --radius: 14px;
    --shadow: 0 1px 2px rgba(16, 18, 22, .06), 0 8px 24px rgba(16, 18, 22, .06);
}

* {
    box-sizing: border-box;
}

html, body {
    height: 100%;
    margin: 0;
    font-family: var(--font-arabic);
    font-size: 16px;
    line-height: 1.75;
    color: var(--ink);
    background: var(--bg);
    -webkit-font-smoothing: antialiased;
}

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

/* ---------- scrollbars ---------- */

/* The standard properties, not ::-webkit-scrollbar - Chrome disables the webkit styling
   entirely once scrollbar-color is set, so mixing the two means only these apply anyway.
   The thumb is translucent so a single value sits right on every surface it scrolls over:
   the light page, the dark sidebar, and the dark passage cards - which also keeps it
   correct in both color schemes without another variable pair. */
* {
    scrollbar-width: thin;
    scrollbar-color: rgba(128, 138, 156, .45) transparent;
}

/* ---------- shell ---------- */

.chat-shell {
    display: flex;
    height: 100vh;
    overflow: hidden;
}

.chat-sidebar {
    width: 288px;
    flex: 0 0 288px;
    background: var(--sidebar-bg);
    color: var(--sidebar-fg);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.chat-main {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-width: 0;
    background: var(--bg);
}

.chat-topbar {
    display: none;
    align-items: center;
    gap: .75rem;
    padding: .5rem .75rem;
    border-bottom: 1px solid var(--line);
    background: var(--surface);
}

.chat-brand {
    font-weight: 700;
}

/* Pushed to the bar's inline end — the left, in this RTL document — leaving the menu button and
   the brand together at the start. The bar itself is hidden above the breakpoint, so this needs
   no desktop counterpart. */
.topbar-print {
    margin-inline-start: auto;
}

.chat-backdrop {
    display: none;
}

/* Below the breakpoint the sidebar becomes an overlay. It slides in from the inline start,
   which the logical property resolves to the right in this RTL document without a second rule. */
@media (max-width: 900px) {
    .chat-topbar {
        display: flex;
    }

    /* The topbar copy takes over here. At this width the reading column runs edge to edge, so a
       control floating over its top corner covers the transcript instead of sitting beside it.
       Two classes on purpose: .icon-btn sets display later in the file at equal specificity, and
       a media query adds none of its own. */
    .icon-btn.print-btn {
        display: none;
    }

    .chat-sidebar {
        position: fixed;
        inset-block: 0;
        inset-inline-start: 0;
        z-index: 30;
        transform: translateX(0);
        transition: transform .18s ease-out;
    }

    html[dir="rtl"] .chat-sidebar {
        transform: translateX(100%);
    }

    html[dir="ltr"] .chat-sidebar {
        transform: translateX(-100%);
    }

    .chat-shell.is-open .chat-sidebar {
        transform: translateX(0);
    }

    .chat-shell.is-open .chat-backdrop {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 20;
        background: rgba(10, 12, 16, .45);
    }
}

/* ---------- sidebar ---------- */

.sidebar-inner {
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: .75rem;
    gap: .75rem;
}

.new-chat-btn {
    display: flex;
    align-items: center;
    gap: .5rem;
    width: 100%;
    padding: .6rem .75rem;
    border: 1px solid rgba(255, 255, 255, .16);
    border-radius: 10px;
    background: transparent;
    color: inherit;
    font: inherit;
    font-weight: 500;
    cursor: pointer;
    transition: background .12s ease;
}

.new-chat-btn:hover {
    background: rgba(255, 255, 255, .08);
}

.new-chat-btn .plus {
    font-size: 1.15rem;
    line-height: 1;
}

.conversation-list {
    flex: 1 1 auto;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.conversation {
    display: flex;
    align-items: center;
    gap: .25rem;
    border-radius: 10px;
    padding-inline: .25rem;
}

.conversation:hover,
.conversation.active {
    background: rgba(255, 255, 255, .09);
}

.conversation-link {
    flex: 1 1 auto;
    min-width: 0;
    padding: .5rem .35rem;
    color: inherit;
    text-decoration: none;
}

.conversation-title {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: .93rem;
}

.conversation-actions {
    display: none;
    gap: .1rem;
}

.conversation:hover .conversation-actions,
.conversation.active .conversation-actions {
    display: flex;
}

.rename-input {
    width: 100%;
    margin: .25rem 0;
    padding: .35rem .5rem;
    border: 1px solid var(--accent);
    border-radius: 8px;
    background: #0c0e12;
    color: var(--sidebar-fg);
    font: inherit;
    font-size: .9rem;
}

.confirm-row {
    display: flex;
    align-items: center;
    gap: .35rem;
    padding: .4rem .35rem;
    font-size: .85rem;
}

.confirm-text {
    flex: 1 1 auto;
    color: var(--sidebar-muted);
}

.empty-note,
.sidebar-footer .muted {
    color: var(--sidebar-muted);
    font-size: .82rem;
}

.sidebar-footer {
    border-top: 1px solid rgba(255, 255, 255, .1);
    padding-top: .6rem;
}

.sidebar-user {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    margin-bottom: .5rem;
}

/* The name is the one part of this row that can be arbitrarily long; it gives up its width
   first so the button never wraps under it. */
.sidebar-user-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: .88rem;
}

/* The sidebar is dark and .quiet-btn is drawn for the light page, so the surface and line
   colours are the only two things overridden here. */
.logout-btn {
    flex: 0 0 auto;
    border-color: rgba(255, 255, 255, .18);
    background: transparent;
    color: var(--sidebar-muted);
    font-size: .8rem;
}

.logout-btn:hover {
    color: var(--sidebar-fg);
    border-color: rgba(255, 255, 255, .32);
}

/* ---------- sign-in ---------- */

.bare-page {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: 1.5rem;
}

.login-card {
    width: min(24rem, 100%);
    padding: 1.75rem;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    box-shadow: var(--shadow);
}

.login-title {
    margin: 0;
    font-size: 1.35rem;
    font-weight: 700;
}

.login-subtitle {
    margin: .15rem 0 1.25rem;
    color: var(--ink-muted);
    font-size: .9rem;
}

.login-field {
    display: block;
    margin-bottom: .9rem;
}

.login-label {
    display: block;
    margin-bottom: .3rem;
    font-size: .85rem;
    color: var(--ink-muted);
}

.login-input {
    width: 100%;
    padding: .5rem .7rem;
    border: 1px solid var(--line);
    border-radius: 10px;
    background: var(--surface);
    /* Form controls do not inherit either of these; in the dark scheme the UA defaults put
       near-black text on a near-black field. Same reason .composer-input sets them. */
    color: var(--ink);
    font: inherit;
    caret-color: var(--accent);
}

.login-input:focus {
    outline: none;
    border-color: var(--accent);
}

/* A phone number and a code read left-to-right inside the RTL document; the field itself
   stays in the RTL flow, only its content is re-anchored. */
.login-input[type="tel"],
.login-input[autocomplete="one-time-code"] {
    direction: ltr;
    text-align: left;
}

.login-code {
    letter-spacing: .3em;
}

.login-note {
    margin: 0 0 1rem;
    font-size: .88rem;
    color: var(--ink-muted);
}

.login-dev {
    margin-bottom: 1rem;
    padding: .5rem .75rem;
    border: 1px dashed var(--line);
    border-radius: 10px;
    font-size: .85rem;
}

.login-link {
    display: block;
    margin-top: .9rem;
    text-align: center;
    font-size: .88rem;
    color: var(--accent);
}

.login-submit {
    width: 100%;
    padding: .55rem;
    border: 0;
    border-radius: 12px;
    background: var(--accent);
    color: #fff;
    font: inherit;
    font-weight: 500;
    cursor: pointer;
}

.login-submit:hover {
    filter: brightness(1.06);
}

.login-error,
.login-validation {
    color: var(--danger);
    font-size: .85rem;
}

.login-error {
    margin-bottom: 1rem;
    padding: .55rem .75rem;
    border: 1px solid rgba(180, 35, 42, .35);
    border-radius: 10px;
    background: rgba(180, 35, 42, .08);
}

.login-validation {
    display: block;
    margin-top: .25rem;
}

/* ---------- buttons ---------- */

.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: inherit;
    font: inherit;
    cursor: pointer;
    opacity: .75;
}

.icon-btn:hover {
    opacity: 1;
    background: rgba(127, 127, 127, .18);
}

.quiet-btn {
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface);
    color: var(--ink-muted);
    font: inherit;
    font-size: .85rem;
    padding: .2rem .8rem;
    cursor: pointer;
}

.quiet-btn:hover {
    color: var(--ink);
    border-color: #c9cdd6;
}

.danger-btn {
    border: 0;
    border-radius: 999px;
    background: var(--danger);
    color: #fff;
    font: inherit;
    font-size: .85rem;
    padding: .2rem .8rem;
    cursor: pointer;
}

/* ---------- page ---------- */

.chat-page {
    position: relative;
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

/* Out of the flow so it cannot push the transcript down, and anchored to .chat-page rather than
   to the viewport so it stays inside the column when the sidebar is open. It carries .icon-btn
   as well, which is where everything but the position comes from. */
.print-btn {
    position: absolute;
    top: .75rem;
    inset-inline-end: 1rem;
    z-index: 10;
}

.banner {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin: .75rem auto 0;
    padding: .6rem 1rem;
    width: min(48rem, calc(100% - 2rem));
    border: 1px solid #f0d9a8;
    border-radius: 10px;
    background: #fdf6e3;
    color: #6b5312;
    font-size: .92rem;
}

.banner span {
    flex: 1 1 auto;
}

.message-scroll {
    flex: 1 1 auto;
    overflow-y: auto;
    scroll-behavior: smooth;
}

/* The single measure the whole conversation is set to. Long Arabic legal prose is unreadable
   across a 1600px window, and centring the column keeps the answer, its sources and the input
   box on one axis. */
.message-column {
    width: min(48rem, calc(100% - 2rem));
    margin: 0 auto;
    padding: 1.5rem 0 2rem;
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

/* ---------- messages ---------- */

.message {
    display: flex;
    min-width: 0;
}

/* The question is the only side that reads as a bubble. An answer runs to paragraphs, sources
   and an action row, so chrome around it would box the page's own content; the question is a
   line or two and needs to be told apart from it at a glance.

   A column so the stamp can sit centred over the bubble. align-items is the inline axis here,
   and flex-start resolves to the right edge in this RTL document — the same side the reference
   keeps its questions on. */
.message.user {
    flex-direction: column;
    align-items: flex-start;
    gap: .35rem;
}

/* Centred over the bubble the way the reference stamps a question; sized as chrome, not content. */
.message-time {
    align-self: center;
    font-size: .72rem;
    color: var(--ink-muted);
}

.bubble {
    flex: 1 1 auto;
    min-width: 0;
}

/* Shrink-to-fit rather than stretched, and capped short of the measure: a bubble as wide as the
   column would read as another answer. The radius is the composer's 18px rather than --radius:
   the question is the composer's own text given back, and the reference rounds it the same way. */
.message.user .bubble {
    flex: 0 1 auto;
    max-width: min(85%, 34rem);
    background: var(--user-bubble-bg);
    color: var(--user-bubble-fg);
    border: 1px solid var(--user-bubble-line);
    border-radius: 18px;
    padding: .35rem 1rem;
    box-shadow: var(--shadow);
}

/* unicode-bidi: plaintext makes each paragraph pick its own direction from its first strong
   character, so an English question inside this RTL page reads left to right — and an Arabic
   answer that quotes an English term does not have its punctuation thrown to the wrong end. */
.content {
    unicode-bidi: plaintext;
}

.content > :first-child {
    margin-top: 0;
}

.content > :last-child {
    margin-bottom: 0;
}

.content p,
.content li {
    margin: .5rem 0;
}

.content h1, .content h2, .content h3 {
    font-size: 1.05rem;
    font-weight: 700;
    margin: 1.1rem 0 .4rem;
}

.content table {
    width: 100%;
    border-collapse: collapse;
    margin: .75rem 0;
    font-size: .93rem;
}

.content th,
.content td {
    border: 1px solid var(--line);
    padding: .4rem .6rem;
    text-align: start;
}

.content blockquote {
    margin: .75rem 0;
    padding-inline-start: .9rem;
    border-inline-start: 3px solid var(--line);
    color: var(--ink-muted);
}

/* Code is the one thing that is never RTL, whatever the surrounding document says: a shell
   command or a JSON fragment mirrored by the bidi algorithm is unreadable and, worse, looks
   plausible. */
.content pre,
.content code {
    font-family: var(--font-mono);
    direction: ltr;
    text-align: left;
    unicode-bidi: embed;
}

.content code {
    background: var(--surface-2);
    border-radius: 5px;
    padding: .1rem .3rem;
    font-size: .88em;
}

.content pre {
    background: #14161a;
    color: #e7e9ee;
    padding: .85rem 1rem;
    border-radius: 10px;
    overflow-x: auto;
}

.content pre code {
    background: transparent;
    padding: 0;
    color: inherit;
}

.user-text {
    white-space: pre-wrap;
}

/* The citation marker Markdig's output is post-processed into. Superscript, so it sits out of
   the reading line, and tinted so a reader can tell a source reference from a bracketed
   article number in the ruling's own text. */
.content .cite {
    color: var(--accent);
    font-size: .72em;
    font-weight: 700;
    padding-inline: .1rem;
}

.cursor {
    display: inline-block;
    width: .5rem;
    height: 1.05rem;
    margin-inline-start: .15rem;
    vertical-align: text-bottom;
    border-radius: 2px;
    background: var(--accent);
    animation: cursor-pulse 1s steps(2, start) infinite;
}

@keyframes cursor-pulse {
    to {
        opacity: .15;
    }
}

/* The pre-token phases (searching, thinking). Shown instead of the cursor while the bubble
   is still empty, because retrieval and the model's reasoning are silent and a bare cursor
   there reads as a hang. */
.thinking {
    display: flex;
    align-items: center;
    gap: .55rem;
    padding-block: .15rem;
    color: var(--ink-muted);
    font-size: .9rem;
}

.thinking-dots {
    display: inline-flex;
    gap: .28rem;
}

.thinking-dots span {
    width: .42rem;
    height: .42rem;
    border-radius: 50%;
    background: var(--accent);
    animation: thinking-bounce 1.2s ease-in-out infinite;
}

.thinking-dots span:nth-child(2) {
    animation-delay: .15s;
}

.thinking-dots span:nth-child(3) {
    animation-delay: .3s;
}

@keyframes thinking-bounce {
    0%, 60%, 100% {
        transform: translateY(0);
        opacity: .35;
    }

    30% {
        transform: translateY(-4px);
        opacity: 1;
    }
}

/* Opacity-only variant of the dots for reduced motion. Same rhythm, no travel. */
@keyframes thinking-fade {
    0%, 60%, 100% {
        opacity: .3;
    }

    30% {
        opacity: 1;
    }
}

@media (prefers-reduced-motion: reduce) {
    /* Windows "animation effects off" lands every user here, so this must stay an
       indicator, not a freeze: a static row of dots reads as a hang, which is the exact
       problem the indicator exists to solve. The preference targets spatial motion — the
       bounce goes, an opacity breathe stays, and the cursor's own pulse is already
       opacity-only so it is left running. The nth-child delays survive because those rules
       are more specific than this shorthand. */
    .thinking-dots span {
        animation: thinking-fade 1.6s ease-in-out infinite;
    }

    .message-scroll {
        scroll-behavior: auto;
    }
}

.message-error {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    padding: .65rem .9rem;
    border: 1px solid #f0c2c2;
    border-radius: 10px;
    background: #fdf2f2;
    color: #7d2020;
    font-size: .92rem;
}

.stopped-note,
.message-actions {
    margin-top: .5rem;
}

.stopped-note {
    color: var(--ink-muted);
    font-size: .85rem;
}

/* One row holds everything a finished answer offers. The page is RTL, so the thumbs sit at the
   inline start — under the answer's opening words — and إعادة التوليد follows them. */
.message-actions {
    display: flex;
    align-items: center;
    gap: .5rem;
}

.feedback {
    display: inline-flex;
    gap: .1rem;
}

/* Deliberately quieter than .icon-btn: this pair sits inside the answer rather than in a
   toolbar, and an unrated answer should not look like it is asking to be rated. */
.feedback-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--ink-muted);
    font: inherit;
    cursor: pointer;
    opacity: .6;
}

.feedback-btn:hover {
    opacity: 1;
    background: rgba(127, 127, 127, .18);
}

.feedback-btn.on {
    color: var(--accent);
    opacity: 1;
}

/* The outline is the unrated state and the fill is the chosen one; at 16px the colour change
   alone is too easy to miss on a glance. */
.feedback-btn.on svg {
    fill: currentColor;
}

/* ---------- citations ---------- */

.citations {
    margin-top: .9rem;
    border-top: 1px solid var(--line);
    padding-top: .7rem;
}

.citations-head {
    display: flex;
    align-items: center;
    gap: .6rem;
    flex-wrap: wrap;
}

.citations-title {
    font-size: .85rem;
    font-weight: 700;
    color: var(--ink-muted);
}

/* Muted and unadorned, matching .stopped-note: it qualifies the sources rather than warning about
   them, and a coloured banner would read as a failed turn to someone whose answer is fine. */
.literal-search-note {
    margin: .45rem 0 0;
    color: var(--ink-muted);
    font-size: .82rem;
}

.chips {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem;
}

/* The paper counterpart of the chips-and-card pair; the print block below swaps them. */
.citations-print {
    display: none;
}

.chip {
    min-width: 28px;
    height: 28px;
    padding: 0 .45rem;
    border: 1px solid var(--line);
    border-radius: 8px;
    background: var(--surface);
    color: var(--ink-muted);
    font: inherit;
    font-size: .82rem;
    font-weight: 700;
    cursor: pointer;
    transition: all .12s ease;
}

.chip:hover {
    border-color: var(--accent);
    color: var(--accent);
}

.chip.open {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}

.citation-card {
    margin-top: .6rem;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--surface);
    padding: .75rem .9rem;
}

/* A block, not a wrapping row: the reader switches cards by clicking chips, and a flow layout
   re-places every label as soon as one value is longer or absent. Scoped to the card — the
   drawer's own meta row keeps the flex behaviour. */
.citation-meta {
    font-size: .84rem;
    color: var(--ink-muted);
    margin-bottom: .5rem;
}

.citation-meta-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: .4rem;
}

/* max-content over a fixed label set, so the label column is the same width on every source and
   the values all start at one line. */
.citation-meta-grid {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: .25rem .5rem;
    margin: 0;
}

.citation-meta-grid dd {
    margin: 0;
}

.meta-label {
    color: #8b909b;
}

.meta-label::after {
    content: ":";
    margin-inline-end: .2rem;
}

.badge {
    background: var(--accent-soft);
    color: var(--accent);
    border-radius: 999px;
    padding: .05rem .6rem;
    font-weight: 700;
}

/* Capped and scrollable: a MemHokom chunk runs to a thousand characters, and letting it push
   the answer off screen defeats the purpose of showing it. */
.citation-text {
    max-height: 15rem;
    overflow-y: auto;
    white-space: pre-wrap;
    font-size: .92rem;
    line-height: 1.85;
    unicode-bidi: plaintext;
    padding-inline-end: .3rem;
}

/* The legislation the ruling rests on. Set below the passage and quieter than it: this is
   context for the citation, not a second body of text. */
.cited-laws {
    margin-top: .7rem;
    padding-top: .6rem;
    border-top: 1px dashed var(--line);
}

.cited-laws-title {
    display: block;
    font-size: .8rem;
    font-weight: 700;
    color: var(--ink-muted);
    margin-bottom: .4rem;
}

.cited-laws-list {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: .3rem;
    margin: 0;
    padding: 0;
}

.cited-law {
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: 999px;
    padding: .1rem .6rem;
    font-size: .82rem;
    color: var(--ink);
    unicode-bidi: plaintext;
}

/* A reconstructed law title below the confidence threshold, or none at all. Muted rather than
   hidden — the article number is exact either way; see CitedLaw.Confidence. */
.cited-law.tentative {
    color: var(--ink-muted);
    border-style: dashed;
    background: transparent;
    cursor: help;
}

.cited-laws-more {
    display: inline-block;
    margin-top: .35rem;
    font-size: .78rem;
    color: var(--ink-muted);
}

/* Below the passage and its legislation, at the foot of the card: the action is about the whole
   ruling, not about anything the reader is part-way through. */
.citation-actions {
    margin-top: .7rem;
}

/* ---------- ruling viewer ---------- */

/* Fixed to the viewport rather than to .chat-page: the drawer covers the sidebar too, and a
   stacking context created by any ancestor transform would otherwise trap it. */
.drawer-layer {
    position: fixed;
    inset: 0;
    z-index: 40;
}

.drawer-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(10, 12, 16, .5);
}

/* Anchored to the inline start, which the logical property resolves to the right in this RTL
   document — the same side the sidebar overlay uses, so the two never read as opposite gestures. */
.drawer {
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    width: min(46rem, 100%);
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border-inline-end: 1px solid var(--line);
    box-shadow: var(--shadow);
}

.drawer-head {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
    padding: .85rem 1.1rem .6rem;
    border-bottom: 1px solid var(--line);
}

.drawer-title {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

/* The topic path arrives as lines and is kept as lines: it is a hierarchy, and joining it with
   separators would read as one long title. */
.drawer-path-line {
    font-size: .95rem;
    font-weight: 700;
    line-height: 1.5;
}

.drawer-path-line:not(:first-child) {
    font-weight: 500;
    color: var(--ink-muted);
    font-size: .85rem;
}

.drawer-meta {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem .9rem;
    padding: .5rem 1.1rem;
    border-bottom: 1px solid var(--line);
    background: var(--surface-2);
    font-size: .82rem;
    color: var(--ink-muted);
}

/* Pinned to the row's far edge — the left, in RTL — away from the date it would otherwise
   crowd. inline-start is the right side here, so the auto margin pushes leftwards. */
.drawer-meta .drawer-meta-end {
    margin-inline-start: auto;
}

/* The scroller is the body, not the page. A MemHokom section runs to tens of thousands of
   characters, and scrolling the document instead would take the header off screen with it. */
.drawer-body {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 1rem 1.1rem 2rem;
}

.drawer-section + .drawer-section {
    margin-top: 1.5rem;
    padding-top: 1.2rem;
    border-top: 1px solid var(--line);
}

.drawer-section-title {
    margin: 0 0 .5rem;
    font-size: .85rem;
    font-weight: 700;
    color: var(--accent);
}

/* pre-wrap because the section's paragraph breaks are its structure — CleanSectionText rejoins
   paragraphs with a blank line and nothing else marks them. */
.drawer-text {
    white-space: pre-wrap;
    font-size: .95rem;
    line-height: 1.9;
    unicode-bidi: plaintext;
}

.drawer-text mark {
    background: rgba(255, 214, 102, .45);
    color: inherit;
    border-radius: 3px;
    padding: .05rem 0;
}

/* The passage the reader actually clicked. Distinct from its siblings rather than merely
   brighter: several passages of one ruling are commonly retrieved together. */
.drawer-text mark.focus {
    background: rgba(255, 190, 40, .75);
    box-shadow: 0 0 0 2px rgba(255, 190, 40, .35);
}

.drawer-notice {
    margin: 0 0 .5rem;
    font-size: .8rem;
    color: var(--ink-muted);
}

/* Rulings resting on the same legislation. Separated from the last section by the same border a
   section uses, because that is what it is to a reader scrolling: another block after the text —
   not a sidebar, and not part of the ruling. */
.drawer-similar {
    margin-top: 1.5rem;
    padding-top: 1.2rem;
    border-top: 1px solid var(--line);
}

.similar-item {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
    padding: .6rem .7rem;
    border-radius: 10px;
    background: var(--surface-2);
}

.similar-item + .similar-item {
    margin-top: .4rem;
}

.similar-main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: .15rem;
}

.similar-title {
    font-size: .9rem;
    font-weight: 600;
    line-height: 1.5;
}

.similar-meta {
    font-size: .8rem;
    color: var(--ink-muted);
}

/* The instruments the two rulings have in common — the whole basis of the row being here, so it
   is stated rather than left to the heading. */
.similar-shared {
    font-size: .78rem;
    color: var(--ink-muted);
    unicode-bidi: plaintext;
}

.similar-more {
    margin-inline-start: .3rem;
}

/* The action keeps its own line once the row is narrow: at this width the button and a topic path
   share a line only by squeezing the path to a few characters. */
@media (max-width: 560px) {
    .similar-item {
        flex-direction: column;
    }
}

@media (max-width: 900px) {
    .drawer {
        width: 100%;
    }
}

/* ---------- empty state ---------- */

.empty-state {
    flex: 1 1 auto;
    display: grid;
    place-items: center;
    overflow-y: auto;
    padding: 2rem 1rem;
}

.hero {
    width: min(48rem, 100%);
    text-align: center;
}

.hero-title {
    font-size: 1.9rem;
    font-weight: 700;
    margin: 0 0 .5rem;
}

.hero-subtitle {
    color: var(--ink-muted);
    margin: 0 auto 2rem;
    max-width: 34rem;
}

.prompt-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: .75rem;
    text-align: start;
}

.prompt-card {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    padding: .85rem 1rem;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--surface);
    font: inherit;
    cursor: pointer;
    text-align: start;
    transition: border-color .12s ease, transform .12s ease;
}

.prompt-card:hover {
    border-color: var(--accent);
    transform: translateY(-1px);
}

.prompt-title {
    font-weight: 700;
    font-size: .88rem;
    color: var(--accent);
}

.prompt-text {
    font-size: .93rem;
    color: var(--ink-muted);
}

/* ---------- topic scope ---------- */

/* Shares the country row's measure and side padding so the two scopes read as one stack above
   the composer. Its own row because a leaf title is a sentence, not a five-character label, and
   wrapping it through the fixed country chips would break their alignment. */
.topic-scope-row {
    display: flex;
    width: min(48rem, 100%);
    margin: 0 auto .35rem;
    padding-inline: .55rem;
}

/* Filled in the accent rather than outlined like a country chip: this one is off by default and
   changes what the corpus even contains for the next question, so it should be the loudest thing
   in the row while it is on. */
.topic-chip {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    max-width: 100%;
    min-height: 26px;
    padding-inline: .7rem .35rem;
    border: 1px solid var(--accent);
    border-radius: 999px;
    background: var(--accent-soft);
    color: var(--accent);
    font-size: .78rem;
    font-weight: 700;
}

/* One line whatever the title's length: the chip sits directly above the composer, and a wrapped
   one pushes the input down the page every time the scope changes. */
.topic-chip-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.topic-chip-clear {
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    line-height: 1;
    padding: .1rem .3rem;
    opacity: .7;
    cursor: pointer;
}

.topic-chip-clear:hover {
    opacity: 1;
}

/* ---------- country scope ---------- */

/* Sits on top of the composer and shares its measure, so the scope reads as part of the input
   rather than as a toolbar over the conversation. Opaque rather than the composer's gradient:
   the message list scrolls underneath this row and would otherwise show through the chips. */
.country-scope {
    padding: .5rem 1rem 0;
    background: var(--bg);
}

/* The block's first line, the way ChatGPT pins its own caution over the composer. Smaller than
   the chips under it so the row of controls stays the thing the eye lands on; the measure keeps
   it aligned with the column the thread uses. */
.chat-disclaimer {
    width: min(48rem, 100%);
    margin: 0 auto .4rem;
    text-align: center;
    font-size: .72rem;
    color: var(--ink-muted);
}

.country-scope-row {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem;
    width: min(48rem, 100%);
    margin: 0 auto;
    /* Matches .composer-inner's own side padding, so a chip's edge lines up with the text in
       the box below it rather than with the box's border. */
    padding-inline: .55rem;
}

/* Deliberately not .chip: that one is the citation opener, sized to a one- or two-digit
   number and toggled per answer. The two share only an idea. */
.country-chip {
    height: 26px;
    padding: 0 .7rem;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface);
    color: var(--ink-muted);
    font: inherit;
    font-size: .78rem;
    font-weight: 700;
    cursor: pointer;
    transition: all .12s ease;
}

.country-chip:hover {
    border-color: var(--accent);
    color: var(--accent);
}

/* After the :hover rule and at equal specificity, so a selected chip keeps its filled look
   while the pointer is over it. */
.country-chip.on {
    background: var(--accent);
    border-color: var(--accent);
    color: #fff;
}

/* The last country standing. Still a button — the click is simply a no-op — so the title
   stays reachable on hover and the state is announced rather than merely implied. */
.country-chip[aria-disabled="true"] {
    cursor: default;
}

/* ---------- composer ---------- */

.composer {
    padding: .75rem 1rem 1rem;
    background: linear-gradient(to top, var(--bg) 65%, rgba(247, 247, 248, 0));
}

.composer-inner {
    display: flex;
    align-items: flex-end;
    gap: .5rem;
    width: min(48rem, 100%);
    margin: 0 auto;
    padding: .45rem .55rem;
    border: 1px solid var(--line);
    border-radius: 18px;
    background: var(--surface);
    box-shadow: var(--shadow);
}

.composer-inner:focus-within {
    border-color: var(--accent);
}

.composer-input {
    flex: 1 1 auto;
    resize: none;
    border: 0;
    outline: none;
    background: transparent;
    font: inherit;
    line-height: 1.7;
    padding: .35rem .5rem;
    max-height: 220px;
    /* Form controls do not inherit color; without this the UA default (near-black) sits on the
       dark surface and the draft is unreadable. No unicode-bidi: plaintext here — it re-anchors
       a Latin-only draft to the left edge; see the note on the textarea itself. */
    color: var(--ink);
    caret-color: var(--accent);
}

.composer-input::placeholder {
    color: var(--ink-muted);
}

.send-btn {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border: 0;
    border-radius: 12px;
    background: var(--accent);
    color: #fff;
    cursor: pointer;
    transition: opacity .12s ease;
}

.send-btn:disabled {
    opacity: .35;
    cursor: default;
}

/* The stop state keeps the send button's full accent: the square icon is the state change, and a
   muted background reads as disabled on exactly the turn the button is most needed. */

/* ---------- dark ---------- */

@media (prefers-color-scheme: dark) {
    :root {
        --bg: #0f1115;
        --surface: #171a20;
        --surface-2: #1e2229;
        --sidebar-bg: #0a0c10;
        --ink: #e7e9ee;
        --ink-muted: #a2a9b6;
        --line: #262b34;
        --accent: #5b9dff;
        --accent-soft: #16233a;
        /* Desaturated against the dark page: the light theme's saturated accent glows here, and
           the reference's own dark bubble is this muted slate blue. */
        --user-bubble-bg: #33507e;
        --user-bubble-fg: #eef2f8;
        --shadow: 0 1px 2px rgba(0, 0, 0, .4);
    }

    .banner {
        background: #2a2412;
        border-color: #4a3d17;
        color: #e8d6a3;
    }

    .message-error {
        background: #2a1618;
        border-color: #4d2528;
        color: #f0b9bc;
    }

    .composer {
        background: linear-gradient(to top, var(--bg) 65%, rgba(15, 17, 21, 0));
    }

    /* A yellow that works on white is invisible against the dark surface. Kept as an amber wash
       rather than the accent blue: blue is the citation marker's colour in this app, and a blue
       highlight over legal prose would read as a link. */
    .drawer-text mark {
        background: rgba(196, 142, 22, .35);
        color: inherit;
    }

    .drawer-text mark.focus {
        background: rgba(230, 168, 30, .55);
        box-shadow: 0 0 0 2px rgba(230, 168, 30, .3);
    }
}

/* ---------- print ---------- */

/* Last in the file on purpose. The dark palette above is a media query of the same weight, so the
   light values re-asserted here win only by coming after it — a reader whose machine is in dark
   mode would otherwise print pale text and dim highlights onto white paper.

   Two layouts share one block: with no class on the body it is the transcript, and body.print-ruling
   flips it to the drawer. chatUi.printPage sets the class for the duration of the print call. */
@media print {
    :root {
        --bg: #f7f7f8;
        --surface: #ffffff;
        --surface-2: #f1f2f4;
        --sidebar-bg: #14161a;
        --ink: #16181d;
        --ink-muted: #5c6270;
        --line: #e2e4e9;
        --accent: #1f6feb;
        --accent-soft: #e8f0fe;
        /* Paper drops backgrounds, so the bubble goes dark-on-white and gets its border back. */
        --user-bubble-bg: #ffffff;
        --user-bubble-fg: #16181d;
        --user-bubble-line: #e2e4e9;
        --shadow: 0 1px 2px rgba(16, 18, 22, .06), 0 8px 24px rgba(16, 18, 22, .06);
    }

    /* The three component rules the dark block overrides outside the token set. Same reasoning as
       the palette: they are equal-specificity media rules and only order settles them. */
    .message-error {
        border-color: #f0c2c2;
        background: #fdf2f2;
        color: #7d2020;
    }

    .drawer-text mark {
        background: rgba(255, 214, 102, .45);
    }

    .drawer-text mark.focus {
        background: rgba(255, 190, 40, .75);
        box-shadow: 0 0 0 2px rgba(255, 190, 40, .35);
    }

    body {
        background: #fff;
    }

    /* Navigation, controls, and the two indicators that only mean something while an answer is
       still arriving. The drawer goes with them and is restored below: the transcript is what a
       classless print produces. */
    .chat-sidebar,
    .chat-topbar,
    .chat-backdrop,
    .banner,
    .country-scope,
    .composer,
    .message-actions,
    .citation-actions,
    .thinking,
    .cursor,
    .print-btn,
    .drawer-layer {
        display: none !important;
    }

    /* The sources swap forms on paper: the chips are clicks and the card is one passage at a
       time, so both go, and the references list — hidden on screen — stands in for them with
       every [n] resolvable. The list keeps the light palette's line colour by token, since the
       print block re-asserts it above. */
    .chips,
    .citation-card {
        display: none !important;
    }

    .citations-print {
        display: block;
        margin: .5rem 0 0;
        padding-inline-start: 1.4rem;
        font-size: .82rem;
        line-height: 1.7;
    }

    .citations-print li {
        break-inside: avoid;
        margin: .15rem 0;
    }

    /* On screen the shell is a viewport-tall flexbox whose transcript is an inner scroller, which
       prints as one page holding whatever happened to be in view. Releasing the whole chain turns
       the conversation back into ordinary flowing content the printer can paginate. */
    html,
    body,
    .chat-shell,
    .chat-main,
    .chat-page {
        display: block;
        height: auto;
        min-height: 0;
        overflow: visible;
    }

    .message-scroll {
        overflow: visible;
    }

    /* Goes the way .citation-actions does. It tells a reader working in the app why these
       particular passages came back, so the next question can be retyped; a printed transcript is
       read away from the app by someone who cannot act on it. */
    .literal-search-note {
        display: none !important;
    }

    /* The reading measure exists to keep a line short on a wide screen; paper already has margins. */
    .message-column {
        width: auto;
        padding: 0;
    }

    /* Only the small atomic blocks. An assistant answer runs to several pages and must be allowed
       to break, so nothing here targets .message or .bubble generally. */
    .message.user {
        break-inside: avoid;
    }

    /* Browsers drop backgrounds when printing, and in these two the background *is* the meaning:
       which passage was highlighted, and which section a card quotes. */
    mark,
    .badge {
        print-color-adjust: exact;
        -webkit-print-color-adjust: exact;
    }

    /* The drawer prints alone. It cannot be isolated by hiding .chat-shell — the drawer renders
       inside .chat-page, so the shell is its ancestor and hiding it takes the drawer too — so the
       transcript's own surfaces are hidden instead and the panel is flattened into the page flow. */
    body.print-ruling .message-scroll,
    body.print-ruling .empty-state {
        display: none !important;
    }

    body.print-ruling .drawer-layer {
        display: block !important;
        position: static;
    }

    body.print-ruling .drawer-backdrop {
        display: none;
    }

    body.print-ruling .drawer {
        position: static;
        display: block;
        width: auto;
        height: auto;
        border: 0;
        box-shadow: none;
    }

    body.print-ruling .drawer-body {
        overflow: visible;
    }

    /* Every one of them: the close control, the back control, and the print control that started
       this. Written against the class rather than against each button, so a control added to the
       header is off the printed page by default. */
    body.print-ruling .drawer-head .icon-btn {
        display: none;
    }

    /* The header block only. A section is the ruling's body text and is expected to run for pages;
       forcing it whole would leave most of every sheet blank. */
    body.print-ruling .drawer-meta {
        break-inside: avoid;
    }

    /* Navigation, and it goes the way .citation-actions does above: a printed judgment ends at the
       ruling's own text. Rulings that merely cite the same statutes are not part of it, and on
       paper the panel's buttons lead nowhere. */
    body.print-ruling .drawer-similar {
        display: none !important;
    }
}
