/* The Kintsugi Garden — visual identity * * Palette tokens. The kintsugi seam (--kg-gold) is the only accent; * the rest of the surface is warm paper and charcoal-brown ink. */ :root { --kg-gold: #BF953F; --kg-gold-deep: #8C6A1F; --kg-paper: #F4EFE4; --kg-paper-deep: #EAE2D0; --kg-ink: #2B2622; --kg-ink-soft: #6F6558; --kg-crack: #D9C99A; color-scheme: light; } /* Defeat any automatic dark-mode that the user-agent or Gradio's runtime * may try to apply. The kintsugi metaphor — black ink on warm paper — * doesn't translate to dark mode, and the theme tokens we set above * already cover the main surfaces. These rules catch anything that * slips through (form controls, scrollbars, system UI). */ html, body, .dark, body.dark, .gradio-container, .gradio-container.dark { background-color: var(--kg-paper) !important; color: var(--kg-ink) !important; } .dark input, .dark textarea, .dark select, body.dark input, body.dark textarea, body.dark select { background-color: var(--kg-paper-deep) !important; color: var(--kg-ink) !important; border-color: var(--kg-crack) !important; } .dark .block, .dark .form, .dark .panel, .dark .tabitem, .dark .markdown { background-color: var(--kg-paper) !important; color: var(--kg-ink) !important; } /* Page surface — narrower than Gradio's default, generous outer padding. */ .gradio-container { max-width: 1100px !important; padding: 40px 24px 80px !important; } /* Header band: mark on the left, wordmark + subtitle on the right, a single gold seam beneath the whole row. */ #kg-header h1 { font-size: 2.4rem; letter-spacing: -0.01em; margin: 0 0 4px; font-weight: 500; } #kg-header em { color: var(--kg-ink-soft); font-style: italic; } #kg-header { padding-bottom: 24px; border-bottom: 1px solid var(--kg-crack); position: relative; margin-bottom: 8px; } .kg-header-row { display: flex; align-items: center; gap: 20px; } .kg-header-mark { flex: 0 0 76px; width: 76px; height: 76px; line-height: 0; } .kg-header-mark svg { display: block; width: 100%; height: 100%; } .kg-header-text { min-width: 0; } .kg-header-text p { margin: 0; } .kg-header-text .kg-tagline { margin-top: 4px; font-size: 0.86rem; opacity: 0.85; } @media (max-width: 560px) { .kg-header-row { flex-direction: column; align-items: flex-start; gap: 12px; } } #kg-header::after { content: ""; position: absolute; left: 0; bottom: -1px; height: 2px; width: 120px; background: var(--kg-gold); } /* Disclaimer — a quiet framing line, not a slab. Gradio wraps the * Markdown in a .block container that defeats display:inline-block on * the host element, so we treat the disclaimer as a wide-but-light * band: smaller mono type, paper-deep wash, gold left-rule. The bold * "Disclaimer:" label still anchors the eye, but the line recedes * compared to the header above it. */ #kg-disclaimer { font-family: "SF Mono", "JetBrains Mono", ui-monospace, monospace; font-size: 0.74rem; line-height: 1.55; letter-spacing: 0.03em; color: var(--kg-ink-soft); border-left: 2px solid var(--kg-gold); padding: 8px 14px; background: var(--kg-paper-deep); margin: 12px 0 28px; } #kg-disclaimer strong { color: var(--kg-ink); font-weight: 500; } /* Privacy disclosure: quieter sibling to the disclaimer chip above — * same mono family + ink-soft color, but no gold rule, no wash, smaller * + lower opacity so it recedes. Honors the "data stays in your browser" * promise visibly without competing with the main disclaimer. */ #kg-privacy-note { font-family: "SF Mono", "JetBrains Mono", ui-monospace, monospace; font-size: 0.68rem; line-height: 1.5; letter-spacing: 0.03em; color: var(--kg-ink-soft); opacity: 0.75; padding: 0 16px; margin: -20px 0 24px; } /* Tabs: erase the default box; show a single gold underline on the * active tab that animates in like a freshly drawn seam. * * Selector note: Gradio 6.5.1 renders the tab strip as * .tabs > .tab-wrapper > .tab-container[role="tablist"] > button * earlier Gradio versions used .tab-nav. We list both so this CSS * survives a minor-version revert in either direction. The "kg-seam" * animation is load-bearing — it's the visual signature that gives the * page its kintsugi recurrence; without these selectors, Gradio's * theme accent leaks through and the seam never animates. */ .tab-nav, .tabs > .tab-wrapper, .tabs .tab-container[role="tablist"] { border-bottom: 1px solid var(--kg-crack) !important; background: transparent !important; } .tab-nav button, .tabs .tab-container[role="tablist"] > button { background: transparent !important; border: none !important; color: var(--kg-ink-soft) !important; font-size: 0.95rem; padding: 12px 18px !important; font-family: inherit; letter-spacing: 0.01em; } .tab-nav button.selected, .tabs .tab-container[role="tablist"] > button.selected, .tabs .tab-container[role="tablist"] > button[aria-selected="true"] { color: var(--kg-ink) !important; position: relative; } .tab-nav button.selected::after, .tabs .tab-container[role="tablist"] > button.selected::after, .tabs .tab-container[role="tablist"] > button[aria-selected="true"]::after { content: ""; position: absolute; left: 18px; right: 18px; bottom: -1px; height: 2px; background: var(--kg-gold); animation: kg-seam 0.6s ease-out; } @keyframes kg-seam { from { transform: scaleX(0); transform-origin: left; } to { transform: scaleX(1); } } /* Tab overflow indicator — at narrow viewports Gradio 6.5.1 measures * the tab strip and hides tabs that don't fit behind a three-dot * overflow affordance. Untouched it renders in ink-black at low * contrast against paper, easy to miss. We tint it kg-gold so the * "more tabs hide here" signal reads as a kintsugi seam too. */ .tabs .overflow-menu > button { color: var(--kg-gold) !important; padding: 0 8px !important; } .tabs .overflow-menu > button:hover { color: var(--kg-gold-deep) !important; } .tabs .overflow-dropdown { background: var(--kg-paper) !important; border: 1px solid var(--kg-crack) !important; border-top: 2px solid var(--kg-gold) !important; border-radius: 0 !important; } .tabs .overflow-dropdown button { color: var(--kg-ink) !important; font-family: inherit !important; padding: 10px 14px !important; background: transparent !important; } .tabs .overflow-dropdown button:hover { background: var(--kg-paper-deep) !important; } /* Primary button: kintsugi gold, flat, with a subtle deeper-gold drop. */ button.primary, .primary { background: var(--kg-gold) !important; color: var(--kg-paper) !important; padding: 10px 28px !important; font-family: inherit; letter-spacing: 0.02em; box-shadow: 0 1px 0 var(--kg-gold-deep) !important; } button.primary:hover, .primary:hover { background: var(--kg-gold-deep) !important; } /* Entry-type row: bottom-align the dropdown field with the Reflect * button. Without this, the button column stretches to fill the row * height while the dropdown's label sits at the top of its column — * the field and the button end up at different baselines and the * button looks oversized. We anchor everything to the bottom of the * row, constrain the Reflect button to roughly the dropdown field * height, and remove the wrapper column's default top padding so the * baselines line up cleanly. */ #kg-entry-row { align-items: flex-end !important; } #kg-reflect-col { align-self: flex-end !important; padding-top: 0 !important; } #kg-reflect-btn { align-self: flex-end !important; } #kg-reflect-btn button { min-height: 0 !important; height: 48px !important; padding: 0 28px !important; line-height: 48px !important; font-size: 1.05rem; } /* Secondary buttons — transparent with a gold border. */ button.secondary, .secondary { background: transparent !important; border: 1px solid var(--kg-gold) !important; color: var(--kg-ink) !important; } /* Soul Map tables — strip the spreadsheet look; gold underline beneath * headers. The .dataframe selectors used to be enough when Gradio * rendered a pandas-styled table, but Gradio 6.x emits a Svelte * component tree whose classes are hashed (.svelte-XYZ) and the * .dataframe class no longer reaches the visible cells. We anchor on * the elem_id/elem_classes set in app.py and force the palette down * through every nested table-ish element. Heavy use of !important is * deliberate — Gradio's runtime applies inline styles that otherwise * win specificity. * * Selector coverage: real
| / | , ARIA-role
* grid/row/cell variants (the editable variant uses divs with roles),
* and the .cell-wrap wrapper that Gradio nests value cells inside. */
.kg-soul-table,
.kg-soul-table * {
font-family: inherit;
}
.kg-soul-table table,
.kg-soul-table [role="grid"],
.kg-soul-table [role="table"] {
border-collapse: collapse;
background-color: var(--kg-paper) !important;
}
.kg-soul-table thead,
.kg-soul-table thead tr,
.kg-soul-table thead th,
.kg-soul-table [role="rowgroup"]:first-child,
.kg-soul-table [role="columnheader"] {
background-color: var(--kg-paper-deep) !important;
color: var(--kg-ink-soft) !important;
font-weight: 500 !important;
text-transform: lowercase;
letter-spacing: 0.04em;
border-bottom: 1px solid var(--kg-gold) !important;
}
.kg-soul-table tbody,
.kg-soul-table tbody tr,
.kg-soul-table tbody td,
.kg-soul-table [role="rowgroup"]:not(:first-child) [role="row"],
.kg-soul-table [role="cell"],
.kg-soul-table [role="gridcell"] {
background-color: var(--kg-paper) !important;
color: var(--kg-ink) !important;
border-color: var(--kg-crack) !important;
}
.kg-soul-table tbody tr:nth-child(even) td,
.kg-soul-table tbody tr:nth-child(even) [role="cell"],
.kg-soul-table tbody tr:nth-child(even) [role="gridcell"] {
background-color: var(--kg-paper-deep) !important;
}
.kg-soul-table th,
.kg-soul-table td {
border: none !important;
padding: 10px 12px !important;
}
/* The inner cell-wrap div Gradio uses for value content. */
.kg-soul-table .cell-wrap,
.kg-soul-table .table-wrap {
background-color: transparent !important;
color: var(--kg-ink) !important;
}
/* Dark-mode runtime override — Gradio sometimes flips internal cell
* backgrounds to a CSS variable like --table-row-bg that resolves to
* a dark color under .dark. Pin those variables here. */
.dark .kg-soul-table,
.kg-soul-table.dark {
--table-row-bg: var(--kg-paper);
--table-row-bg-odd: var(--kg-paper);
--table-row-bg-even: var(--kg-paper-deep);
--table-header-bg: var(--kg-paper-deep);
--table-header-fg: var(--kg-ink-soft);
--table-text-color: var(--kg-ink);
--table-border-color: var(--kg-crack);
--body-text-color: var(--kg-ink);
}
/* The Mandala — fixed-aspect square with a hairline gold frame. */
#kg-mandala {
aspect-ratio: 1 / 1;
border: 1px solid var(--kg-crack);
padding: 12px;
background: var(--kg-paper);
box-shadow:
0 0 0 8px var(--kg-paper),
0 0 0 9px var(--kg-gold);
position: relative;
}
/* Empty-mandala state: before the first Reflect, Gradio's image
* component renders a large grey placeholder icon. On a quiet paper
* surface that placeholder reads as broken-image clutter, not as
* "awaiting input." We use :has() to detect the absence of a populated
* |
|---|