/* =============================================================
   DICTATION — floating mic button + settings panel
   Theme-aware via body[data-cf-theme="light"|"dark"] (set by
   dictation.js from the active theme stylesheet).
   ============================================================= */

:root {
    /* One number for the mic's diameter, because things orbit it — the
       branch satellite sits on its rim and has to stay there when the size
       changes. Overridden per-breakpoint and while the keyboard is up. */
    --dict-size: 3.25rem;

    --dict-bg: #000d00;
    --dict-fg: #00bb00;
    --dict-fg-bright: #00ff00;
    --dict-border: #004400;
    --dict-glow: rgba(0, 255, 0, 0.25);
    --dict-danger: #ff4444;
}

body[data-cf-theme="light"] {
    --dict-bg: #f5ebd1;
    --dict-fg: #333;
    --dict-fg-bright: #111;
    --dict-border: #b7a684;
    --dict-glow: rgba(0, 0, 0, 0.15);
    --dict-danger: #b03030;
}

#dictationRoot {
    position: fixed;
    right: 1.25rem;
    bottom: 1.25rem;
    z-index: 9500;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.5rem;
    font-family: inherit;
}

/* ── Mic button ───────────────────────────────────────────── */

#dictationBtn {
    position: relative;
    width: var(--dict-size);
    height: var(--dict-size);
    border-radius: 50%;
    background-color: var(--dict-bg);
    color: var(--dict-fg);
    border: 1px solid var(--dict-border);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    box-shadow: 0 0 0 rgba(0, 0, 0, 0), inset 0 0 12px var(--dict-glow);
    transition: color 0.15s ease, border-color 0.15s ease, box-shadow 0.25s ease, transform 0.1s ease;
    -webkit-tap-highlight-color: transparent;
}

#dictationBtn:hover {
    color: var(--dict-fg-bright);
    border-color: var(--dict-fg-bright);
    box-shadow: 0 0 12px var(--dict-glow), inset 0 0 12px var(--dict-glow);
}

#dictationBtn:active {
    transform: scale(0.94);
}

/* The mic drawing. Excludes the taiji, which is also an <svg> in here and
   owns its own size and visibility — this rule's `display: block` outranked
   #dictationPlay's `display: none` and put both glyphs on the button at
   once. */
#dictationBtn > svg:not(#dictationPlay) {
    width: 1.35rem;
    height: 1.35rem;
    display: block;
    position: relative;
    z-index: 2;
}

/* Level ring — scaled by mic input amplitude while recording */
#dictationLevel {
    position: absolute;
    inset: -1px;
    border-radius: 50%;
    border: 1px solid var(--dict-fg-bright);
    opacity: 0;
    transform: scale(1);
    pointer-events: none;
    transition: opacity 0.2s ease;
}

#dictationRoot[data-state="recording"] #dictationBtn {
    color: var(--dict-fg-bright);
    border-color: var(--dict-fg-bright);
    box-shadow: 0 0 18px var(--dict-glow), inset 0 0 16px var(--dict-glow);
}

#dictationRoot[data-state="recording"] #dictationLevel {
    opacity: 0.7;
}

#dictationRoot[data-state="recording"] #dictationBtn::before {
    content: '';
    position: absolute;
    inset: -1px;
    border-radius: 50%;
    border: 1px solid var(--dict-fg-bright);
    animation: dictPulse 1.6s ease-out infinite;
    pointer-events: none;
}

@keyframes dictPulse {
    0% { transform: scale(1); opacity: 0.6; }
    100% { transform: scale(1.7); opacity: 0; }
}

/* Not set up yet — dimmed, with a marker that says "needs attention" */
#dictationRoot[data-state="setup"] #dictationBtn {
    opacity: 0.6;
}


/* Download progress ring — driven by --dict-progress (0–100) */
#dictationRing {
    position: absolute;
    inset: -3px;
    border-radius: 50%;
    pointer-events: none;
    opacity: 0;
    background: conic-gradient(var(--dict-fg-bright) calc(var(--dict-progress, 0) * 1%), transparent 0);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
    transition: opacity 0.2s ease;
}

#dictationRoot[data-state="working"] #dictationRing {
    opacity: 0.9;
}

/* Working (transcribing / loading model) */
#dictationRoot[data-state="working"] #dictationBtn {
    color: var(--dict-fg-bright);
    border-color: var(--dict-fg-bright);
}

