/* ============================================================ MOODLINE — design tokens ============================================================ */ :root{ --bg: #0e0f14; --surface: #16171f; --surface-2: #1c1e29; --border: rgba(255,255,255,0.08); --border-strong: rgba(255,255,255,0.16); --text: #f2f0ea; --text-dim: #9497a6; --text-faint: #5c5f6d; /* neutral accent while idle / no result yet */ --accent: #6c7a89; --accent-soft: rgba(108,122,137,0.18); --font-display: "Fraunces", serif; --font-body: "Space Grotesk", sans-serif; --font-mono: "JetBrains Mono", monospace; --ease-out: cubic-bezier(.16,1,.3,1); --ease-soft: cubic-bezier(.4,0,.2,1); } /* per-emotion accent palette, applied to */ body[data-emotion="sadness"] { --accent: #5b7fde; --accent-soft: rgba(91,127,222,0.16); } body[data-emotion="joy"] { --accent: #f2b705; --accent-soft: rgba(242,183,5,0.16); } body[data-emotion="love"] { --accent: #e85d75; --accent-soft: rgba(232,93,117,0.16); } body[data-emotion="anger"] { --accent: #e4572e; --accent-soft: rgba(228,87,46,0.16); } body[data-emotion="fear"] { --accent: #8b5fbf; --accent-soft: rgba(139,95,191,0.16); } body[data-emotion="surprise"] { --accent: #17bebb; --accent-soft: rgba(23,190,187,0.16); } /* fixed colors for breakdown bars, independent of current accent */ .bar-sadness .bar-fill{ background: #5b7fde; } .bar-joy .bar-fill{ background: #f2b705; } .bar-love .bar-fill{ background: #e85d75; } .bar-anger .bar-fill{ background: #e4572e; } .bar-fear .bar-fill{ background: #8b5fbf; } .bar-surprise .bar-fill{ background: #17bebb; } /* ============================================================ RESET / BASE ============================================================ */ *{ box-sizing: border-box; } html{ color-scheme: dark; } body{ margin: 0; min-height: 100vh; background: radial-gradient(60% 50% at 50% -10%, var(--accent-soft), transparent 70%), var(--bg); background-attachment: fixed; color: var(--text); font-family: var(--font-body); transition: background 900ms var(--ease-soft); overflow-x: hidden; } textarea, button{ font-family: inherit; } /* subtle film-grain overlay for warmth, purely decorative */ .grain{ position: fixed; inset: 0; pointer-events: none; z-index: 1; opacity: 0.035; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); } @media (prefers-reduced-motion: reduce){ *{ animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } } /* Focus-visible improvements */ :focus-visible{ outline: 2px solid var(--accent); outline-offset: 2px; } /* ============================================================ LAYOUT ============================================================ */ .app{ position: relative; z-index: 2; max-width: 960px; margin: 0 auto; padding: 48px 24px 40px; display: flex; flex-direction: column; min-height: 100vh; } .topbar{ display: flex; align-items: baseline; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 56px; animation: rise 700ms var(--ease-out) both; } .brand{ display: flex; align-items: center; gap: 10px; } .brand-mark{ width: 9px; height: 9px; border-radius: 50%; background: var(--text-faint); box-shadow: 0 0 0 3px transparent; transition: background 400ms, box-shadow 400ms; } .brand-mark.live{ background: #52d17c; box-shadow: 0 0 0 3px rgba(82,209,124,0.18); } .brand-mark.warming{ background: #f2b705; box-shadow: 0 0 0 3px rgba(242,183,5,0.18); animation: pulse-dot 1.4s ease-in-out infinite; } .brand-mark.down{ background: #e4572e; box-shadow: 0 0 0 3px rgba(228,87,46,0.18); } @keyframes pulse-dot{ 50%{ opacity: 0.35; } } .brand-name{ font-family: var(--font-display); font-weight: 600; font-size: 20px; letter-spacing: -0.01em; } .brand-tag{ margin: 0; color: var(--text-dim); font-size: 13px; letter-spacing: 0.01em; } .eyebrow{ display: block; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em; color: var(--text-faint); margin-bottom: 14px; } main{ flex: 1; } /* ============================================================ CONSOLE (input area + orb) ============================================================ */ .console{ display: grid; grid-template-columns: 220px 1fr; gap: 40px; align-items: center; padding: 40px; border: 1px solid var(--border); border-radius: 28px; background: linear-gradient(180deg, var(--surface), var(--surface-2)); animation: rise 800ms 80ms var(--ease-out) both; } @media (max-width: 720px){ .console{ grid-template-columns: 1fr; padding: 28px; gap: 28px; } } /* --- the orb: signature element -------------------------------- */ .orb-stage{ position: relative; height: 220px; display: flex; align-items: center; justify-content: center; } .orb-glow{ position: absolute; inset: 10%; border-radius: 50%; background: radial-gradient(circle, var(--accent) 0%, transparent 72%); filter: blur(26px); opacity: 0.55; transition: background 700ms var(--ease-soft); animation: breathe 6s ease-in-out infinite; } .orb{ position: relative; width: 148px; height: 148px; display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 55%, #0e0f14)); border-radius: 42% 58% 65% 35% / 48% 42% 58% 52%; box-shadow: inset 0 0 30px rgba(255,255,255,0.14), 0 20px 40px -18px var(--accent); animation: morph 9s ease-in-out infinite, breathe 6s ease-in-out infinite; transition: background 700ms var(--ease-soft), box-shadow 700ms var(--ease-soft); } .orb.thinking{ animation: morph 2.1s ease-in-out infinite, spin 2.1s linear infinite, pulse-glow 2s ease-in-out infinite; } .orb.settled{ animation: morph 9s ease-in-out infinite, settle-pop 640ms var(--ease-out); } /* Subtle glow pulse during thinking */ @keyframes pulse-glow{ 0%, 100%{ box-shadow: inset 0 0 30px rgba(255,255,255,0.14), 0 20px 40px -18px var(--accent); } 50%{ box-shadow: inset 0 0 40px rgba(255,255,255,0.22), 0 25px 50px -12px var(--accent); } } .orb.settled{ animation: morph 9s ease-in-out infinite, settle-pop 640ms var(--ease-out); } .orb-emoji{ font-size: 38px; filter: drop-shadow(0 4px 10px rgba(0,0,0,0.35)); transition: opacity 200ms; font-family: var(--font-body); color: rgba(255,255,255,0.92); } @keyframes breathe{ 0%, 100%{ transform: scale(1); } 50%{ transform: scale(1.05); } } @keyframes morph{ 0%,100%{ border-radius: 42% 58% 65% 35% / 48% 42% 58% 52%; } 33%{ border-radius: 60% 40% 44% 56% / 40% 62% 38% 60%; } 66%{ border-radius: 48% 52% 38% 62% / 62% 40% 60% 38%; } } @keyframes spin{ to{ transform: rotate(360deg); } } @keyframes settle-pop{ 0%{ transform: scale(0.86); } 55%{ transform: scale(1.08); } 100%{ transform: scale(1); } } /* --- input panel -------------------------------------------------- */ .input-panel{ min-width: 0; } textarea{ width: 100%; min-height: 118px; resize: vertical; background: rgba(0,0,0,0.18); border: 1px solid var(--border); border-radius: 14px; padding: 16px 18px; color: var(--text); font-size: 16px; line-height: 1.55; outline: none; transition: border-color 250ms, box-shadow 250ms; } textarea::placeholder{ color: var(--text-faint); } textarea:focus{ border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); } .input-footer{ display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-top: 14px; } .char-count{ font-family: var(--font-mono); font-size: 12px; color: var(--text-faint); } .btn-primary{ display: inline-flex; align-items: center; gap: 8px; padding: 12px 20px; border-radius: 999px; border: none; background: var(--text); color: #0e0f14; font-weight: 600; font-size: 14.5px; cursor: pointer; transition: transform 220ms var(--ease-out), box-shadow 220ms var(--ease-out), background 300ms var(--ease-soft), opacity 200ms var(--ease-soft); user-select: none; } .btn-primary:hover:not(:disabled){ transform: translateY(-2px); box-shadow: 0 12px 24px -10px var(--accent); background: var(--accent); color: #fff; } .btn-primary:active:not(:disabled){ transform: translateY(0); } .btn-primary:focus-visible{ outline: 2px solid var(--accent); outline-offset: 2px; } .btn-primary:disabled{ opacity: 0.35; cursor: not-allowed; } .btn-arrow{ transition: transform 220ms var(--ease-out); } .btn-primary:hover:not(:disabled) .btn-arrow{ transform: translateX(3px); } .btn-primary.loading .btn-label::after{ content: ""; } .btn-primary.loading{ pointer-events: none; } /* Reduced motion: disable subtle animations */ @media (prefers-reduced-motion: reduce){ .btn-primary:hover:not(:disabled){ transform: none; box-shadow: none; background: var(--accent); } .orb{ animation: none !important; } .bar-fill{ transition-duration: 0.01ms !important; } } .error-msg{ margin: 12px 2px 0; font-size: 13px; color: #ff8a72; font-family: var(--font-mono); } .error-msg.visible{ animation: shake 0.4s ease-in-out; } @keyframes shake{ 0%, 100%{ transform: translateX(0); } 20%{ transform: translateX(-8px); } 40%{ transform: translateX(8px); } 60%{ transform: translateX(-6px); } 80%{ transform: translateX(6px); } } /* ============================================================ RESULT ============================================================ */ .result{ margin-top: 32px; display: grid; grid-template-columns: 1fr 1fr; gap: 24px; } @media (max-width: 720px){ .result{ grid-template-columns: 1fr; } } .result.entering{ animation: rise 620ms var(--ease-out) both; } .reveal, .breakdown{ border: 1px solid var(--border); border-radius: 24px; padding: 32px; background: linear-gradient(180deg, var(--surface), var(--surface-2)); } .reveal-main{ display: flex; align-items: center; gap: 16px; margin-bottom: 10px; } .reveal-emoji{ font-size: 40px; line-height: 1; } #emotionWord{ margin: 0; font-family: var(--font-display); font-style: italic; font-weight: 600; font-size: clamp(36px, 6vw, 52px); letter-spacing: -0.01em; color: var(--accent); transition: color 500ms var(--ease-soft); } .confidence-mono{ display: inline-block; font-family: var(--font-mono); font-size: 13px; color: var(--text-dim); margin-bottom: 20px; } .echoed-text{ margin: 0; padding-top: 18px; border-top: 1px solid var(--border); font-size: 14.5px; line-height: 1.6; color: var(--text-dim); font-style: italic; } .bars{ display: flex; flex-direction: column; gap: 14px; align-items: flex-start; } .bar-row{ display: grid; grid-template-columns: 84px 1fr 52px; align-items: center; gap: 12px; opacity: 0; transform: translateY(8px); animation: bar-enter 0.5s var(--ease-out) forwards; } @keyframes bar-enter{ to{ opacity: 1; transform: translateY(0); } } /* Stagger bars - earlier bars animate sooner */ .bar-row:nth-child(1){ animation-delay: 0ms; } .bar-row:nth-child(2){ animation-delay: 70ms; } .bar-row:nth-child(3){ animation-delay: 140ms; } .bar-row:nth-child(4){ animation-delay: 210ms; } .bar-row:nth-child(5){ animation-delay: 280ms; } .bar-row:nth-child(6){ animation-delay: 350ms; } .bar-label{ font-size: 13px; color: var(--text-dim); display: flex; align-items: center; gap: 6px; text-transform: capitalize; transition: color 200ms var(--ease-soft); } .bar-label:hover{ color: var(--accent); } .bar-track{ height: 8px; border-radius: 999px; background: rgba(255,255,255,0.06); overflow: hidden; } .bar-fill{ height: 100%; width: 0%; border-radius: 999px; background: var(--accent-soft); transition: width 900ms var(--ease-out), background 400ms var(--ease-soft); } .bar-fill.bar-joy{ background: #f2b705; } .bar-fill.bar-love{ background: #e85d75; } .bar-fill.bar-anger{ background: #e4572e; } .bar-fill.bar-fear{ background: #8b5fbf; } .bar-fill.bar-surprise{ background: #17bebb; } .bar-fill.bar-sadness{ background: #5b7fde; } .bar-pct{ font-family: var(--font-mono); font-size: 12px; color: var(--text-faint); text-align: right; transition: color 200ms var(--ease-soft); } .bar-pct:hover{ color: var(--text); } /* ============================================================ FOOTER ============================================================ */ .footbar{ margin-top: 40px; display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; font-size: 12px; color: var(--text-faint); font-family: var(--font-mono); } @keyframes rise{ from{ opacity: 0; transform: translateY(14px); } to{ opacity: 1; transform: translateY(0); } }