@import url('https://fonts.googleapis.com/css2?family=Fredoka+One&family=Patrick+Hand&family=Gloria+Hallelujah&display=swap'); :root { --paper: #fffef7; --paper-edge: #f5ecd9; --crayon-blue: #4a90d9; --crayon-red: #e15a4e; --crayon-yellow: #f5c842; --crayon-green: #6fb05e; --crayon-purple: #9b6db5; --crayon-pink: #f08ab0; --crayon-orange: #f0934a; --ink: #2d3142; /* dark mode surface tokens (overridden below when .dark is active) */ --surface-card: var(--paper); --surface-input: rgba(255, 255, 255, 0.6); --surface-dropdown: #ffffff; --surface-canvas: #f3f1ec; --surface-canvas-inner: #fdfbf3; } /* ── Dark mode ── */ .dark { --paper: #1a1b2e; --paper-edge: #16172a; --ink: #e8e4d9; --crayon-blue: #6aabf0; --crayon-yellow: #f5c842; --crayon-red: #f07066; --crayon-orange: #f5a060; --crayon-green: #80cc6e; --surface-card: #1e2040; --surface-input: rgba(30, 32, 64, 0.85); --surface-dropdown: #252848; --surface-canvas: #1c1e38; --surface-canvas-inner: #23264a; } /* Dark mode toggle button */ .dark-toggle-label { display: inline-flex; align-items: center; gap: 8px; font-family: 'Fredoka One', cursive !important; font-size: 1.05rem !important; color: var(--ink) !important; cursor: pointer !important; } #dark-toggle-btn { width: 40px; height: 22px; appearance: none; -webkit-appearance: none; background: var(--ink); border: 2.5px solid var(--ink); border-radius: 22px; position: relative; cursor: pointer; transition: background .2s; } #dark-toggle-btn:checked { background: var(--crayon-blue) !important; } #dark-toggle-btn::before { content: ''; position: absolute; left: 0px; top: -0.5px; width: 18px; height: 18px; background: var(--paper); border-radius: 50%; transition: transform .2s; } #dark-toggle-btn:checked::before { transform: translateX(16px); } #dark-toggle-btn:hover { transform: translate(-1px, -1px) !important; box-shadow: 4px 4px 0 rgba(45, 49, 66, 0.2) !important; } .gradio-container { background: var(--paper) !important; background-image: radial-gradient(circle at 20% 30%, rgba(245, 200, 66, 0.06) 0%, transparent 30%), radial-gradient(circle at 80% 70%, rgba(74, 144, 217, 0.06) 0%, transparent 30%), radial-gradient(circle at 50% 90%, rgba(240, 138, 176, 0.06) 0%, transparent 30%); font-family: 'Patrick Hand', sans-serif !important; color: var(--ink) !important; min-height: 100vh; transition: background 0.3s ease, color 0.3s ease; } .dark .gradio-container { background-image: radial-gradient(circle at 20% 30%, rgba(106, 171, 240, 0.05) 0%, transparent 30%), radial-gradient(circle at 80% 70%, rgba(155, 109, 181, 0.05) 0%, transparent 30%), radial-gradient(circle at 50% 90%, rgba(245, 200, 66, 0.04) 0%, transparent 30%) !important; } #title-block { text-align: center; padding: 40px 24px 16px; } #title-block::after { content: ""; display: block; width: 280px; height: 18px; margin: 20px auto 0; /* Hand-drawn squiggle. Inline SVG as a background image — single ink color, gentle wave reading as "kid drew a wavy line under the title". */ background-image: url("data:image/svg+xml;utf8,"); background-repeat: no-repeat; background-size: contain; background-position: center; opacity: 0.85; } #title-block h1 { font-family: 'Fredoka One', cursive !important; font-weight: 400 !important; font-size: 4.2rem !important; color: var(--ink) !important; margin: 0 !important; letter-spacing: 0.02em; line-height: 1 !important; text-shadow: 3px 3px 0px rgba(245, 200, 66, 0.45); } #title-block .subtitle { font-family: 'Patrick Hand', sans-serif !important; font-size: 1.4rem !important; color: var(--crayon-blue) !important; margin-top: 12px; font-weight: 400; transform: rotate(-1.5deg); display: inline-block; } /* Orientation copy under the title. Sits BELOW the sketched squiggle (the #title-block::after pseudo-element) so the squiggle reads as the title's closing flourish, and the explainer is its own calmer block underneath. Plain warm prose — what the app IS and who does WHAT, in two lines. */ #title-explainer { font-family: 'Patrick Hand', sans-serif; font-size: 1.15rem; color: var(--ink); opacity: 0.82; margin: 12px auto 24px; max-width: 640px; line-height: 1.5; text-align: center; } #title-explainer .explainer-roles { display: block; margin-top: 6px; font-size: 1.0rem; opacity: 0.85; font-style: italic; } /* ---------- Step diagram (1 ➜ 2 ➜ 3) ------------------------------------- Wayfinding strip just under the title. Three larger pills connected by dashed lines, hand-drawn aesthetic to match the rest of the app. Each pill contains: number badge (popped above), emoji icon, short heading, and a two-line description. Step 1 is styled with a dashed border to visually telegraph "optional" — backs up the explicit "(optional)" text underneath. The diagram doubles as the main explainer of how Lolaby works, so it sits prominently above the cards. */ #step-diagram { display: flex; align-items: flex-start; /* top-align so descs of different lengths don't shift the headings */ justify-content: center; gap: 6px; margin: 8px auto 32px; flex-wrap: wrap; max-width: 920px; } #step-diagram .step { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 14px 18px 16px; background: rgba(255, 255, 255, 0.35); border: 2.5px solid var(--ink); border-radius: 16px 20px 14px 18px; /* irregular to look hand-drawn */ width: 240px; flex: 0 1 240px; box-shadow: 2px 2px 0 rgba(45, 49, 66, 0.12); position: relative; } .dark #step-diagram .step { background: rgba(30, 32, 64, 0.75); box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.3); } #step-diagram .step-optional { border-style: dashed; background: rgba(255, 255, 255, 0.35); opacity: 0.92; } .dark #step-diagram .step-optional { background: rgba(30, 32, 64, 0.35); } #step-diagram .step-num { font-family: 'Fredoka One', sans-serif; font-size: 1.25rem; color: var(--ink); background: var(--crayon-yellow); width: 30px; height: 30px; border-radius: 50%; border: 2.5px solid var(--ink); display: inline-flex; align-items: center; justify-content: center; line-height: 1; margin-top: -28px; /* pop the number above the pill */ margin-bottom: 4px; box-shadow: 1px 1px 0 rgba(45, 49, 66, 0.15); } .dark #step-diagram .step-num { color: var(--paper); } #step-diagram .step-icon { font-size: 1.7rem; line-height: 1; margin: 2px 0; } #step-diagram .step-label { font-family: 'Fredoka One', sans-serif; font-size: 1.05rem; color: var(--ink); text-align: center; line-height: 1.2; margin-bottom: 4px; } #step-diagram .step-sub { font-family: 'Patrick Hand', sans-serif; font-weight: normal; font-size: 0.85rem; opacity: 0.7; display: block; margin-top: 2px; } #step-diagram .step-desc { font-family: 'Patrick Hand', sans-serif; font-size: 0.95rem; color: var(--ink); opacity: 0.82; text-align: center; line-height: 1.35; margin-top: 2px; } #step-diagram .step-connector { flex: 0 0 24px; height: 0; border-top: 2.5px dashed var(--ink); opacity: 0.5; /* Connector centred vertically against the pill's vertical mid-point. The pills are ~150px tall now, so the connector needs a ~70px top offset so it visually meets the middle of the boxes, not the top. */ margin-top: 70px; border-radius: 50%; } @media (max-width: 880px) { /* When the strip can't fit three pills + connectors, stack vertically. Hide connectors so the pills stack cleanly. */ #step-diagram { flex-direction: column; align-items: center; gap: 24px; } #step-diagram .step-connector { display: none; } #step-diagram .step { width: 280px; flex: 0 0 auto; } } /* ---------- Step badge (small number inside a card tab) ------------------ Reinforces the diagram by anchoring each card to its step number. Once a user scrolls past the diagram they can still see which step they're on by looking at the card tab. */ .step-badge { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; margin-right: 6px; background: #2d3142 !important; color: #ffffff !important; border-radius: 50%; font-family: 'Fredoka One', sans-serif; font-size: 0.85rem; line-height: 1; vertical-align: middle; position: relative; top: -1px; } .step-badge-inline { background: var(--crayon-yellow); color: var(--ink); border: 2px solid var(--ink); margin-right: 8px; } /* ---------- Step-3 hint above the Sing button --------------------------- Sits right above the primary CTA so a non-power user sees a clear "this is the next thing to do" line before the button itself. */ .step-3-hint { font-family: 'Patrick Hand', sans-serif; font-size: 1.05rem; color: var(--ink); text-align: center; margin: 18px 0 8px; opacity: 0.9; } label>span, .gradio-container label>span:first-child { font-family: 'Fredoka One', cursive !important; font-size: 1.2rem !important; color: var(--ink) !important; font-weight: 400 !important; } input[type="text"], input[type="number"], textarea, select { background: rgba(255, 255, 255, 0.6) !important; border: 2.5px solid var(--ink) !important; border-radius: 14px 18px 12px 16px !important; color: var(--ink) !important; font-family: 'Patrick Hand', sans-serif !important; font-size: 1.15rem !important; padding: 10px 14px !important; box-shadow: 3px 3px 0 rgba(45, 49, 66, 0.12); transition: all 0.18s ease; } .dark input[type="text"], .dark input[type="number"], .dark textarea, .dark select, .dark input[role="listbox"] { background: var(--paper) !important; color: var(--ink) !important; } input[type="text"]:focus, textarea:focus, select:focus { border-color: var(--crayon-blue) !important; box-shadow: 4px 4px 0 var(--crayon-yellow); outline: none; } /* Dropdown: style only the visible trigger input, leave the options panel with Gradio defaults so it stays usable. */ .gradio-dropdown input { background: rgba(255, 255, 255, 0.6) !important; border: 2.5px solid var(--ink) !important; border-radius: 14px 18px 12px 16px !important; color: var(--ink) !important; font-family: 'Patrick Hand', sans-serif !important; font-size: 1.15rem !important; padding: 10px 14px !important; box-shadow: 3px 3px 0 rgba(45, 49, 66, 0.12); } .dark .gradio-dropdown input { background: rgba(30, 32, 64, 0.85) !important; color: var(--ink) !important; } /* Make sure the options popup is on top and uses readable defaults */ .gradio-dropdown ul, .gradio-dropdown [role="listbox"], ul.options { background: #ffffff !important; border: 2px solid var(--ink) !important; border-radius: 8px !important; font-family: 'Patrick Hand', sans-serif !important; color: var(--ink) !important; z-index: 9999 !important; box-shadow: 4px 4px 0 rgba(45, 49, 66, 0.18); } .gradio-dropdown ul li, .gradio-dropdown [role="option"], ul.options li { padding: 8px 14px !important; font-family: 'Patrick Hand', sans-serif !important; font-size: 1.05rem !important; color: var(--ink) !important; background: transparent !important; cursor: pointer; } .gradio-dropdown ul li:hover, .gradio-dropdown [role="option"]:hover, ul.options li:hover { background: var(--crayon-yellow) !important; } .dark .gradio-dropdown ul, .dark .gradio-dropdown [role="listbox"], .dark ul.options { color: var(--paper) !important; } .dark .reset-button { color: var(--ink) !important; } .dark ul.options li, .dark .gradio-dropdown ul li, .dark .gradio-dropdown [role="option"] { color: var(--paper) !important; } input[type="range"] { accent-color: var(--crayon-red) !important; } .form-card { background: var(--paper) !important; border: 3px solid var(--ink) !important; border-radius: 22px 18px 26px 16px !important; padding: 28px !important; box-shadow: 5px 5px 0 rgba(45, 49, 66, 0.08); /* No transform here — it creates a stacking context that breaks Gradio's fixed-position dropdown popup. */ } .dark .form-card { box-shadow: 5px 5px 0 rgba(0, 0, 0, 0.3) !important; } .dark .form-card div { background-color: var(--paper) !important; } .form-card-right { background: var(--paper) !important; border: 3px solid var(--ink) !important; border-radius: 18px 24px 16px 22px !important; padding: 28px !important; box-shadow: 5px 5px 0 rgba(245, 200, 66, 0.25); } .dark .form-card-right { box-shadow: 5px 5px 0 rgba(245, 200, 66, 0.12) !important; } .dark .form-card-right div { background-color: var(--paper) !important; } /* ---- Drawing canvas card ----------------------------------------------- */ /* Matches the form-card aesthetic: paper background, ink border, wobbly corners that read as "drawn by hand". Sits above the form as the hero. */ .draw-card { background: var(--paper) !important; border: 3px solid var(--ink) !important; border-radius: 24px 16px 22px 18px !important; padding: 24px 28px 18px !important; box-shadow: 5px 5px 0 rgba(74, 144, 217, 0.18); margin-bottom: 12px; } .dark .draw-card { box-shadow: 5px 5px 0 rgba(106, 171, 240, 0.12) !important; } .draw-card .card-heading { margin-bottom: 4px; } .draw-hint { font-family: 'Patrick Hand', sans-serif; color: var(--ink); opacity: 0.7; font-size: 1.0rem; margin: 0 0 14px 0; } /* ---------- Split draw card: canvas | upload ------------------------------ The draw card hosts two side-by-side image inputs so trackpad-allergic users (i.e. small children) can upload a phone photo of a paper drawing instead of trying to draw with a mouse. Soft vertical divider between the two halves; on narrow viewports the columns stack and the divider becomes a horizontal one. */ #draw-row { gap: 18px; align-items: stretch; } .draw-half { padding: 0 6px; position: relative; z-index: 2; /* sit above background doodles */ } /* Vertical divider between the two halves, drawn on the canvas-side's right edge so it sits exactly between the two columns. */ .draw-half-canvas { border-right: 2px dashed rgba(45, 49, 66, 0.18); padding-right: 18px; } .draw-half-upload { padding-left: 6px; } /* Small label above each half so people immediately see "this side OR that side." Same font as the hint, slightly bolder, slightly darker. */ .draw-half-label { font-family: 'Patrick Hand', sans-serif; font-size: 1.05rem; color: var(--ink); opacity: 0.85; margin: 0 0 8px; font-weight: 700; letter-spacing: 0.01em; } /* The little caption under the upload widget, mirroring the canvas's `.draw-hint` styling but scoped to the upload half. */ .draw-half-hint { font-family: 'Patrick Hand', sans-serif; color: var(--ink); opacity: 0.65; font-size: 0.95rem; margin: 8px 2px 0; text-align: center; } /* Match the upload widget's idle look to the canvas surround so the two halves feel like siblings. Gradio's default upload widget has a plain white drop-zone — we soften that to the same warm taupe used for the canvas surround. */ .gradio-container #draw-upload { background-color: transparent !important; background-image: none !important; } .gradio-container #draw-upload .upload-container, .gradio-container #draw-upload .image-container { border: 2px dashed rgba(45, 49, 66, 0.25) !important; border-radius: 14px !important; background-color: #fdfbf3 !important; } .dark .gradio-container #draw-upload .upload-container, .dark .gradio-container #draw-upload .image-container { border: 2px dashed rgba(232, 228, 217, 0.25) !important; background-color: var(--paper) !important; } /* When viewport gets narrow, stack the two halves vertically and convert the vertical divider into a horizontal one so it still reads as a "this OR that" separator. */ @media (max-width: 760px) { .draw-half-canvas { border-right: none; border-bottom: 2px dashed rgba(45, 49, 66, 0.18); padding-right: 0; padding-bottom: 18px; margin-bottom: 6px; } .draw-half-upload { padding-left: 0; } } /* Tab-pill labels that sit ABOVE each card heading, classifying who the section is for. Visually paired (same shape) but color-differentiated (kid = playful crayon-yellow accent, grown-up = grounded ink) so the two roles are recognisable at a glance. */ .card-tab { font-family: 'Patrick Hand', sans-serif; font-size: 0.95rem; font-weight: 400; display: inline-block; padding: 4px 14px; border-radius: 12px 16px 14px 12px; margin: 0 0 10px; letter-spacing: 0.02em; transform: rotate(-1.2deg); border: 2px solid var(--ink); } .card-tab-kid { background: #f4d8a0; color: var(--ink); } .dark .card-tab-kid { color: var(--paper) !important; } /* Grown-up tab: soft crayon-blue wash — paired with yellow (the kid tab) as a classic complementary crayon pair, calm enough to read as the more sober adult-facing section. Solid border (the dashed border had it visually colliding with the Clear-drawing button). */ .card-tab-grownup { background: rgba(74, 144, 217, 0.22) !important; /* crayon-blue @ 22% */ color: var(--ink); } .dark .card-tab-grownup.card-tab-grownup { background: rgba(74, 144, 217, 0.22) !important; color: var(--ink); } /* Subtitle under the form heading — explains what's required vs optional in one breath, so the user isn't surprised by validation errors. Same visual weight as .draw-hint so the two cards feel like siblings. */ .form-role-hint { font-family: 'Patrick Hand', sans-serif; color: var(--ink); opacity: 0.7; font-size: 1.0rem; margin: 0 0 14px 0; } /* The Sketchpad itself: give the inner canvas a creamy "paper" feel and the surround a dashed-ink border so it sits inside our card. The actual surround color is set lower in the taupe block below. */ #draw-canvas .image-container, #draw-canvas canvas { background: #fdfbf3 !important; border-radius: 14px !important; } #draw-canvas { border: 2.5px dashed var(--ink) !important; border-radius: 14px !important; overflow: hidden; } #draw-canvas canvas { border: none !important; } /* Drawing canvas surround. IDLE state: warm muted taupe — repainted via CSS-variable overrides scoped to #draw-canvas (Gradio uses --block-background-fill and friends to color component surrounds; overriding them recolors the idle wrapper without fighting Sketchpad's active editor chrome). ACTIVE editing state: Gradio's Sketchpad swaps in its own dark editor surface using inline styles / different variables, which I'm accepting as a constraint — fighting it produced more side effects than wins. */ .gradio-container #draw-canvas { --block-background-fill: #f3f1ec !important; --background-fill-primary: #f3f1ec !important; --background-fill-secondary: #f3f1ec !important; --neutral-50: #f3f1ec !important; --neutral-100: #f3f1ec !important; background-color: #f3f1ec !important; background-image: none !important; } .dark .gradio-container #draw-canvas { --block-background-fill: var(--paper) !important; --background-fill-primary: var(--paper) !important; --background-fill-secondary: var(--paper) !important; --neutral-50: var(--paper) !important; --neutral-100: var(--paper) !important; background-color: var(--paper) !important; } /* Also paint direct child wrappers (Gradio's Sketchpad nests several divs; any "inactive" surround inherits/uses these surfaces). The active editor uses a deeper element with its own inline style that we no longer fight. */ .gradio-container #draw-canvas>div, .gradio-container #draw-canvas .block, .gradio-container #draw-canvas .wrap, .gradio-container #draw-canvas .container { background-color: #f3f1ec !important; background-image: none !important; } .dark .gradio-container #draw-canvas>div, .dark .gradio-container #draw-canvas .block, .dark .gradio-container #draw-canvas .wrap, .dark .gradio-container #draw-canvas .container { background-color: var(--paper) !important; } /* The inner stays cream-white when idle (it's the "paper") */ .gradio-container #draw-canvas canvas { background-color: #fdfbf3 !important; background-image: none !important; } .dark .gradio-container #draw-canvas canvas { background-color: #23264a !important; } /* The "Clear drawing" button — secondary visual weight; the primary CTA is still "Sing with Lola" further down the page. */ #reset-drawing-btn { margin-top: 10px !important; background: transparent !important; border: 2px dashed var(--ink) !important; color: var(--ink) !important; font-family: 'Patrick Hand', sans-serif !important; font-size: 1.0rem !important; padding: 6px 16px !important; border-radius: 12px !important; box-shadow: none !important; width: auto !important; align-self: flex-start; } #reset-drawing-btn:hover { background: rgba(45, 49, 66, 0.04) !important; } /* ---- "What Lola saw" hint ---------------------------------------------- Sits between the audio player and the lyrics. Reserves a CONSTANT amount of vertical space whether or not it has content, so the layout never reflows when content arrives (which was previously pushing the lyrics down on the first generation and overlapping them mid-transition). The visual chrome (background, border, padding) only renders when the inner .saw-hint div exists; the outer container keeps its margin always. */ #saw-hint { margin: 4px 0 14px !important; /* ALWAYS reserve this space */ min-height: 12px; /* small constant gap when empty */ } .saw-hint { font-family: 'Patrick Hand', sans-serif; color: var(--ink); background: rgba(245, 200, 66, 0.10); /* faint crayon-yellow */ border-left: 4px solid var(--crayon-yellow); border-radius: 8px 12px 10px 8px; padding: 10px 14px; margin: 0; /* margin lives on #saw-hint now */ font-size: 1.0rem; line-height: 1.45; } .dark .saw-label { color: var(--ink) !important; } .saw-hint .saw-label { font-weight: 700; margin-right: 4px; } .saw-hint em { font-style: italic; color: var(--ink); opacity: 0.85; } .saw-hint .saw-plus { margin-left: 6px; opacity: 0.75; font-size: 0.95rem; } .saw-hint-empty { background: rgba(74, 144, 217, 0.08); /* faint crayon-blue */ border-left-color: var(--crayon-blue); font-style: italic; } /* Instrument grid — auto-fill so cells wrap naturally at any container width. minmax(80px, 1fr): each cell is at least 80px wide (enough for the 56px icon + padding) and expands to fill available space. No fixed column count means the grid reflows on its own: 4 across on desktop, 3 on tablet, 2 on narrow mobile — without ever squashing the buttons. */ .instr-grid { display: grid !important; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)) !important; gap: 12px !important; margin: 0 0 14px !important; } /* Gradio wraps every gr.HTML in a div with default margin; squash the gap between the picker title and the instrument grid. */ .form-card-left .gr-block:has(> .instr-grid), .form-card-left .gr-block:has(> #picker-hint) { display: contents !important; margin: 0 !important; padding: 0 !important; } /* Slider — Gradio's value bubble sits in a small box that can clip the rounded border at the bottom. Give the wrapper extra padding so the bubble's full outline shows, and force no overflow clipping on the surrounding block. */ .gr-slider, .gradio-slider, [data-testid="slider"] { overflow: visible !important; padding-bottom: 14px !important; } .gr-slider input[type="number"], .gradio-slider input[type="number"], [data-testid="slider"] input[type="number"] { overflow: visible !important; } /* The bubble container itself */ .gr-slider .wrap, .gradio-slider .wrap { overflow: visible !important; } .instr-cell { background: var(--paper) !important; border: 2.5px solid var(--ink) !important; border-radius: 16px 20px 14px 18px !important; padding: 10px 6px 8px !important; cursor: pointer; box-shadow: 3px 3px 0 rgba(45, 49, 66, 0.12); transition: all 0.2s ease; display: flex; flex-direction: column; align-items: center; gap: 4px; font-family: 'Patrick Hand', sans-serif; font-size: 1rem; color: var(--ink); } .dark .instr-cell { box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.3) !important; } .dark .instr-cell span { color: var(--ink) !important; } .instr-cell:hover { transform: translate(-2px, -2px) rotate(-2deg); box-shadow: 5px 5px 0 rgba(45, 49, 66, 0.18); } .instr-cell.selected { background: var(--crayon-yellow) !important; box-shadow: 3px 3px 0 var(--ink) !important; transform: rotate(-1deg); } .instr-cell img { width: 56px; height: 56px; object-fit: contain; pointer-events: none; } .instr-cell span { pointer-events: none; } /* The little "1" / "2" badge in the corner of selected cells — tells the user which slot they've assigned the instrument to. */ .instr-cell { position: relative; } .slot-badge { position: absolute; top: -8px; right: -8px; background: #2d3142 !important; color: #ffffff !important; font-family: 'Fredoka One', cursive; font-size: 0.85rem; width: 22px; height: 22px; border-radius: 50%; display: flex !important; align-items: center; justify-content: center; box-shadow: 2px 2px 0 rgba(45, 49, 66, 0.25); pointer-events: none; } #picker-hint { font-family: 'Patrick Hand', sans-serif; font-size: 0.95rem; color: var(--crayon-blue); margin: -2px 0 10px; padding: 4px 8px; border-radius: 6px; transition: background 0.25s ease, color 0.25s ease; min-height: 0; } #picker-hint:empty { margin: 0; padding: 0; } #picker-hint.hint-flash { background: var(--crayon-red); color: #fff; transform: rotate(-0.5deg); } #picker-hint.hint-error { font-weight: 700; box-shadow: 2px 2px 0 rgba(45, 49, 66, 0.2); } .section-title { font-family: 'Fredoka One', cursive; font-size: 1.4rem; color: var(--ink); margin: 18px 0 2px; display: flex; align-items: baseline; gap: 10px; } .section-title .which { font-family: 'Patrick Hand', sans-serif; font-size: 1rem; color: var(--crayon-blue); font-style: italic; } button#generate-btn, .primary { background: var(--crayon-red) !important; color: #fffef7 !important; border: 3px solid var(--ink) !important; border-radius: 26px 18px 28px 22px !important; font-family: 'Fredoka One', cursive !important; font-size: 1.7rem !important; font-weight: 400 !important; padding: 18px 36px !important; cursor: pointer; box-shadow: 5px 5px 0 var(--ink); transition: all 0.18s ease; letter-spacing: 0.03em; width: 100%; margin-top: 16px; } button#generate-btn:hover { transform: translate(-2px, -2px) rotate(-1deg); box-shadow: 7px 7px 0 var(--ink); background: var(--crayon-orange) !important; } button#generate-btn:active { transform: translate(2px, 2px); box-shadow: 2px 2px 0 var(--ink); } #output-lyrics textarea { background: linear-gradient(transparent 28px, rgba(74, 144, 217, 0.18) 28px, rgba(74, 144, 217, 0.18) 29px, transparent 29px) !important; background-size: 100% 30px !important; background-color: rgba(255, 255, 255, 0.7) !important; font-family: 'Gloria Hallelujah', cursive !important; font-size: 1.25rem !important; line-height: 30px !important; color: var(--ink) !important; border: 2.5px solid var(--ink) !important; border-radius: 16px 20px 14px 18px !important; padding: 12px 18px !important; } .dark #output-lyrics textarea { background: linear-gradient(transparent 28px, rgba(106, 171, 240, 0.15) 28px, rgba(106, 171, 240, 0.15) 29px, transparent 29px) !important; background-size: 100% 30px !important; background-color: rgba(30, 32, 64, 0.8) !important; } audio { border-radius: 18px !important; border: 2.5px solid var(--ink) !important; background: var(--paper) !important; box-shadow: 3px 3px 0 rgba(45, 49, 66, 0.1); } .dark audio { box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.3) !important; } .attribution { text-align: center; font-family: 'Patrick Hand', sans-serif; font-size: 0.85rem; color: rgba(45, 49, 66, 0.55); margin: 24px auto 16px; padding: 12px; } .attribution a { color: var(--crayon-blue); text-decoration: none; border-bottom: 1px dashed var(--crayon-blue); } /* Footer container — wraps the icon attribution and a professional credit block. A subtle divider sits between them. */ .footer { text-align: center; padding: 8px 12px 20px; } .footer .attribution { padding: 6px 12px 14px; border-bottom: 1px dashed rgba(45, 49, 66, 0.18); margin-bottom: 12px; } /* Powered-by line — sits below the icon attribution. Small and quiet: names the open-source models behind the app and gives judges one-click access to each on the Hub. */ .footer .powered-by { font-family: 'Patrick Hand', sans-serif; font-size: 0.92rem; color: var(--ink); opacity: 0.72; letter-spacing: 0.01em; padding: 0 0 4px; } .footer .powered-by a { color: var(--ink); text-decoration: none; border-bottom: 1px dotted rgba(45, 49, 66, 0.45); padding: 0 1px; transition: color 0.2s ease, border-color 0.2s ease; } .footer .powered-by a:hover { color: var(--crayon-blue); border-bottom-color: var(--crayon-blue); } footer { display: none !important; } .gr-form { gap: 14px !important; } /* Hide the state-holder textboxes — they're in the DOM only so JS can write to them */ .pick-state { display: none !important; } /* Card-level section headings (replaces inline gr.Markdown "###" usage) */ .card-heading { font-family: 'Fredoka One', cursive; font-size: 1.5rem; color: var(--ink); margin: 4px 0 14px; letter-spacing: 0.01em; } /* Advanced settings accordion */ #advanced-accordion { margin-top: 22px !important; border: 2.5px dashed var(--ink) !important; border-radius: 14px 18px 12px 16px !important; background: rgba(255, 255, 255, 0.3) !important; overflow: visible !important; } .dark #advanced-accordion { background: rgba(30, 32, 64, 0.5) !important; } #advanced-accordion>button, #advanced-accordion .label-wrap, #advanced-accordion summary { font-family: 'Fredoka One', cursive !important; font-size: 1.1rem !important; color: var(--ink) !important; padding: 10px 14px !important; } /* Inline error banner — appears under the form when validation fails */ #error-banner { margin-top: 12px; } .error-banner-inner { background: #fde6e3; border: 2.5px solid var(--crayon-red); border-radius: 14px 18px 12px 16px; color: #8a2a22; font-family: 'Patrick Hand', sans-serif; font-size: 1.1rem; padding: 12px 16px; box-shadow: 3px 3px 0 rgba(225, 90, 78, 0.25); transform: rotate(-0.4deg); } .dark .error-banner-inner { background: #3a1a1a; color: #f0a0a0; } /* ---------- Success banner (between heading and audio in lullaby card) --- Sits between "Your lullaby" heading and the audio player. One-liner, no emoji — quiet confirmation that generation completed. Friendly green palette to mirror the error-banner's red, but smaller padding and no rotation since it's an inline confirmation, not a celebration. */ #success-banner { margin: 4px 0 10px; } .success-banner-inner { background: #e5f3dc; border: 2.5px solid #6fb05e; border-radius: 12px 16px 10px 14px; color: #2f5a26; font-family: 'Patrick Hand', sans-serif; font-size: 1.05rem; padding: 8px 14px; text-align: center; box-shadow: 2px 2px 0 rgba(111, 176, 94, 0.2); } .dark .success-banner-inner { background: #1a3020; color: #90cc80; } /* Idle (pre-generation) variant — soft yellow "waiting" tone, no green to avoid implying success before there's a song. Same shape as the success state so the slot doesn't jump around when content changes. */ .success-banner-idle { background: rgba(245, 200, 66, 0.14); /* whisper of crayon-yellow */ border: 2px dashed rgba(45, 49, 66, 0.40); border-radius: 12px 16px 10px 14px; color: var(--ink); opacity: 0.78; font-family: 'Patrick Hand', sans-serif; font-size: 1.0rem; padding: 8px 14px; text-align: center; } /* ---------- "Both inputs" notice (in the draw card) --------------------- Soft, low-key, informational tone. Not red/alarming because the user didn't do anything wrong — we're just being transparent about which input wins when both are present. */ #both-inputs-notice { margin: 14px 18px 0; } .both-inputs-inner { background: rgba(245, 200, 66, 0.18); /* whisper of crayon-yellow */ border: 2px dashed rgba(45, 49, 66, 0.45); border-radius: 12px 16px 10px 14px; color: var(--ink); font-family: 'Patrick Hand', sans-serif; font-size: 1.0rem; padding: 10px 14px; line-height: 1.4; } .both-inputs-inner .both-inputs-icon { margin-right: 4px; font-size: 1.1rem; } #lola-status:empty { display: none; }