#dictationRoot[data-state="working"] #dictationBtn::before {
    content: '';
    position: absolute;
    inset: -1px;
    border-radius: 50%;
    border: 1px solid transparent;
    border-top-color: var(--dict-fg-bright);
    animation: dictSpin 0.9s linear infinite;
    pointer-events: none;
}

@keyframes dictSpin {
    to { transform: rotate(360deg); }
}

/* Generating. The oracle button reports itself the way the mic does — it
   lights up and spins while the answer is being written, and dims back when
   it stops. This is why there is no "generating…" toast over the prose. */
#dictationRoot[data-generating="true"] #dictationBtn {
    color: var(--dict-fg-bright);
    border-color: var(--dict-fg-bright);
    box-shadow: 0 0 18px var(--dict-glow), inset 0 0 16px var(--dict-glow);
}

#dictationRoot[data-generating="true"] #dictationPlay {
    animation: dictPulse 1.1s ease-in-out infinite;
}

#dictationRoot[data-generating="true"] #dictationBtn::before {
    content: '';
    position: absolute;
    inset: -1px;
    border-radius: 50%;
    border: 1px solid transparent;
    border-top-color: var(--dict-fg-bright);
    animation: dictSpin 0.9s linear infinite;
    pointer-events: none;
}

@keyframes dictPulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.45; }
}

#dictationRoot[data-state="error"] #dictationBtn {
    color: var(--dict-danger);
    border-color: var(--dict-danger);
}

@media (prefers-reduced-motion: reduce) {
    #dictationBtn::before { animation: none !important; }
    #dictationLevel { transition: none; }
}

/* Small gear for settings, tucked against the mic */
/* ── Satellites ───────────────────────────────────────────────
   Settings, mode and the quick-action fan ride the TOP of the button's rim,
   evenly spaced 55° apart: settings upper-left, mode straight up, the fan
   upper-right. Nothing sits beside or below the button, so the bottom of the
   cluster stays clean for the thumb.
   Angles are measured clockwise from top-centre, exactly like #newBranchBtn
   in the phone layer — one convention for the whole cluster.

   The radius comes off the button's own diameter, so the three stay on the
   rim whatever size it is, and the counter-rotation keeps each glyph
   upright while it sits on the arc. */
#dictationGear,
#dictationMode {
    --sat-radius: calc(var(--dict-size) / 2 + 0.12rem);

    position: absolute;
    top: 50%;
    left: 50%;
    margin: -0.68rem 0 0 -0.68rem;
    width: 1.35rem;
    height: 1.35rem;
    transform: rotate(var(--sat-angle))
               translateY(calc(-1 * var(--sat-radius)))
               rotate(calc(-1 * var(--sat-angle)));
    border-radius: 50%;
    background-color: var(--dict-bg);
    color: var(--dict-fg);
    border: 1px solid var(--dict-border);
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding: 0;
    font-family: inherit;
    z-index: 3;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
    transition: color 0.15s ease, border-color 0.15s ease;
}

/* Upper-left */
#dictationGear {
    --sat-angle: -55deg;
    font-size: 0.7rem;
}

/* Straight up */
#dictationMode {
    --sat-angle: 0deg;
    font-size: 0.72rem;
}

#dictationGear:hover,
#dictationMode:hover {
    color: var(--dict-fg-bright);
    border-color: var(--dict-fg-bright);
}

/* In oracle mode the mic glyph would be a lie — the button asks the oracle,
   which answers whether or not an AI is behind it. A real element, not a
   ::after: the setup state already owns that pseudo-element for its "needs
   downloading" dot. The taiji sits a little large and optically low, so it
   is sized and nudged rather than left to the font. */
#dictationBtn #dictationPlay {
    display: none;
    width: 1.55rem;
    height: 1.55rem;
    position: relative;
    z-index: 2;
    color: inherit;
}

/* The mic drawing, not the taiji — both are <svg> inside this button now. */
#dictationRoot[data-mode="complete"] #dictationBtn > svg:not(#dictationPlay) {
    display: none;
}

#dictationRoot[data-mode="complete"] #dictationBtn #dictationPlay {
    display: block;
}

/* The setup dot reports on the DICTATION model, which says nothing about
   whether completion is ready. */
#dictationRoot[data-mode="complete"][data-state="setup"] #dictationBtn {
    opacity: 1;
}

