@import "tailwindcss"; :root { --background: #fafaf9; --foreground: #1c1917; --primary: #0f766e; /* deep teal — financial-services serious */ --primary-foreground: #ffffff; --muted: #f5f5f4; --muted-foreground: #57534e; --border: #e7e5e4; --card: #ffffff; --accent: #fef3c7; /* warm amber for highlights */ --error: #dc2626; } @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); --color-primary: var(--primary); --color-primary-foreground: var(--primary-foreground); --color-muted: var(--muted); --color-muted-foreground: var(--muted-foreground); --color-border: var(--border); --color-card: var(--card); --color-accent: var(--accent); --color-error: var(--error); --font-sans: var(--font-body), ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --font-serif: var(--font-display), ui-serif, Georgia, "Times New Roman", serif; --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, monospace; } @media (prefers-color-scheme: dark) { :root { --background: #0c0a09; --foreground: #fafaf9; --muted: #1c1917; --muted-foreground: #a8a29e; --border: #292524; --card: #1c1917; --primary: #2dd4bf; --primary-foreground: #0a0a0a; --accent: #422006; } } body { background: var(--background); color: var(--foreground); font-family: var(--font-sans); -webkit-font-smoothing: antialiased; } /* utility — scrollbar styling */ .scrollbar-thin::-webkit-scrollbar { width: 8px; height: 8px; } .scrollbar-thin::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; } .scrollbar-thin::-webkit-scrollbar-thumb:hover { background: var(--muted-foreground); } .scrollbar-thin::-webkit-scrollbar-track { background: transparent; } /* fade-in for chat messages */ @keyframes fade-up { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } } .animate-fade-up { animation: fade-up 0.3s ease-out; } /* pulse for recording indicator */ @keyframes record-pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(220, 38, 38, 0.7); } 50% { box-shadow: 0 0 0 12px rgba(220, 38, 38, 0); } } .animate-record-pulse { animation: record-pulse 1.4s infinite; } /* Header chip-tile: locks every chip on a uniform min height + clean * focus ring + keyboard accessibility. Two-line layout (kicker + sub) is * guaranteed to align across chips even when one chip has more text. */ .chip-tile { min-height: 52px; display: inline-flex; align-items: stretch; } .chip-tile:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; } /* ──────────────────────────────────────────────────────────────────── * PREMIUM LANDING (EmptyState) — editorial-fintech redesign * Design direction: warm, trustworthy, magazine-grade. Fraunces display * serif + Plus Jakarta body, layered soft depth, a faint grain + grid * hero texture, a numbered "journey" spine, and one orchestrated * page-load reveal. No generic AI card-grid look. * ──────────────────────────────────────────────────────────────────── */ /* Display serif — applied to the hero headline + section titles. The * optical-size + soft axes give large type a warm, set-by-hand feel. */ .font-display { font-family: var(--font-serif); font-optical-sizing: auto; font-variation-settings: "SOFT" 40, "WONK" 0; letter-spacing: -0.012em; } /* The landing root sets the editorial body face + a calm vertical wash * (deep at the very top behind the hero, fading to paper) and a barely * perceptible film grain so flat fills never look plastic. */ .landing-root { font-family: var(--font-sans); position: relative; background: radial-gradient(120% 60% at 50% -10%, color-mix(in srgb, var(--primary) 11%, transparent) 0%, transparent 60%), linear-gradient(180deg, color-mix(in srgb, var(--primary) 4%, var(--background)) 0%, var(--background) 40%); } .landing-root::before { content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0.5; mix-blend-mode: multiply; /* tiny SVG fractal-noise grain, base64-free via data URI */ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.32'/%3E%3C/svg%3E"); } /* HERO — generous, asymmetric-feeling slab with a layered teal glow, * an inner hairline, and a faint engineering grid that signals "built, * not marketing fluff". */ .hero-card { position: relative; isolation: isolate; border-radius: 28px; border: 1px solid color-mix(in srgb, var(--primary) 16%, var(--border)); background: radial-gradient(90% 120% at 18% 0%, color-mix(in srgb, var(--primary) 12%, var(--card)) 0%, var(--card) 55%), var(--card); box-shadow: 0 1px 0 color-mix(in srgb, var(--primary) 14%, transparent) inset, 0 1px 2px color-mix(in srgb, var(--foreground) 5%, transparent), 0 24px 60px -30px color-mix(in srgb, var(--primary) 42%, transparent); } .hero-card::after { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none; opacity: 0.5; -webkit-mask-image: radial-gradient(70% 90% at 22% 8%, #000 0%, transparent 70%); mask-image: radial-gradient(70% 90% at 22% 8%, #000 0%, transparent 70%); background-image: linear-gradient(color-mix(in srgb, var(--primary) 12%, transparent) 1px, transparent 1px), linear-gradient(90deg, color-mix(in srgb, var(--primary) 12%, transparent) 1px, transparent 1px); background-size: 30px 30px; } /* Eyebrow / kicker pill — small caps, brand-tinted, with a live dot. */ .kicker { display: inline-flex; align-items: center; gap: 8px; padding: 6px 13px 6px 11px; border-radius: 999px; font-size: 11.5px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--primary); background: color-mix(in srgb, var(--primary) 9%, var(--card)); border: 1px solid color-mix(in srgb, var(--primary) 22%, var(--border)); box-shadow: 0 1px 1px color-mix(in srgb, var(--foreground) 4%, transparent); } .kicker .dot { width: 6px; height: 6px; border-radius: 999px; background: var(--primary); box-shadow: 0 0 0 0 color-mix(in srgb, var(--primary) 70%, transparent); animation: kicker-pulse 2.6s ease-out infinite; } @keyframes kicker-pulse { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--primary) 55%, transparent); } 70% { box-shadow: 0 0 0 7px color-mix(in srgb, var(--primary) 0%, transparent); } 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--primary) 0%, transparent); } } /* SECTION SHELL — quieter than the hero: clean paper, hairline border, * a soft long shadow so sections feel lifted off the page wash. */ .section-card { border-radius: 22px; border: 1px solid var(--border); background: var(--card); box-shadow: 0 1px 2px color-mix(in srgb, var(--foreground) 4%, transparent), 0 18px 48px -34px color-mix(in srgb, var(--foreground) 30%, transparent); } /* Section header: a hairline rule grows from the icon so each section * reads as a titled chapter rather than a stacked box. */ .section-rule { flex: 1; height: 1px; background: linear-gradient(90deg, color-mix(in srgb, var(--primary) 30%, var(--border)) 0%, var(--border) 30%, transparent 100%); } .section-num { font-family: var(--font-serif); font-size: 13px; font-weight: 600; color: color-mix(in srgb, var(--primary) 70%, var(--muted-foreground)); letter-spacing: 0.02em; } /* STEP — the three "how it works" cards sit on a shared horizontal spine * (a connecting line through the numbered medallions) so they read as one * journey, not three disconnected tiles. */ .step-grid { position: relative; } @media (min-width: 640px) { .step-grid::before { content: ""; position: absolute; top: 50px; /* aligns to the centre of the 36px medallion + pt */ left: 16%; right: 16%; height: 2px; background: repeating-linear-gradient(90deg, color-mix(in srgb, var(--primary) 34%, var(--border)) 0 7px, transparent 7px 14px); z-index: 0; } } .step-card { position: relative; z-index: 1; border-radius: 18px; border: 1px solid var(--border); background: linear-gradient(180deg, color-mix(in srgb, var(--primary) 5%, var(--card)) 0%, var(--card) 42%); transition: transform .22s cubic-bezier(.2,.7,.3,1), box-shadow .22s ease, border-color .22s ease; } .step-card:hover { transform: translateY(-4px); border-color: color-mix(in srgb, var(--primary) 34%, var(--border)); box-shadow: 0 1px 2px color-mix(in srgb, var(--foreground) 4%, transparent), 0 22px 44px -26px color-mix(in srgb, var(--primary) 46%, transparent); } .step-medallion { width: 44px; height: 44px; border-radius: 14px; display: flex; align-items: center; justify-content: center; font-family: var(--font-serif); font-size: 18px; font-weight: 600; color: var(--primary-foreground); background: linear-gradient(150deg, color-mix(in srgb, var(--primary) 92%, white) 0%, var(--primary) 55%, color-mix(in srgb, var(--primary) 78%, black) 100%); box-shadow: 0 2px 6px color-mix(in srgb, var(--primary) 40%, transparent), 0 0 0 5px color-mix(in srgb, var(--primary) 10%, transparent); } /* Tight one-line fact bullets used inside step / callout bodies. */ .fact-list { display: flex; flex-direction: column; gap: 9px; } .fact-list li { display: flex; align-items: flex-start; gap: 9px; font-size: 13.5px; line-height: 1.45; color: var(--muted-foreground); } .fact-list li .tick { flex: none; margin-top: 1px; color: var(--primary); } .fact-list li strong { color: var(--foreground); font-weight: 600; } /* INPUT-MODE rows — refined list with a left accent rail on hover. */ .mode-row { position: relative; border-radius: 16px; border: 1px solid var(--border); background: var(--card); overflow: hidden; transition: transform .2s cubic-bezier(.2,.7,.3,1), box-shadow .2s ease, border-color .2s ease; } .mode-row::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--primary); transform: scaleY(0); transform-origin: top; transition: transform .22s ease; } .mode-row:hover { transform: translateY(-2px); border-color: color-mix(in srgb, var(--primary) 30%, var(--border)); box-shadow: 0 16px 34px -24px color-mix(in srgb, var(--primary) 40%, transparent); } .mode-row:hover::before { transform: scaleY(1); } .mode-glyph { background: linear-gradient(150deg, color-mix(in srgb, var(--primary) 14%, var(--card)) 0%, color-mix(in srgb, var(--primary) 6%, var(--card)) 100%); border: 1px solid color-mix(in srgb, var(--primary) 18%, var(--border)); color: var(--primary); } /* CALLOUT cards — keep the amber trust card distinct, lift both. */ .callout-card { border-radius: 18px; transition: transform .2s ease, box-shadow .2s ease; } .callout-card:hover { transform: translateY(-2px); box-shadow: 0 18px 40px -28px color-mix(in srgb, var(--foreground) 40%, transparent); } /* Orchestrated page-load reveal — staggered, calm, runs once. */ @keyframes reveal-up { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } } .reveal { opacity: 0; animation: reveal-up .6s cubic-bezier(.2,.7,.3,1) forwards; } .reveal-1 { animation-delay: .02s; } .reveal-2 { animation-delay: .12s; } .reveal-3 { animation-delay: .22s; } .reveal-4 { animation-delay: .32s; } /* ──────────────────────────────────────────────────────────────────── * PREMIUM APP SURFACES — profile builder · chat · cited cards · * marketplace. Same editorial-fintech system as the landing: Fraunces * display serif for section titles, Plus Jakarta body, hairline * borders, soft long shadows, brand-teal accents, one calm reveal. * ──────────────────────────────────────────────────────────────────── */ /* Slide-over panel shell (profile / marketplace). Quiet paper, a faint * top teal wash so it reads as a lifted "sheet", not a flat overlay. */ .app-panel { position: relative; font-family: var(--font-sans); background: radial-gradient(110% 50% at 50% -8%, color-mix(in srgb, var(--primary) 7%, transparent) 0%, transparent 55%), var(--background); } /* Chaptered panel header — kicker + serif title, mirrors .section-num. */ .panel-kicker { display: inline-flex; align-items: center; gap: 7px; font-size: 10.5px; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: color-mix(in srgb, var(--primary) 78%, var(--muted-foreground)); } .panel-kicker .dot { width: 5px; height: 5px; border-radius: 999px; background: var(--primary); } .panel-title { font-family: var(--font-serif); font-optical-sizing: auto; font-variation-settings: "SOFT" 40, "WONK" 0; letter-spacing: -0.012em; font-weight: 600; } /* A profile "fieldset" — one numbered chapter of the form. Hairline * card, soft long shadow, a serif step index in a tinted medallion so * the form reads as a guided journey, not a wall of inputs. */ .field-group { position: relative; border-radius: 18px; border: 1px solid var(--border); background: linear-gradient(180deg, color-mix(in srgb, var(--primary) 4%, var(--card)) 0%, var(--card) 38%); box-shadow: 0 1px 2px color-mix(in srgb, var(--foreground) 4%, transparent), 0 16px 40px -32px color-mix(in srgb, var(--foreground) 28%, transparent); transition: border-color .22s ease, box-shadow .22s ease; } .field-group:focus-within { border-color: color-mix(in srgb, var(--primary) 32%, var(--border)); box-shadow: 0 1px 2px color-mix(in srgb, var(--foreground) 4%, transparent), 0 18px 44px -28px color-mix(in srgb, var(--primary) 36%, transparent); } .field-medallion { width: 30px; height: 30px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-family: var(--font-serif); font-size: 14px; font-weight: 600; color: var(--primary-foreground); background: linear-gradient(150deg, color-mix(in srgb, var(--primary) 92%, white) 0%, var(--primary) 55%, color-mix(in srgb, var(--primary) 80%, black) 100%); box-shadow: 0 2px 5px color-mix(in srgb, var(--primary) 36%, transparent), 0 0 0 4px color-mix(in srgb, var(--primary) 9%, transparent); } /* Selectable option pill — replaces the ad-hoc chip classes. Crisp * hairline, brand fill on select, a soft press feel. */ .opt-pill { display: inline-flex; align-items: center; gap: 6px; padding: 7px 13px; border-radius: 999px; border: 1px solid var(--border); background: var(--card); font-size: 12px; font-weight: 500; color: var(--foreground); cursor: pointer; transition: transform .15s cubic-bezier(.2,.7,.3,1), border-color .15s ease, background .15s ease, color .15s ease, box-shadow .15s ease; } .opt-pill:hover { border-color: color-mix(in srgb, var(--primary) 40%, var(--border)); } .opt-pill:active { transform: scale(.97); } .opt-pill[data-on="true"] { border-color: var(--primary); background: var(--primary); color: var(--primary-foreground); box-shadow: 0 6px 16px -8px color-mix(in srgb, var(--primary) 60%, transparent); } .opt-pill:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; } /* Text / number field — single shared input look. */ .app-input { width: 100%; font-size: 14px; padding: 9px 12px; border-radius: 11px; border: 1px solid var(--border); background: var(--card); color: var(--foreground); transition: border-color .18s ease, box-shadow .18s ease; } .app-input::placeholder { color: var(--muted-foreground); } .app-input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 14%, transparent); } /* Brand range slider — themed track + thumb so it stops looking like a * raw OS control next to the editorial type. */ .app-range { -webkit-appearance: none; appearance: none; width: 100%; background: transparent; /* track is drawn by the pseudo-elements below — relying on the element bg broke once .app-range-lg added padding + background-clip:content-box (#58). */ outline: none; cursor: pointer; } .app-range::-webkit-slider-runnable-track { height: 6px; border-radius: 999px; background: color-mix(in srgb, var(--primary) 22%, var(--border)); } .app-range::-moz-range-track { height: 6px; border-radius: 999px; background: color-mix(in srgb, var(--primary) 22%, var(--border)); } .app-range::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 18px; height: 18px; margin-top: -6px; /* center the 18px thumb on the 6px track */ border-radius: 999px; background: var(--primary); border: 3px solid var(--card); box-shadow: 0 1px 4px color-mix(in srgb, var(--primary) 50%, transparent); cursor: pointer; } .app-range::-moz-range-thumb { width: 16px; height: 16px; border-radius: 999px; background: var(--primary); border: 3px solid var(--card); cursor: pointer; } /* Conditional sub-block (parents detail) — a tinted inset rail. */ .subfield { border-radius: 14px; border: 1px solid color-mix(in srgb, var(--primary) 20%, var(--border)); background: color-mix(in srgb, var(--primary) 5%, var(--card)); } /* Sticky save bar — frosted, lifted off the form. */ .save-bar { background: color-mix(in srgb, var(--card) 86%, transparent); -webkit-backdrop-filter: saturate(180%) blur(10px); backdrop-filter: saturate(180%) blur(10px); border-top: 1px solid var(--border); } .btn-primary { font-weight: 600; border-radius: 12px; color: var(--primary-foreground); background: linear-gradient(150deg, color-mix(in srgb, var(--primary) 94%, white) 0%, var(--primary) 60%); box-shadow: 0 8px 20px -10px color-mix(in srgb, var(--primary) 60%, transparent); transition: transform .15s ease, box-shadow .15s ease, opacity .15s ease; } .btn-primary:hover:not(:disabled) { transform: translateY(-1px); } .btn-primary:disabled { opacity: .5; cursor: not-allowed; } /* CHAT bubbles — the assistant reads as a calm "letter" on paper, the * user as a brand slab. Both lifted, both with a soft tail-less radius. */ .bubble-assistant { border-radius: 18px 18px 18px 6px; border: 1px solid var(--border); background: linear-gradient(180deg, color-mix(in srgb, var(--primary) 3.5%, var(--card)) 0%, var(--card) 36%); box-shadow: 0 1px 2px color-mix(in srgb, var(--foreground) 4%, transparent), 0 14px 36px -30px color-mix(in srgb, var(--foreground) 26%, transparent); } .bubble-user { border-radius: 18px 18px 6px 18px; color: var(--primary-foreground); background: linear-gradient(150deg, color-mix(in srgb, var(--primary) 92%, white) 0%, var(--primary) 62%); box-shadow: 0 10px 26px -14px color-mix(in srgb, var(--primary) 55%, transparent); } /* Cited-policy card — hairline, lifts to a teal-tinted long shadow. */ .cited-card { border-radius: 14px; border: 1px solid var(--border); background: var(--card); transition: transform .2s cubic-bezier(.2,.7,.3,1), border-color .2s ease, box-shadow .2s ease; } .cited-card:hover { transform: translateY(-2px); border-color: color-mix(in srgb, var(--primary) 32%, var(--border)); box-shadow: 0 16px 34px -24px color-mix(in srgb, var(--primary) 42%, transparent); } /* Marketplace policy card — same lift language as the step cards. */ .policy-card { border-radius: 16px; border: 1px solid var(--border); background: linear-gradient(180deg, color-mix(in srgb, var(--primary) 3.5%, var(--card)) 0%, var(--card) 40%); transition: transform .2s cubic-bezier(.2,.7,.3,1), border-color .2s ease, box-shadow .2s ease; } .policy-card:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--primary) 34%, var(--border)); box-shadow: 0 1px 2px color-mix(in srgb, var(--foreground) 4%, transparent), 0 22px 44px -26px color-mix(in srgb, var(--primary) 44%, transparent); } .policy-card[data-selected="true"] { border-color: var(--primary); box-shadow: 0 18px 40px -22px color-mix(in srgb, var(--primary) 50%, transparent); } /* Filter shell + sticky compare bar share the frosted treatment. */ .filter-shell { border-radius: 18px; border: 1px solid var(--border); background: var(--card); box-shadow: 0 1px 2px color-mix(in srgb, var(--foreground) 4%, transparent); } /* Honour reduced-motion preference: drop the hover-lift transition on the * landing step / mode / callout cards for vestibular-sensitive users. */ @media (prefers-reduced-motion: reduce) { .step-card, .mode-row, .callout-card, .chip-tile, .field-group, .opt-pill, .cited-card, .policy-card, .btn-primary { transition: none !important; } .step-card:hover, .mode-row:hover, .callout-card:hover, .cited-card:hover, .policy-card:hover, .btn-primary:hover { transform: none !important; } .reveal { opacity: 1 !important; animation: none !important; } .kicker .dot { animation: none !important; } } /* ──────────────────────────────────────────────────────────────────── * #44 — assistant markdown prose. Tight, readable defaults that inherit * the chat bubble's type scale. Lists, bold policy names, paragraphs and * line breaks all read cleanly instead of as a raw `**`/`1.` wall. * ──────────────────────────────────────────────────────────────────── */ .md-body { overflow-wrap: anywhere; word-break: break-word; } .md-body > *:first-child { margin-top: 0; } .md-body > *:last-child { margin-bottom: 0; } .md-body a { word-break: break-word; } .md-body ol, .md-body ul { padding-inline-start: 1.35rem; } .md-body li::marker { font-variant-numeric: tabular-nums; } .md-body code { white-space: pre-wrap; word-break: break-word; } /* #47 — larger continuous slider variant for the merged Profile & * premium money fields. Bigger track + thumb so the touch target clears * the 44px guideline on phones (the wrapper row + thumb hit-area). */ /* Padding gives the ≥44px touch target; the track is a pseudo-element so * the padding does not hide it. */ .app-range-lg { padding: 13px 0; } .app-range-lg::-webkit-slider-runnable-track { height: 8px; } .app-range-lg::-moz-range-track { height: 8px; } .app-range-lg::-webkit-slider-thumb { width: 24px; height: 24px; margin-top: -8px; border-width: 4px; } .app-range-lg::-moz-range-thumb { width: 22px; height: 22px; border-width: 4px; } .app-range:focus-visible { outline: 2px solid var(--primary); outline-offset: 4px; } /* ──────────────────────────────────────────────────────────────────── * #49 — full mobile optimization. Single-column stacks, ≥44px tap * targets, no horizontal overflow, mobile-safe modals / sliders / * sticky bars, readable type. Scoped so desktop is untouched. * ──────────────────────────────────────────────────────────────────── */ /* Hard stop on horizontal overflow anywhere in the app. */ html, body { max-width: 100%; overflow-x: hidden; } @media (max-width: 640px) { /* Generous tap targets for every interactive control on phones. */ .opt-pill { min-height: 40px; padding: 9px 15px; font-size: 12.5px; } .chip-tile { min-height: 48px; } .btn-primary { min-height: 44px; } /* The header chip row scrolls horizontally instead of wrapping into a * tall ragged stack — keeps the brand mark + chips on one tidy line a * thumb can swipe. Hide the scrollbar; momentum scroll on iOS. */ .chip-row-scroll { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; margin-inline: -1rem; padding-inline: 1rem; scroll-snap-type: x proximity; } .chip-row-scroll::-webkit-scrollbar { display: none; } .chip-row-scroll > * { scroll-snap-align: start; } /* Slide-over app panels become a full-height sheet on phones (the chat * lives above in the column flow; the panel gets the rest of the * viewport and scrolls internally). Drops the desktop 80vh cap. */ .app-panel-mobile-full { max-height: none !important; min-height: 70vh; } /* Centered modals dock to the bottom as a full-width sheet — easier to * reach one-handed, respects the home-indicator safe area. */ .modal-shell-mobile { align-items: flex-end !important; padding: 0 !important; } .modal-card-mobile { max-width: 100% !important; width: 100% !important; max-height: 92dvh !important; border-bottom-left-radius: 0 !important; border-bottom-right-radius: 0 !important; padding-bottom: env(safe-area-inset-bottom) !important; } /* Any 2-up grid inside a panel collapses to one column on phones. */ .stack-on-mobile { grid-template-columns: 1fr !important; } /* Comparison table stays usable: allow horizontal scroll within its * own container without blowing out the page width. */ .table-scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; } /* Slightly larger base type for chat prose on small screens. */ .md-body { font-size: 14.5px; line-height: 1.6; } } /* ───────────────────────────────────────────────────────────────────── * POLICY SNAPSHOT (#75 + #64) — the decision-ordered coverage lens shared * by the marketplace detail modal and the in-chat compare card. Grounded * on the landing's editorial system: hairline card, soft long shadow, * Fraunces group title, a tinted accent rail per decision group, generous * row rhythm. One look, two surfaces. * ───────────────────────────────────────────────────────────────────── */ .snap-stack { display: flex; flex-direction: column; gap: 12px; } .snap-group { position: relative; border: 1px solid var(--border); border-radius: 16px; padding: 14px 16px 8px 18px; background: linear-gradient(180deg, color-mix(in srgb, var(--snap-accent, var(--primary)) 6%, var(--card)) 0%, var(--card) 44%); box-shadow: 0 1px 2px color-mix(in srgb, var(--foreground) 4%, transparent), 0 18px 44px -34px color-mix(in srgb, var(--foreground) 26%, transparent); } .snap-group::before { content: ""; position: absolute; left: 0; top: 14px; bottom: 14px; width: 3px; border-radius: 999px; background: var(--snap-accent, var(--primary)); opacity: .5; } .snap-head { display: inline-flex; align-items: center; gap: 8px; margin-bottom: 3px; } .snap-dot { width: 6px; height: 6px; border-radius: 999px; background: var(--snap-accent, var(--primary)); flex-shrink: 0; } .snap-title { font-family: var(--font-serif); font-optical-sizing: auto; font-variation-settings: "SOFT" 40, "WONK" 0; letter-spacing: -.011em; font-weight: 600; font-size: 14.5px; color: var(--foreground); } .snap-sub { font-size: 11px; line-height: 1.45; color: var(--muted-foreground); margin: 0 0 9px; } .snap-rows { display: flex; flex-direction: column; } .snap-row { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding: 8px 0; border-top: 1px solid color-mix(in srgb, var(--border) 65%, transparent); } .snap-row:first-child { border-top: 0; } .snap-row dt { font-size: 11.5px; line-height: 1.4; color: var(--muted-foreground); flex: 1; min-width: 0; } .snap-row dd { margin: 0; font-size: 12.5px; font-weight: 600; color: var(--foreground); text-align: right; font-variant-numeric: tabular-nums; max-width: 60%; overflow-wrap: anywhere; } .snap-row[data-rel="true"] dd { color: var(--primary); } .snap-group--sit { padding: 13px 16px; background: linear-gradient(180deg, color-mix(in srgb, var(--primary) 4%, var(--card)) 0%, var(--card) 60%); } .snap-group--sit::before { display: none; } .snap-sit-toggle { display: flex; align-items: center; gap: 9px; width: 100%; background: none; border: 0; padding: 0; cursor: pointer; color: inherit; text-align: left; } .snap-rel-pill { font-size: 9px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--primary); background: color-mix(in srgb, var(--primary) 12%, transparent); border: 1px solid color-mix(in srgb, var(--primary) 38%, transparent); border-radius: 999px; padding: 2px 8px; white-space: nowrap; } .snap-chevron { margin-left: auto; font-size: 15px; line-height: 1; color: var(--muted-foreground); transition: transform .2s ease; } .snap-chevron[data-open="true"] { transform: rotate(180deg); } .snap-rel-tag { font-size: 8.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--primary); margin-left: 7px; vertical-align: middle; } /* In-chat / marketplace card stat tile (#47/#89) — equal-height tiles in a * 2×2 grid. The label gets a fixed 2-line block so a 1-line label and a * wrapping one ("Mandatory co-pay") line up, and the value is pinned to the * bottom so all four value baselines align. overflow:visible so the * hover "?" tooltip is never clipped by the tile. */ .cs-tile { display: flex; flex-direction: column; min-height: 64px; background: color-mix(in srgb, var(--primary) 4%, var(--muted)); border: 1px solid color-mix(in srgb, var(--border) 82%, transparent); border-radius: 10px; padding: 8px 10px; overflow: visible; } .cs-label { font-size: 9.5px; font-weight: 600; letter-spacing: .045em; text-transform: uppercase; color: var(--muted-foreground); line-height: 1.25; min-height: 2.4em; /* reserve 2 lines so every tile aligns */ display: flex; align-items: flex-start; overflow-wrap: anywhere; } .cs-value { margin-top: auto; padding-top: 4px; font-size: 13px; font-weight: 700; color: var(--foreground); font-variant-numeric: tabular-nums; line-height: 1.2; overflow-wrap: anywhere; } /* ───────────────────────────────────────────────────────────────────── * REPUTATION — one card per independent source (#82). Same editorial * tokens as the snapshot: tinted card, hairline, soft lift on hover for * the clickable ones. A lead "overall" synthesis sits above the grid. * ───────────────────────────────────────────────────────────────────── */ .rev-lead { display: flex; align-items: flex-start; gap: 12px; border: 1px solid var(--border); border-radius: 16px; padding: 13px 15px; background: linear-gradient(180deg, color-mix(in srgb, var(--primary) 6%, var(--card)) 0%, var(--card) 50%); box-shadow: 0 1px 2px color-mix(in srgb, var(--foreground) 4%, transparent), 0 18px 44px -34px color-mix(in srgb, var(--foreground) 26%, transparent); } .rev-grade { display: flex; flex-direction: column; align-items: center; justify-content: center; width: 46px; height: 46px; border-radius: 12px; font-size: 17px; font-weight: 800; line-height: 1; flex-shrink: 0; } .rev-grade small { font-size: 9px; font-weight: 700; opacity: .9; margin-top: 2px; } .rev-lead-head { font-size: 12.5px; line-height: 1.45; color: var(--foreground); } .rev-lead-sub { font-size: 10.5px; line-height: 1.4; color: var(--muted-foreground); margin-top: 4px; } /* #90 — fixed 3×2 even grid (never ragged auto-fit). Equal-height rows so * the six buckets are perfectly uniform regardless of content length. */ .rev-grid { display: grid; grid-template-columns: repeat(3, 1fr); grid-auto-rows: 1fr; gap: 10px; } @media (max-width: 900px) { .rev-grid { grid-template-columns: repeat(2, 1fr); } } @media (max-width: 560px) { .rev-grid { grid-template-columns: 1fr; } } .rev-card { position: relative; display: flex; flex-direction: column; min-height: 116px; border: 1px solid color-mix(in srgb, var(--border) 82%, transparent); border-radius: 12px; padding: 12px 13px; background: color-mix(in srgb, var(--primary) 4%, var(--card)); text-decoration: none; color: inherit; } .rev-card--link { transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease; } .rev-card--link:hover { border-color: color-mix(in srgb, var(--primary) 48%, var(--border)); box-shadow: 0 14px 30px -24px color-mix(in srgb, var(--foreground) 32%, transparent); transform: translateY(-1px); } .rev-src { font-size: 9.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--muted-foreground); } .rev-val { font-size: 16px; font-weight: 700; color: var(--foreground); margin-top: 4px; font-variant-numeric: tabular-nums; } .rev-verdict { font-size: 13px; font-weight: 600; text-transform: capitalize; } .rev-sub { font-size: 10.5px; line-height: 1.4; color: var(--muted-foreground); margin-top: 3px; } .rev-go { color: var(--primary); font-weight: 700; font-size: 10px; } .rev-card--sum { padding: 12px 14px; } .rev-lines { display: flex; flex-direction: column; gap: 2px; margin-top: 7px; } .rev-line { display: block; font-size: 12px; line-height: 1.5; text-decoration: none; color: var(--foreground); padding: 3px 0; border-top: 1px solid color-mix(in srgb, var(--border) 55%, transparent); } .rev-lines .rev-line:first-child { border-top: 0; } .rev-line:hover .rev-line-name { color: var(--primary); } .rev-line-name { font-weight: 600; } .rev-line-verdict { color: var(--muted-foreground); } /* ───────────────────────────────────────────────────────────────────── * GLOSSARY TIP (#64/#65/#98) — the ONE explainer used on snapshot rows * AND card tiles. Hover/focus only (no click, no close). The popup is * width-constrained and sits ABOVE the badge, centred, pointer-events- * none, so it never blocks interaction or spills across cards. Editorial * card chrome to match .snap-* / .rev-* (Fraunces-adjacent title, soft * shadow, hairline border). * ───────────────────────────────────────────────────────────────────── */ .gtip { position: relative; display: inline-flex; vertical-align: middle; margin-left: 5px; } .gtip-badge { display: inline-flex; align-items: center; justify-content: center; width: 14px; height: 14px; border-radius: 999px; border: 1px solid color-mix(in srgb, var(--muted-foreground) 55%, transparent); color: var(--muted-foreground); font-size: 9px; font-weight: 700; line-height: 1; cursor: help; user-select: none; outline: none; transition: color .15s ease, border-color .15s ease; } .gtip:hover .gtip-badge, .gtip:focus-within .gtip-badge { color: var(--primary); border-color: color-mix(in srgb, var(--primary) 60%, transparent); } .gtip-pop { pointer-events: none; position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%) translateY(3px); width: min(20rem, 74vw); background: var(--card); border: 1px solid var(--border); border-radius: 12px; box-shadow: 0 1px 2px color-mix(in srgb, var(--foreground) 5%, transparent), 0 18px 44px -22px color-mix(in srgb, var(--foreground) 32%, transparent); padding: 11px 13px; text-align: left; opacity: 0; visibility: hidden; transition: opacity .15s ease, transform .15s ease, visibility .15s; z-index: 60; } .gtip:hover .gtip-pop, .gtip:focus-within .gtip-pop { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); } .gtip-pop::after { content: ""; position: absolute; top: 100%; left: 50%; transform: translateX(-50%); border: 6px solid transparent; border-top-color: var(--card); } .gtip-title { display: block; font-family: var(--font-serif); font-weight: 600; font-size: 12.5px; letter-spacing: -.01em; color: var(--foreground); margin-bottom: 4px; } .gtip-body { display: block; font-size: 11.5px; line-height: 1.5; color: var(--muted-foreground); text-transform: none; font-weight: 400; letter-spacing: normal; } /* ───────────────────────────────────────────────────────────────────── * HelpTip — the shared "?" affordance for policy-calculation controls. * * Visual chrome mirrors `.gtip-*` above (14px badge, var(--card) bg, * var(--border) hairline, Fraunces title, soft shadow, small arrow). The * difference is structural: the popover is portalled to and given * `position:fixed` coords by HelpTip.tsx (the surfaces sit in overflow * scroll containers that clip an absolute popover), so this block carries * NO positioning — only appearance and the up/down arrow direction. * ───────────────────────────────────────────────────────────────────── */ .helptip-badge { display: inline-flex; align-items: center; justify-content: center; width: 14px; height: 14px; border-radius: 999px; border: 1px solid color-mix(in srgb, var(--muted-foreground) 55%, transparent); background: transparent; color: var(--muted-foreground); font-size: 9px; font-weight: 700; line-height: 1; cursor: help; user-select: none; outline: none; padding: 0; margin-left: 5px; transition: color .15s ease, border-color .15s ease; } .helptip-badge:hover, .helptip-badge:focus-visible, .helptip-badge[aria-expanded="true"] { color: var(--primary); border-color: color-mix(in srgb, var(--primary) 60%, transparent); } .helptip-badge:focus-visible { box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 35%, transparent); } .helptip-pop { width: min(20rem, 74vw); background: var(--card); border: 1px solid var(--border); border-radius: 12px; box-shadow: 0 1px 2px color-mix(in srgb, var(--foreground) 5%, transparent), 0 18px 44px -22px color-mix(in srgb, var(--foreground) 32%, transparent); padding: 11px 13px; text-align: left; } .helptip-pop::after { content: ""; position: absolute; left: 50%; transform: translateX(-50%); border: 6px solid transparent; } .helptip-pop--above::after { top: 100%; border-top-color: var(--card); } .helptip-pop--below::after { bottom: 100%; border-bottom-color: var(--card); } .helptip-title { display: block; font-family: var(--font-serif); font-weight: 600; font-size: 12.5px; letter-spacing: -.01em; color: var(--foreground); margin-bottom: 4px; } .helptip-body { display: block; font-size: 11.5px; line-height: 1.5; color: var(--muted-foreground); text-transform: none; font-weight: 400; letter-spacing: normal; }