"""audio·brief design tokens — lifted from Audio Brief.dc.html (Crate Dock). Three semantic colour families: - coral #FF6A3D — generative (prompts, gens, variants, "create") - mint #5BE0C8 — measured (BPM, key, sections, loudness, "observe") - amber #FFC24B — anchor (your favourited take we blend from) Fonts: Space Grotesk for body/heading, JetBrains Mono for numbers + labels. Background system: near-black (#0F1115) → panel (#121419) → card (#14171D) → input (#171A20). Borders step from #20242C (faint) to #2A2F38 (chip). The theme exposes Gradio's tokens; the CSS adds layout primitives the design needs that Gradio doesn't model (mono labels, metric tile grid, brand mark, pollen pill). All custom classes prefixed `dc-`. """ from __future__ import annotations import gradio as gr # --------------------------------------------------------------------------- # Pollinations App Key — public client identifier for audio-brief, issued at # auth.pollinations.ai. `pk_` prefix = publishable, safe to commit (Stripe- # style). Embedded in the OAuth authorize URL so Pollinations knows which # registered app is asking for consent and scopes the issued user-key to it. # The redirect URI registered alongside this key MUST match the production # URL the OAuth flow lands on — currently `https://kalamishere-audio-brief.hf.space/`. # --------------------------------------------------------------------------- POLLINATIONS_APP_KEY = "pk_dM3MSkFzNdenZCd5" # --------------------------------------------------------------------------- # Colour ramps — c500 anchors the brand colour; c50→c950 fade for hover/text # --------------------------------------------------------------------------- CORAL = gr.themes.Color( c50="#FFE7DD", c100="#FFD0BC", c200="#FFB89A", c300="#FFA279", c400="#FF8C5A", c500="#FF6A3D", # brand coral c600="#E55731", c700="#CC4424", c800="#A23217", c900="#78210B", c950="#140B07", # dark text on coral button ) MINT = gr.themes.Color( c50="#E1FBF6", c100="#C2F5EA", c200="#A2EFDE", c300="#83E9D3", c400="#5BE0C8", # brand mint (light) c500="#5BE0C8", # brand mint c600="#42C7AE", c700="#2BB89E", c800="#1B8C76", c900="#0F5949", c950="#06201B", ) # Warm-grey neutral — matches design's panel + text greys. ZINC = gr.themes.Color( c50="#F2EFE9", # primary text (cream) c100="#E3E0D9", c200="#C9CDD4", # secondary text c300="#99A0AB", # muted text c400="#7A828D", c500="#5E6671", # faint label text c600="#4A5158", c700="#3A3F47", c800="#2A2F38", # chip border c900="#20242C", # divider border c950="#0F1115", # page bg ) # --------------------------------------------------------------------------- # Theme object # --------------------------------------------------------------------------- THEME = gr.themes.Base( primary_hue=CORAL, secondary_hue=MINT, neutral_hue=ZINC, radius_size=gr.themes.sizes.radius_lg, spacing_size=gr.themes.sizes.spacing_md, text_size=gr.themes.sizes.text_md, font=[gr.themes.GoogleFont("Space Grotesk"), "system-ui", "sans-serif"], font_mono=[gr.themes.GoogleFont("JetBrains Mono"), "ui-monospace", "monospace"], ).set( # surfaces body_background_fill="#0F1115", body_text_color="#F2EFE9", body_text_color_subdued="#99A0AB", background_fill_primary="#0F1115", background_fill_secondary="#121419", block_background_fill="#14171D", block_border_color="#232831", block_border_width="1px", block_radius="14px", block_label_background_fill="transparent", block_label_text_color="#99A0AB", block_label_text_size="11px", block_label_text_weight="600", block_title_text_color="#F2EFE9", block_title_text_weight="600", panel_background_fill="#121419", panel_border_color="#20242C", border_color_primary="#232831", border_color_accent="#FF6A3D", # buttons button_primary_background_fill="#FF6A3D", button_primary_background_fill_hover="#FF8C5A", button_primary_text_color="#140B07", button_primary_border_color="#FF6A3D", button_secondary_background_fill="#171A20", button_secondary_background_fill_hover="#1B1F26", button_secondary_text_color="#C9CDD4", button_secondary_border_color="#2A2F38", button_cancel_background_fill="#171A20", button_cancel_text_color="#99A0AB", button_cancel_border_color="#2A2F38", button_large_radius="9px", button_small_radius="7px", # inputs input_background_fill="#0F1115", input_background_fill_focus="#121419", input_border_color="#232831", input_border_color_focus="#FF6A3D", input_placeholder_color="#5E6671", input_radius="9px", slider_color="#FF6A3D", # tables / dataframes table_border_color="#232831", table_even_background_fill="#14171D", table_odd_background_fill="#121419", table_row_focus="rgba(255,106,61,0.08)", table_text_color="#C9CDD4", # code / markdown code_background_fill="#0F1115", link_text_color="#5BE0C8", link_text_color_hover="#FF8C5A", # accent token used by various states color_accent="#5BE0C8", color_accent_soft="rgba(91,224,200,0.14)", ) # --------------------------------------------------------------------------- # CSS — what Gradio's theme tokens don't cover. # Adds: font import, scrollbar, brand mark, pollen pill, metric tiles, # inline-coloured number helpers, label mono-uppercase. # --------------------------------------------------------------------------- CUSTOM_CSS = """ /* ---- Fonts (Gradio's font= already injects these, kept as belt-and-braces) */ @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap'); body { font-family: 'Space Grotesk', system-ui, sans-serif !important; } code, kbd, pre, .mono, .dc-mono { font-family: 'JetBrains Mono', ui-monospace, monospace !important; } /* ---- Palette system (v3 design handoff) ------------------------------- Three named worlds the user toggles in the top bar. Implemented as a class on (`pal-studio` / `pal-console` / `pal-dub`) that defines a token set; every surface styles from var(--token) so a single class swap re-themes the tree. The 350ms cross-fade requested in the brief is intentionally NOT used here — animating background-color through a var() that resolves via a class swap stalls mid-transition in-engine (renders half-painted). Instant swap is correct and reliable. See design/README.md §⚠. Default below `:root` matches Console so var() resolves even before the JS class-swap runs on first paint. */ :root, body.pal-console { --paper:#13141A; --paper2:#181A22; --paper3:#1C1F28; --input:#1F232D; --ink:#F2EFE9; --ink2:#C9CDD4; --ink3:#99A0AB; --label:#5E6671; --line:#23262F; --line2:#1D2027; --chipline:#2E323C; --coral:#FF6A3D; --coralb:#FF8C5A; --onCoral:#140B07; --amber:#FFC24B; --metric:#5BE0C8; --mint:#5BE0C8; --secIntro:#2BB89E; --secBuild:#5BE0C8; --secCore:#FF6A3D; --secOutro:#FF8C5A; --coralTint: rgba(255,106,61,0.08); --coralTintHover: rgba(255,106,61,0.14); --amberTint: rgba(255,194,75,0.10); --drop: 0 24px 60px rgba(0,0,0,.40); } /* Studio (light) was the v3 design's primary new palette but shipped with multiple legibility regressions on Gradio v6 — browser-default button backgrounds beating our transparent rule, brand wordmark losing contrast, cost pip washing out, native button text inheriting the wrong color. Dropped from the toggle for now; spec preserved below for a dedicated Studio pass (will need Gradio-native button + input overrides at .pal-studio scope to beat user-agent styles). ---- body.pal-studio { --paper:#FBF8F1; --paper2:#F3EDE1; --paper3:#EAE2D2; --input:#FCFAF4; --ink:#0E1A1E; --ink2:#45565A; --ink3:#7A878A; --label:#8A969A; --line:rgba(14,26,30,0.14); --line2:rgba(14,26,30,0.09); --chipline:rgba(14,26,30,0.20); --coral:#D9461F; --coralb:#E8633A; --onCoral:#FBF8F1; --amber:#BC841C; --metric:#157567; --mint:#1C9482; --secIntro:#157567; --secBuild:#1C9482; --secCore:#D9461F; --secOutro:#E8633A; --coralTint: rgba(217,70,31,0.07); --coralTintHover: rgba(217,70,31,0.13); --amberTint: rgba(188,132,28,0.10); --drop: 0 1px 2px rgba(14,26,30,.10), 0 14px 40px rgba(14,26,30,.08); } */ body.pal-dub { --paper:#1B1612; --paper2:#241D17; --paper3:#2E2620; --input:#332A22; --ink:#E8DECB; --ink2:#C2B7A0; --ink3:#8C8270; --label:#6E6453; --line:#372E25; --line2:#2A231C; --chipline:#473C30; --coral:#FF7A4D; --coralb:#FF9468; --onCoral:#1B1612; --amber:#FFB94B; --metric:#7BE5CC; --mint:#7BE5CC; --secIntro:#3FB89E; --secBuild:#7BE5CC; --secCore:#FF7A4D; --secOutro:#FF9468; --coralTint: rgba(255,122,77,0.10); --coralTintHover: rgba(255,122,77,0.16); --amberTint: rgba(255,185,75,0.12); --drop: 0 22px 50px rgba(0,0,0,.55); } /* ---- Dub-only character pass — make it actually feel like vinyl, not just "Console but warmer". Each rule is scoped to body.pal-dub so the Console look is untouched. Pieces: 1. Subtle paper-grain noise overlay on body (fractalNoise SVG data URI, ~3% opacity) so card stock reads as material, not glass. 2. Brand wordmark dot flips mint → amber — Console's mint dot is a "measured" cue; Dub leans warmer, amber matches the anchor. 3. Coral buttons gain an inset bottom shadow so they read as stamped/inked rather than flat. Hover lifts the stamp. 4. Card-edge highlight (1px top inner glow + a slightly heavier border) — gives cards a worn-pressboard feel. 5. Metric numbers bump to 700 weight — the readout reads as chunky-typeset rather than the lighter Console face. 6. Top-bar bottom border thickens to 2px → reads as a turntable platter rim under the brand. */ body.pal-dub::before { content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 9999; opacity: 0.04; mix-blend-mode: overlay; background-image: url("data:image/svg+xml;utf8,"); background-size: 180px 180px; } body.pal-dub .dc-brand .dot { color: var(--amber); } body.pal-dub .gr-button.gr-button-primary, body.pal-dub .gr-button-primary, body.pal-dub button[class*="primary"] { box-shadow: inset 0 -2px 0 rgba(0,0,0,0.35), 0 1px 0 rgba(255,180,120,0.10) !important; text-shadow: 0 1px 0 rgba(0,0,0,0.20); } body.pal-dub .gr-button.gr-button-primary:hover, body.pal-dub .gr-button-primary:hover, body.pal-dub button[class*="primary"]:hover { box-shadow: inset 0 -1px 0 rgba(0,0,0,0.30), 0 2px 0 rgba(255,180,120,0.14) !important; } body.pal-dub .dc-metric, body.pal-dub .dc-anchor-player, body.pal-dub .dc-variants-prompt-card, body.pal-dub .dc-derived-card, body.pal-dub .dc-variant-title { box-shadow: inset 0 1px 0 rgba(255,210,170,0.04); border-width: 1px; } body.pal-dub .dc-metric-v { font-weight: 700; letter-spacing: -0.01em; } body.pal-dub .dc-topbar { border-bottom-width: 2px; border-bottom-color: var(--line); } body.pal-dub .dc-crate-strip label, body.pal-dub .dc-crate-strip .wrap label { box-shadow: inset 0 1px 0 rgba(255,210,170,0.05); } /* Anchor card in the variants row reads as the actual record on the mat — slightly warmer tint than Console's plain amber wash. */ body.pal-dub .dc-variant.anchor, body.pal-dub .dc-tile.anchor { background: linear-gradient(180deg, var(--amberTint) 0%, var(--paper3) 100%) !important; border-color: color-mix(in srgb, var(--amber) 55%, transparent) !important; } /* ---- Scrollbar — slim, neutral */ ::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar-thumb { background: var(--chipline); border-radius: 4px; } ::-webkit-scrollbar-track { background: transparent; } /* ---- Page container — palette-driven base, cap content width so the layout stays focused on wide monitors. Gradio v6 wraps content in `.wrap > main.contain` (no .gradio-container class). 1200px feels right for composer + crate; waveform + grids fill this width. Below 1200px viewport, the container naturally shrinks. The explicit width:100% on html/body/wrap defends against a Gradio v6 layout collapse: when a top-level state-changing element re-renders (e.g. the topbar gr.HTML refreshing after OAuth completes), the outer flex container can fall back to min-content width — which then shrinks to the widest single child (the 360px-capped Generate button). Pinning the chain to 100% width keeps it filling the viewport across re-renders. */ html, body, .wrap, gradio-app, gradio-app > div, .gradio-container { width: 100% !important; min-width: 100% !important; max-width: 100% !important; transform: none !important; zoom: 1 !important; } /* Stop any horizontal overflow so the centered main.contain doesn't sit off-axis — 100vw includes scrollbar width on Chromium/Brave, so anything pinned to 100vw drifts the layout right by the scroll gutter (~15px). Stay with 100% (respects scrollbar). */ html, body { overflow-x: hidden !important; } html { zoom: 1 !important; -webkit-text-size-adjust: 100% !important; } /* Belt-and-braces: if Gradio's .wrap is a flex container, margin:0 auto on main.contain won't center — assert it explicitly. */ .wrap { display: block !important; } main.contain, .wrap > main { background: transparent !important; color: var(--ink); width: 100% !important; max-width: 1280px !important; margin: 0 auto !important; padding: 28px 24px !important; box-sizing: border-box !important; } body { background: var(--paper) !important; color: var(--ink); position: relative; /* Soft brand-axis gradients on the body bg — coral at top-right (generative axis), mint at bottom-left (measured axis). Each sits at ~5% opacity so the surface stays Console-dark but reads as a composed page rather than a flat black plane. Designer cleanup pass: gives the eye warmth without competing with the Generate CTA. */ background-image: radial-gradient(60% 50% at 95% 0%, color-mix(in srgb, var(--coral) 14%, transparent), transparent 60%), radial-gradient(60% 60% at 5% 100%, color-mix(in srgb, var(--mint) 9%, transparent), transparent 65%) !important; background-attachment: fixed !important; } /* ---- Gradio native surface overrides — needed so block/input/button backgrounds re-paint per palette (the gr.themes.Base values were baked at construction time, so we re-assert via the class). */ body .block, body .panel { background: var(--paper2) !important; border-color: var(--line) !important; } body .form, body .gr-box { background: var(--paper3) !important; border-color: var(--line) !important; } body input[type="text"], body textarea, body .input-container { background: var(--input) !important; color: var(--ink) !important; border-color: var(--line) !important; } body .gr-button-primary, body button[class*="primary"] { background: var(--coral) !important; color: var(--onCoral) !important; border-color: var(--coral) !important; } body .gr-button-secondary, body button[class*="secondary"] { background: var(--input) !important; color: var(--ink2) !important; border-color: var(--chipline) !important; } /* Hide Gradio's footer ("Use via API" etc.) — clutter */ footer { display: none !important; } /* ---- Action button width cap — primary buttons should size to content, not stretch to the row width. ~360px is the design's big-CTA width. Prevents the "Use for analysis" button from ballooning to 1900px on a wide monitor when its sibling chip strip is full-width. Override via `elem_classes=["dc-full-button"]` on buttons that DO want to span the row (Generate / Regenerate on the prompt card). */ .gr-button.lg, .gr-button-lg, button.lg, button.gr-button-large { max-width: 360px !important; margin-left: 0 !important; } .dc-full-button button, button.dc-full-button { max-width: 100% !important; width: 100% !important; } /* Primary "Use for analysis →" in the crate row — cap its growth */ .dc-crate-row .gr-button-primary, .dc-crate-row button[class*="primary"] { max-width: 320px !important; flex: 0 0 auto !important; } /* ---- Headings — Space Grotesk weight/letter-spacing per design */ h1, h2, h3 { font-family: 'Space Grotesk', sans-serif !important; font-weight: 600; letter-spacing: -0.01em; color: var(--ink); } h1 { font-size: 22px; letter-spacing: -0.02em; } h2 { font-size: 16px; } h3 { font-size: 13px; color: var(--ink2); } /* ---- Brand wordmark — used in top bar HTML block */ .dc-brand { display: inline-flex; align-items: center; gap: 9px; font-family: 'Space Grotesk', sans-serif; font-weight: 600; font-size: 16px; letter-spacing: -0.01em; color: var(--ink); } .dc-brand .dot { color: var(--mint); margin: 0 1px; } .dc-brand-bars { display: inline-flex; align-items: flex-end; gap: 2px; height: 18px; } .dc-brand-bars > span { width: 3px; border-radius: 1px; display: inline-block; } .dc-brand-bars .b1 { height: 7px; background: var(--coral); } .dc-brand-bars .b2 { height: 16px; background: var(--coral); } .dc-brand-bars .b3 { height: 10px; background: var(--mint); } .dc-brand-bars .b4 { height: 13px; background: var(--mint); } /* ---- Palette toggle — circular swatch buttons. Each circle's interior paints the palette's paper color, the border ring uses that palette's accent (coral for Console, amber for Dub). Active = brighter ring + outer halo + faint scale; inactive dims to 55% so the active swatch reads loud. Hover restores full opacity. JS in the palette-swap script (top of app) updates body class + persists to localStorage. */ .dc-palette-toggle { display: inline-flex; align-items: center; gap: 8px; user-select: none; padding: 0 4px; } .dc-palette-toggle button { appearance: none !important; cursor: pointer !important; padding: 0 !important; width: 26px !important; height: 26px !important; flex-shrink: 0 !important; border-radius: 50% !important; background: var(--swatch-fill, var(--coral)) !important; border: 1.5px solid rgba(255,255,255,0.22) !important; box-shadow: none; opacity: 0.7; transition: opacity 120ms ease, transform 120ms ease, box-shadow 160ms ease; } .dc-palette-toggle button[data-pal="console"] { /* Console = coral solid (matches the brand's primary axis) */ --swatch-fill: #FF6A3D; } .dc-palette-toggle button[data-pal="dub"] { /* Dub = amber solid (the anchor / vinyl colour) */ --swatch-fill: #FFB94B; } .dc-palette-toggle button:hover { opacity: 0.95; transform: scale(1.06); } .dc-palette-toggle button.active { opacity: 1; transform: scale(1.10); border-color: rgba(255,255,255,0.45) !important; box-shadow: 0 0 0 2px var(--paper), 0 0 0 4px color-mix(in srgb, var(--swatch-fill) 70%, transparent), 0 6px 16px color-mix(in srgb, var(--swatch-fill) 28%, transparent); } /* Strip the Gradio .block chrome from gr.HTML elements that hold pure script/style tags. They were rendering as visible blank bars because Gradio still paints the block's background/border even when there's no DOM content. */ .dc-script-only, .dc-script-only > .block, .dc-script-only > div, .gradio-html.dc-script-only { display: none !important; } /* Off-screen hide for the wallet-bridge textbox. NOT display:none and NOT visible=False on the gr.Textbox — both pull the element out of the DOM, so the popup OAuth bridge JS can't find it to write the sk_... key. Off-screen + 1px + opacity 0 keeps the input mounted, focusable by JS, and addressable by getElementById('wallet-bridge-key'). */ .dc-wallet-bridge-hidden { position: fixed !important; left: -9999px !important; top: auto !important; width: 1px !important; height: 1px !important; overflow: hidden !important; opacity: 0 !important; pointer-events: none !important; } /* ---- Pollen balance pill — doubles as wallet button */ .dc-pollen-pill { display: inline-flex; align-items: center; gap: 7px; background: var(--input); border: 1px solid var(--chipline); border-radius: 20px; padding: 6px 13px; cursor: pointer; transition: border-color 120ms, background 120ms; user-select: none; } .dc-pollen-pill:hover { border-color: var(--coral); } .dc-pollen-pill .diamond { color: var(--amber); font-size: 13px; line-height: 1; } .dc-pollen-pill .balance { font-family: 'JetBrains Mono', monospace; font-weight: 600; font-size: 13px; color: var(--ink); } .dc-pollen-pill .lbl { font-family: 'JetBrains Mono', monospace; font-weight: 500; font-size: 10px; color: var(--label); } /* Not-connected state — coral CTA tint to invite the click */ .dc-pollen-pill.not-connected { background: var(--coralTint); border-color: var(--coral); } .dc-pollen-pill.not-connected:hover { background: var(--coralTintHover); border-color: var(--coral); } .dc-pollen-pill.not-connected .diamond { color: var(--coralb); } .dc-pollen-pill.not-connected .balance { color: var(--coralb); } .dc-pollen-pill.not-connected .lbl { color: var(--coral); opacity: 0.7; } /* ---- Session spend pill — running total ◆ pollen this visit. Sits to the left of the wallet pill. Muted by default (it's reference info, not a CTA); only shown when there's actual spend > 0. */ .dc-session-pill { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; background: transparent; border: 1px solid var(--line2); border-radius: 14px; font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--label); user-select: none; } .dc-session-pill .amt { font-weight: 600; color: var(--ink3); } .dc-session-pill .diamond { color: var(--amber); opacity: 0.7; font-size: 11px; } .dc-session-pill .lbl { font-size: 9px; letter-spacing: 0.08em; text-transform: uppercase; } /* ---- Inline cost pip — small inline annotation next to the Generate / Regenerate buttons. Reads "~0.04 ◆ per call · flat". */ .dc-cost-pip { display: inline-flex; align-items: center; gap: 5px; padding: 4px 10px; background: var(--paper3); border: 1px solid var(--line2); border-radius: 7px; font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink3); margin: 8px 0; width: fit-content; } .dc-cost-pip .amt { color: var(--ink2); font-weight: 600; } .dc-cost-pip .diamond { color: var(--amber); } .dc-cost-pip .sep { color: var(--ink3); } /* ---- Variation HOLD chips — placeholder for the CFG control Pollinations doesn't expose yet. Entire group disabled at 0.45 opacity so users can see the shape coming, but can't click. Reactivate when Pollinations adds a CFG/guidance param to /audio/{text}. */ .dc-var-hold { opacity: 0.45; pointer-events: none; user-select: none; margin: 10px 0; } .dc-var-hold .head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; } .dc-var-hold .head .label { font-family: 'JetBrains Mono', monospace; font-size: 11px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--label); } .dc-var-hold .head .tag { font-family: 'JetBrains Mono', monospace; font-size: 10px; color: var(--label); padding: 2px 8px; border: 1px solid var(--line2); border-radius: 6px; background: var(--paper3); } .dc-var-hold .chips { display: flex; gap: 6px; } /* ---- Two-column regen controls — Variant Duration | Variants ------- */ .dc-regen-control-row { align-items: stretch !important; gap: 16px !important; margin-top: 10px !important; } .dc-regen-control-card { border: 1px solid var(--line) !important; border-radius: 12px !important; background: var(--paper2) !important; padding: 14px 16px !important; } .dc-regen-control-card .dc-label { margin-bottom: 8px; } /* Suppress the giant default radio fieldset margin so the choices sit right under the label inside the card. */ .dc-regen-control-card fieldset { margin-top: 0 !important; } /* The .info text under each radio (small grey hint) keeps a tight line-height so the cards stay roughly equal in height. */ .dc-regen-control-card .info { margin-top: 8px !important; line-height: 1.35 !important; } /* ---- TRANSFORM tab engine selector — Morpho vs Local SA3 ---------- */ .dc-transform-engine .wrap, .dc-transform-engine > div { display: flex !important; flex-direction: row !important; gap: 8px !important; margin: 0 0 14px !important; } .dc-transform-engine label { flex: 1 1 0 !important; padding: 10px 14px !important; border: 1px solid var(--chipline) !important; border-radius: 10px !important; background: var(--paper2) !important; color: var(--ink2) !important; font-family: 'JetBrains Mono', monospace !important; font-size: 12px !important; cursor: pointer !important; transition: border-color 120ms, color 120ms, background 120ms !important; } .dc-transform-engine label:hover { border-color: var(--ink3) !important; color: var(--ink) !important; } .dc-transform-engine label.selected { border-color: var(--coral) !important; color: var(--coral) !important; background: color-mix(in srgb, var(--coral) 10%, var(--paper2)) !important; } .dc-transform-engine input[type="radio"] { display: none !important; } /* ---- Regen history tabs — radio rendered as a horizontal tab strip above the variants row. Each tab is one saved regen batch (`MATCH·1`, `LOOSE·1`, `MATCH·2`, etc.). Click → replay that batch into the variants cards + prompt-used card. */ .dc-regen-tabs .wrap, .dc-regen-tabs > div { display: flex !important; flex-direction: row !important; flex-wrap: wrap !important; gap: 6px !important; margin: 14px 0 6px !important; } .dc-regen-tabs label { padding: 6px 12px !important; background: var(--paper3) !important; border: 1px solid var(--line) !important; border-radius: 6px !important; font-family: 'JetBrains Mono', monospace !important; font-size: 11px !important; font-weight: 600 !important; letter-spacing: 0.08em !important; color: var(--ink3) !important; cursor: pointer !important; transition: background 120ms, border-color 120ms, color 120ms; } .dc-regen-tabs label:hover { background: var(--input) !important; color: var(--ink) !important; border-color: var(--coral) !important; } .dc-regen-tabs label.selected { background: var(--coralTint) !important; border-color: color-mix(in srgb, var(--coral) 60%, transparent) !important; color: var(--coralb) !important; } .dc-regen-tabs input[type="radio"] { display: none !important; } /* ---- Variants prompt-used card — sits above the ANCHOR + 5 VARIANTS title and echoes the derived prompt that produced the batch. Helps users see at a glance which lens / wording landed which 5 gens. */ .dc-variants-prompt-card { background: var(--paper3); border: 1px solid var(--line); border-radius: 8px; padding: 10px 14px; margin: 14px 0 6px; } .dc-variants-prompt-card .head { font-family: 'JetBrains Mono', monospace; font-size: 10px; font-weight: 600; letter-spacing: 0.12em; color: var(--label); margin-bottom: 6px; } .dc-variants-prompt-card .body { font-family: 'JetBrains Mono', monospace; font-size: 11px; line-height: 1.55; color: var(--ink2); white-space: pre-wrap; } /* ---- Variant cards (anchor + 5 variants in one row) — each is a Column containing a custom HTML title + an Audio component, so they all line up at the same height regardless of how the audio widget grows. Title carries the BPM/Harm/Rhyt bar breakdown on three left-aligned lines + the v-name in the bottom-right. */ .dc-variant-cell { min-width: 0; /* let columns shrink in a tight row */ } .dc-variant-title { background: var(--paper3); border: 1px solid var(--line); border-radius: 8px 8px 0 0; border-bottom: none; padding: 6px 10px; min-height: 28px; display: flex; justify-content: space-between; align-items: center; gap: 8px; white-space: nowrap; overflow: hidden; } .dc-variant-title .bars { font-family: 'JetBrains Mono', monospace; font-size: 10px; line-height: 1.2; color: var(--label); /* track behind the meter — muted grey */ text-align: left; flex: 1; overflow: hidden; text-overflow: ellipsis; } .dc-variant-title .bars .fill { color: var(--mint); /* mint — measured axis, the metering colour */ font-weight: 600; } .dc-variant-title .bars.placeholder { color: var(--ink3); /* faded — pre-regen state */ } .dc-variant-title .bars.anchor-label { font-size: 12px; color: var(--amber); /* amber for the anchor */ font-weight: 600; letter-spacing: 0.05em; } .dc-variant-title .name { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--label); font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; } /* The Audio sits directly under the title — kill its rounded top so they read as one card. */ .dc-variant-cell .audio-container, .dc-variant-cell [class*="audio"] > div:first-child { border-top-left-radius: 0 !important; border-top-right-radius: 0 !important; border-top: none !important; } /* ---- Prompt-lens chip row (Analysis tab, above derived prompt textbox). Three radio options rendered as horizontally-arranged chips that indicate decreasing fidelity to the measured arc via the leading freedom-bars glyphs (▮▮▮▮ MATCH / ▮▮▯▯ LOOSE / ▮▯▯▯ FREE). Visual coherence with the variant card bars is intentional — both use the same glyph language for "how much constraint the LLM has". */ .dc-lens-chips .wrap, .dc-lens-chips > div { display: flex !important; flex-direction: row !important; gap: 8px !important; margin: 4px 0 12px !important; } .dc-lens-chips label { flex: 1 !important; padding: 8px 12px !important; background: var(--paper3) !important; border: 1px solid var(--line) !important; border-radius: 8px !important; cursor: pointer !important; font-family: 'JetBrains Mono', monospace !important; font-size: 11px !important; color: var(--ink2) !important; text-align: center !important; line-height: 1.45 !important; transition: background 120ms, border-color 120ms, color 120ms; } .dc-lens-chips label:hover { background: var(--input) !important; border-color: var(--coral) !important; color: var(--ink) !important; } .dc-lens-chips label.selected { background: var(--coralTint) !important; border-color: color-mix(in srgb, var(--coral) 60%, transparent) !important; color: var(--coralb) !important; } .dc-lens-chips input[type="radio"] { display: none !important; } /* ---- Anchor player (Analysis tab) — raw HTML5