/* The wrap is EXACTLY the button, so its centre and the button's centre are
   the same point. The satellites orbit that centre, and anything else that
   gets parked in here — the quick-action fan, which is absolute — can no
   longer stretch the box and drag the whole cluster off the rim. That was
   the bug: on a phone the fan's container made the wrap taller than the
   button, so settings and mode drifted off-centre and off-radius. */
#dictationBtnWrap {
    position: relative;
    width: var(--dict-size);
    height: var(--dict-size);
    flex: none;
}

/* ── Status pill ──────────────────────────────────────────── */

#dictationStatus {
    max-width: 16rem;
    background-color: var(--dict-bg);
    color: var(--dict-fg);
    border: 1px solid var(--dict-border);
    border-radius: 4px;
    padding: 0.3em 0.55em;
    font-size: 0.72rem;
    letter-spacing: 0.04em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    display: none;
}

#dictationStatus.visible {
    display: block;
}

/* ── Settings / consent panel ─────────────────────────────── */

/* The oracle panel is the dictation panel's twin — same box, same column
   above the button — so they are styled as one and only one is ever open. */
#dictationPanel,
#oraclePanel {
    width: min(15.5rem, calc(100vw - 2.5rem));
    background-color: var(--dict-bg);
    color: var(--dict-fg);
    border: 1px solid var(--dict-border);
    border-radius: 4px;
    padding: 0.75em;
    font-size: 0.8rem;
    box-shadow: 0 0 20px var(--dict-glow);
    display: none;
    max-height: min(70vh, 34rem);
    overflow-y: auto;
}

#dictationPanel.visible,
#oraclePanel.visible {
    display: block;
}

#dictationPanel h3,
#oraclePanel h3 {
    margin: 0 0 0.6em 0;
    font-size: 0.8rem;
    font-weight: normal;
    letter-spacing: 0.12em;
    color: var(--dict-fg-bright);
    text-transform: uppercase;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

#dictationPanel .dict-close,
#oraclePanel .dict-close {
    cursor: pointer;
    padding: 0 0.2em;
}

/* Setup status line — the single source of truth in the panel */
.dict-status-line {
    font-size: 0.68rem;
    line-height: 1.35;
    padding: 0.35em 0.5em;
    margin-bottom: 0.55em;
    border: 1px solid var(--dict-border);
    border-left-width: 3px;
    border-radius: 3px;
}

.dict-status-line[data-state="ready"] {
    border-left-color: var(--dict-fg-bright);
    color: var(--dict-fg-bright);
}

.dict-status-line[data-state="busy"],
.dict-status-line[data-state="live"] {
    border-left-color: var(--dict-fg-bright);
}

.dict-status-line[data-state="partial"] {
    border-left-color: var(--dict-fg);
}

.dict-status-line[data-state="blocked"] {
    border-left-color: var(--dict-danger);
}

/* Compact label-left / control-right rows */
.dict-row-field {
    display: flex;
    align-items: center;
    gap: 0.5em;
    margin-bottom: 0.35em;
}

.dict-row-field label {
    flex: 0 0 2.6rem;
    font-size: 0.68rem;
    letter-spacing: 0.06em;
    opacity: 0.8;
}

.dict-row-field select,
.dict-row-field input {
    flex: 1;
    min-width: 0;
    background-color: transparent;
    color: var(--dict-fg-bright);
    border: 1px solid var(--dict-border);
    border-radius: 3px;
    padding: 0.25em 0.3em;
    font-family: inherit;
    font-size: 0.75rem;
}

.dict-row-field select:focus,
.dict-row-field input:focus {
    outline: none;
    border-color: var(--dict-fg-bright);
}

.dict-row-field input.dict-cb {
    flex: 0 0 auto;
    margin-right: auto;
}








#dictationPanel button.dict-btn,
#oraclePanel button.dict-btn {
    background-color: transparent;
    color: var(--dict-fg);
    border: 1px solid var(--dict-border);
    border-radius: 3px;
    padding: 0.45em 0.6em;
    font-family: inherit;
    font-size: 0.78rem;
    cursor: pointer;
    width: 100%;
    margin-top: 0.15em;
}

#dictationPanel button.dict-btn:hover:not(:disabled),
#oraclePanel button.dict-btn:hover:not(:disabled) {
    color: var(--dict-fg-bright);
    border-color: var(--dict-fg-bright);
}

#dictationPanel button.dict-btn:disabled,
#oraclePanel button.dict-btn:disabled {
    opacity: 0.45;
    cursor: default;
}

#dictationPanel button.dict-btn.dict-btn-quiet,
#oraclePanel button.dict-btn.dict-btn-quiet {
    border-color: transparent;
    opacity: 0.7;
    font-size: 0.7rem;
    padding: 0.3em 0.6em;
}

#dictationPanel button.dict-btn.dict-btn-quiet:hover,
#oraclePanel button.dict-btn.dict-btn-quiet:hover {
    color: var(--dict-danger);
    border-color: var(--dict-danger);
    opacity: 1;
}

.dict-row {
    display: flex;
    gap: 0.4em;
    margin-top: 0.15em;
}

.dict-row button.dict-btn {
    flex: 1;
    margin-top: 0;
}

.dict-row button.dict-btn.dict-btn-quiet {
    flex: 0 0 auto;
}

.dict-note {
    font-size: 0.68rem;
    line-height: 1.45;
    opacity: 0.75;
    margin: 0 0 0.6em 0;
}

.dict-hr {
    border: none;
    border-top: 1px solid var(--dict-border);
    margin: 0.7em 0;
}

/* Model download progress */
#dictationProgress {
    display: none;
    margin-top: 0.5em;
}

#dictationProgress.visible {
    display: block;
}

.dict-bar {
    height: 4px;
    background-color: var(--dict-border);
    border-radius: 2px;
    overflow: hidden;
}

.dict-bar > div {
    height: 100%;
    width: 0%;
    background-color: var(--dict-fg-bright);
    transition: width 0.2s ease;
}

.dict-progress-label {
    font-size: 0.66rem;
    margin-top: 0.25em;
    opacity: 0.8;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ── Mobile ───────────────────────────────────────────────── */

@media (max-width: 768px) {
    :root {
        --dict-size: 3.6rem;
    }

    #dictationRoot {
        right: 0.9rem;
        /* Vertical position is owned by mobile.css, which docks it above
           the branch-tree handle and the phone's gesture bar. */
    }

    #dictationBtn > svg:not(#dictationPlay) {
        width: 1.5rem;
        height: 1.5rem;
    }

    #dictationGear {
        width: 1.6rem;
        height: 1.6rem;
        font-size: 0.8rem;
    }
}

/* Panel buttons must not out-grow the panel. The themes style bare
   <button> generously — drawer proportions, big padding, no shrink — and a
   long label like "import text…" pushed the row past 15.5rem and put a
   scrollbar under the panel. Pin them to the box: equal thirds, allowed to
   shrink, text clipped rather than expanding. */
#oraclePanel .dict-row {
    display: flex;
    gap: 0.4em;
    width: 100%;
    box-sizing: border-box;
}

#oraclePanel .dict-row button.dict-btn {
    flex: 1 1 0;
    min-width: 0;
    max-width: 100%;
    box-sizing: border-box;
    padding: 0.4em 0.3em;
    font-size: 0.7rem;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Nothing in the panel may widen it — a stray long option or label would
   otherwise scroll the whole box sideways. */
#oraclePanel {
    overflow-x: hidden;
}

#oraclePanel .dict-row-field select,
#oraclePanel .dict-row-field input {
    max-width: 100%;
    box-sizing: border-box;
}

/* ── Glyph metrics ────────────────────────────────────────────────
   The light theme applies 'Special Elite' to everything, including these
   buttons, and its ascent/descent are lopsided enough that a centred glyph
   visibly rides high — ⚙, ☯, ◉ all sat above the middle. Flex centring
   cannot fix that: it centres the LINE BOX, and the line box is what the
   font's metrics made crooked. So the cluster's symbols opt out of the
   display font and use one with even metrics. */
#dictationGear,
#dictationMode,
#newBranchBtn,
.qf-glyph,
.qa-glyph {
    font-family: system-ui, -apple-system, 'Segoe UI Symbol', sans-serif;
    line-height: 1;
}

/* ── The I Ching consultation ──────────────────────────────────
   A third panel in the floating cluster, same box as the other two, so all
   three read as one object. Only its innards are its own. */

#ichingPanel {
    width: min(19rem, calc(100vw - 2.5rem));
    background-color: var(--dict-bg);
    color: var(--dict-fg);
    border: 1px solid var(--dict-border);
    border-radius: 4px;
    padding: 0.75em;
    font-size: 0.8rem;
    box-shadow: 0 0 20px var(--dict-glow);
    display: none;
    max-height: min(76vh, 40rem);
    overflow-y: auto;
}

#ichingPanel.visible { display: block; }

#ichingPanel h3 {
    margin: 0 0 0.6em 0;
    font-size: 0.8rem;
    font-weight: normal;
    letter-spacing: 0.12em;
    color: var(--dict-fg-bright);
    text-transform: uppercase;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

#ichingPanel .dict-close { cursor: pointer; padding: 0 0.2em; }

.ich-prompt,
.ich-trigrams {
    font-size: 0.68rem;
    line-height: 1.35;
    opacity: 0.75;
    text-align: center;
}

.ich-head-block { margin-bottom: 0.2em; }

.ich-name {
    text-align: center;
    color: var(--dict-fg-bright);
    font-size: 0.9rem;
    margin-bottom: 0.15em;
}

/* The hexagram. Six rows, top line first, each one a bar with its total and
   the three coins that made it. */
.ich-column {
    display: flex;
    flex-direction: column;
    gap: 0.28em;
    align-items: center;
    margin: 0.7em 0;
}

.ich-row {
    display: flex;
    align-items: center;
    gap: 0.45em;
}

/* A yang bar is solid; a yin bar is the same width with the middle cut out,
   which is what makes the two read as one figure rather than two lengths. */
.ich-bar {
    width: 4.6rem;
    height: 0.42em;
    border-radius: 1px;
    background-color: var(--dict-fg);
}

.ich-yin {
    background-image: linear-gradient(to right,
        var(--dict-fg) 0 38%, transparent 38% 62%, var(--dict-fg) 62% 100%);
    background-color: transparent;
}

.ich-row-pending .ich-bar {
    background-color: transparent;
    background-image: linear-gradient(to right,
        var(--dict-border) 0 12%, transparent 12% 25%,
        var(--dict-border) 25% 37%, transparent 37% 50%,
        var(--dict-border) 50% 62%, transparent 62% 75%,
        var(--dict-border) 75% 87%, transparent 87% 100%);
}

.ich-moving .ich-bar { background-color: var(--dict-fg-bright); }
.ich-moving .ich-yin {
    background-color: transparent;
    background-image: linear-gradient(to right,
        var(--dict-fg-bright) 0 38%, transparent 38% 62%, var(--dict-fg-bright) 62% 100%);
}

.ich-value {
    font-size: 0.66rem;
    width: 0.9em;
    text-align: right;
    opacity: 0.8;
}

.ich-mark {
    font-size: 0.66rem;
    width: 0.8em;
    color: var(--dict-fg-bright);
}

.ich-coins { display: flex; gap: 0.2em; }

/* Heads filled, tails hollow — the same convention as the terminal. */
.ich-coins i {
    width: 0.42em;
    height: 0.42em;
    border-radius: 50%;
    border: 1px solid var(--dict-fg);
}

.ich-coins i.ich-head { background-color: var(--dict-fg); }

/* The reading. Scrolls inside the panel rather than stretching it. */
.ich-reading {
    max-height: 40vh;
    overflow-y: auto;
    border-top: 1px solid var(--dict-border);
    padding-top: 0.5em;
    margin-bottom: 0.6em;
}

.ich-section { margin-bottom: 0.7em; }

.ich-section h4 {
    margin: 0 0 0.2em 0;
    font-size: 0.64rem;
    font-weight: normal;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--dict-fg-bright);
}

.ich-section p {
    margin: 0;
    font-size: 0.72rem;
    line-height: 1.45;
}

.ich-sub {
    font-size: 0.72rem;
    color: var(--dict-fg-bright);
    margin-bottom: 0.2em;
}

#ichingPanel button.dict-btn {
    background-color: transparent;
    color: var(--dict-fg);
    border: 1px solid var(--dict-border);
    border-radius: 3px;
    padding: 0.45em 0.6em;
    font-family: inherit;
    font-size: 0.78rem;
    cursor: pointer;
    width: 100%;
    margin-top: 0.15em;
}

#ichingPanel button.dict-btn:hover { color: var(--dict-fg-bright); border-color: var(--dict-fg-bright); }
#ichingPanel .dict-row { display: flex; gap: 0.35em; }
#ichingPanel .dict-btn-quiet { font-size: 0.7rem; opacity: 0.85; }
