/* ========================================================================= auth.css — login + dashboard dreamy surfaces Frosted glass cards, rose CTAs, 44px+ touch targets, soft glows. Builds on tokens.css (colors, type, motion) + base.css (buttons). ========================================================================= */ /* ---- shared page shell ------------------------------------------------ */ .auth-shell { /* centers content vertically + horizontally */ min-height: 100vh; /* full viewport height */ min-height: 100svh; /* small viewport units for mobile browsers */ display: flex; /* flexbox column for centering */ flex-direction: column; /* stack header / card / footer */ align-items: center; /* horizontal center */ justify-content: center; /* vertical center (fallback for old browsers) */ justify-content: safe center; /* when content overflows, anchor to top so the */ /* toast/button never slide up under the fixed nav */ padding: clamp(5.5rem, 14vh, 7rem) var(--gut) calc(var(--gut) * 1.5); /* big top pad clears the nav pill */ position: relative; /* let glows position against this */ z-index: 1; /* sit above the scene (z 0), below whale (z 2) */ } /* soft rose glow that sits behind the card (pure decoration) */ .auth-glow { /* radial blush halo */ position: absolute; /* relative to .auth-shell */ width: 60vmin; /* responsive diameter */ height: 60vmin; /* keep it circular */ background: radial-gradient(circle, /* rose center fading out */ rgba(255, 143, 171, 0.35) 0%, /* warm rose core */ rgba(255, 143, 171, 0.10) 45%, /* mid fade */ transparent 72%); /* fully transparent edge */ border-radius: 50%; /* circle */ filter: blur(40px); /* soften into a haze */ z-index: -1; /* sit behind the card */ top: 50%; /* vertically centered */ left: 50%; /* horizontally centered */ transform: translate(-50%, -50%); /* perfect center */ pointer-events: none; /* never block clicks */ animation: glow-breathe 6s var(--ease-flow) infinite alternate; /* slow pulse */ } @keyframes glow-breathe { /* the halo gently swells + contracts */ from { transform: translate(-50%, -50%) scale(0.92); opacity: 0.7; } /* smaller, dimmer */ to { transform: translate(-50%, -50%) scale(1.08); opacity: 1; } /* larger, brighter */ } /* ---- the frosted card ------------------------------------------------- */ .auth-card { /* the glass panel holding the form / dashboard bits */ width: 100%; /* fill column up to max */ max-width: 460px; /* login card max width */ background: var(--panel); /* frosted cloud white */ backdrop-filter: blur(24px) saturate(140%); /* frost the scene behind */ -webkit-backdrop-filter: blur(24px) saturate(140%); /* safari prefix */ border: 1px solid var(--panel-border); /* soft rose hairline */ border-radius: var(--radius-card); /* 22px rounded corners */ padding: clamp(2rem, 5vw, 3rem); /* generous internal padding */ box-shadow: /* layered soft shadows for float */ 0 30px 60px -20px rgba(61, 44, 78, 0.28), /* deep drop */ 0 8px 20px -8px rgba(255, 143, 171, 0.22); /* warm rose tint */ position: relative; /* anchor the mascot */ animation: card-rise 0.8s var(--ease-soft) both; /* gentle entrance */ } @keyframes card-rise { /* card floats up + fades in */ from { opacity: 0; transform: translateY(24px); } /* start low + invisible */ to { opacity: 1; transform: translateY(0); } /* settle into place */ } /* mini whale mascot perched on the card top */ .auth-mascot { /* small floating whale above the card */ width: 120px; /* compact whale */ margin: 0 auto -10px; /* center + overlap the card top */ display: block; /* block so margin auto centers */ animation: mascot-bob 5s var(--ease-flow) infinite alternate; /* gentle hover */ } @keyframes mascot-bob { /* the whale bobs up and down */ from { transform: translateY(0); } /* resting position */ to { transform: translateY(-8px); } /* lifted slightly */ } /* ---- headings on auth pages ------------------------------------------ */ .auth-card h1 { /* main heading inside the card */ font-family: var(--font-display); /* Comfortaa rounded display */ font-size: var(--step-h3); /* fluid heading size */ font-weight: 700; /* bold */ color: var(--ink); /* plum-charcoal */ text-align: center; /* centered under mascot */ margin: 0 0 0.5rem; /* tight space below */ line-height: 1.15; /* airy line height */ } .auth-sub { /* subtitle paragraph under heading */ text-align: center; /* match heading alignment */ color: var(--ink-soft); /* muted plum */ font-size: var(--step-body); /* body size */ margin: 0 0 2rem; /* space before the form */ line-height: 1.6; /* readable */ max-width: 34ch; /* cap line length */ margin-left: auto; /* center the cap */ margin-right: auto; /* center the cap */ } /* ---- form fields ------------------------------------------------------ */ .field { /* one labeled input block */ margin-bottom: 1.25rem; /* spacing between fields */ } .field > label { /* the label ABOVE the input */ display: block; /* full width row */ font-size: var(--step-small); /* small label text */ font-weight: 700; /* bold label */ color: var(--ink-soft); /* muted plum */ margin-bottom: 0.5rem; /* gap between label + input */ letter-spacing: 0.02em; /* slight tracking */ } .input-wrap { /* relative wrapper for input + toggle */ position: relative; /* anchor the eye button */ display: flex; /* so the toggle aligns right */ align-items: center; /* vertically center the toggle */ } .input-wrap input, .input-wrap textarea, .input-wrap select { /* the field itself */ width: 100%; /* fill the wrapper */ min-height: 52px; /* ≥44px touch target + comfort */ padding: 0.85rem 1rem; /* inner spacing */ padding-right: 3rem; /* room for the eye toggle */ font-family: var(--font-body); /* Nunito body font */ font-size: var(--step-body); /* body size */ color: var(--ink); /* plum text */ background: rgba(255, 255, 255, 0.55); /* translucent white fill */ border: 1.5px solid var(--panel-border); /* soft rose border */ border-radius: 14px; /* rounded field */ outline: none; /* we draw our own focus ring */ transition: border-color var(--dur-fast) var(--ease-gentle), /* smooth focus */ box-shadow var(--dur-fast) var(--ease-gentle), /* smooth glow */ background var(--dur-fast) var(--ease-gentle); /* smooth fill */ } .input-wrap input::placeholder, .input-wrap textarea::placeholder { /* placeholder styling */ color: rgba(107, 90, 126, 0.5); /* faint plum */ } .input-wrap input:focus, .input-wrap textarea:focus, .input-wrap select:focus { /* focus state — rose ring */ border-color: var(--rose); /* rose border on focus */ background: rgba(255, 255, 255, 0.8); /* brighter fill on focus */ box-shadow: 0 0 0 4px rgba(255, 143, 171, 0.18); /* soft rose halo */ } .input-wrap textarea { /* multiline fields (playground) */ min-height: 120px; /* taller for messages */ resize: vertical; /* let users drag taller */ padding-right: 1rem; /* no eye toggle on textarea */ line-height: 1.6; /* readable lines */ } .input-wrap select { /* dropdown (model picker) */ appearance: none; /* kill native chrome */ -webkit-appearance: none; /* safari too */ cursor: pointer; /* indicate it's clickable */ padding-right: 2.5rem; /* room for custom arrow */ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='none' stroke='%236B5A7E' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M1 1.5l5 5 5-5'/%3E%3C/svg%3E"); /* chevron */ background-repeat: no-repeat; /* don't tile */ background-position: right 1rem center; /* park chevron at right */ } /* show/hide eye toggle inside password-style inputs */ .eye-toggle { /* the eye button */ position: absolute; /* pinned inside the wrapper */ right: 0.5rem; /* tucked at the right edge */ background: transparent; /* no fill */ border: none; /* no border */ cursor: pointer; /* pointer cursor */ padding: 0.5rem; /* 44px-ish hit area */ color: var(--ink-soft); /* muted icon */ border-radius: 10px; /* rounded hover surface */ display: grid; /* center the svg */ place-items: center; /* dead center */ transition: color var(--dur-fast) var(--ease-gentle), /* smooth color */ background var(--dur-fast) var(--ease-gentle); /* smooth bg */ } .eye-toggle:hover { /* hover feedback */ color: var(--rose); /* rose on hover */ background: rgba(255, 143, 171, 0.12); /* faint rose wash */ } .eye-toggle svg { /* the eye icon */ width: 20px; /* icon size */ height: 20px; /* icon size */ } /* ---- error message below a field ------------------------------------- */ .field-error { /* red error text under a field */ color: var(--rose-deep); /* deep rose for errors */ font-size: var(--step-small); /* small text */ font-weight: 600; /* semibold */ margin-top: 0.5rem; /* gap below the input */ min-height: 1.25rem; /* reserve space so layout doesn't jump */ display: flex; /* icon + text row */ align-items: center; /* vertically align */ gap: 0.4rem; /* space between icon + text */ opacity: 0; /* hidden by default */ transform: translateY(-4px); /* start slightly up */ transition: opacity var(--dur-fast) var(--ease-soft), /* fade in */ transform var(--dur-fast) var(--ease-soft); /* slide in */ } .field-error.is-visible { /* shown state */ opacity: 1; /* visible */ transform: translateY(0); /* settled */ animation: shake 0.4s var(--ease-gentle); /* one-shot wiggle */ } @keyframes shake { /* error wiggle */ 0%, 100% { transform: translateX(0); } /* rest */ 25% { transform: translateX(-5px); } /* left */ 75% { transform: translateX(5px); } /* right */ } /* ---- primary CTA with loading spinner -------------------------------- */ .auth-submit { /* the main form button */ width: 100%; /* full width */ min-height: 54px; /* generous touch target */ margin-top: 0.5rem; /* slight gap above */ font-family: var(--font-display); /* Comfortaa */ font-size: 1.05rem; /* readable */ font-weight: 700; /* bold */ display: inline-flex; /* spinner + text row */ align-items: center; /* vertical center */ justify-content: center; /* horizontal center */ gap: 0.6rem; /* space between spinner + label */ } .auth-submit .spinner { /* the loading spinner */ width: 18px; /* spinner size */ height: 18px; /* spinner size */ border: 2.5px solid rgba(255, 255, 255, 0.5); /* white track */ border-top-color: #fff; /* solid leading edge */ border-radius: 50%; /* circle */ animation: spin 0.7s linear infinite; /* constant spin */ display: none; /* hidden until loading */ } .auth-submit.is-loading .spinner { display: block; } /* show when loading */ .auth-submit.is-loading .label { opacity: 0.7; } /* dim label when loading */ .auth-submit.is-loading { pointer-events: none; } /* block double-submit */ @keyframes spin { to { transform: rotate(360deg); } } /* full rotation */ /* ---- helper links under the form ------------------------------------- */ .auth-helpers { /* row of small links */ margin-top: 1.5rem; /* gap below the button */ text-align: center; /* centered */ font-size: var(--step-small); /* small text */ color: var(--ink-soft); /* muted */ } .auth-helpers a { /* the links */ color: var(--rose-deep); /* rose link */ text-decoration: none; /* no underline */ font-weight: 700; /* bold */ transition: color var(--dur-fast) var(--ease-gentle); /* smooth */ } .auth-helpers a:hover { color: var(--rose); } /* brighter on hover */ /* ========================================================================= DASHBOARD ========================================================================= */ .dash-shell { /* dashboard layout */ max-width: var(--maxw); /* site max width */ margin: 0 auto; /* center */ padding: clamp(5rem, 10vw, 7rem) var(--gut) var(--space-section); /* top clears nav */ position: relative; /* z-index context */ z-index: 1; /* above scene */ } .dash-head { /* greeting + actions row */ display: flex; /* space between title + logout */ align-items: flex-end; /* align bottoms */ justify-content: space-between; /* push apart */ gap: 1.5rem; /* gap on wrap */ flex-wrap: wrap; /* wrap on small screens */ margin-bottom: 2.5rem; /* space before stats */ } .dash-head h1 { /* the greeting heading */ font-family: var(--font-display); /* Comfortaa */ font-size: var(--step-h2); /* h2 scale */ font-weight: 700; /* bold */ color: var(--ink); /* plum */ margin: 0 0 0.4rem; /* tight below */ line-height: 1.1; /* snug */ } .dash-head p { /* subtitle */ color: var(--ink-soft); /* muted */ margin: 0; /* reset */ font-size: var(--step-body); /* body */ } .dash-head .endpoint-mini { /* the endpoint pill in the header */ font-family: 'JetBrains Mono', monospace; /* mono */ font-size: var(--step-mono); /* small mono */ background: var(--panel); /* frosted */ border: 1px solid var(--panel-border); /* hairline */ padding: 0.4rem 0.8rem; /* pill padding */ border-radius: var(--radius-pill); /* pill */ color: var(--ink-soft); /* muted */ margin-top: 0.6rem; /* gap */ display: inline-block; /* pill sizing */ } /* ---- stat cards row --------------------------------------------------- */ .stats-row { /* grid of stat cards */ display: grid; /* css grid */ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); /* responsive */ gap: 1rem; /* card gap */ margin-bottom: 2.5rem; /* space before next section */ } .stat-card { /* one stat tile */ background: var(--panel); /* frosted */ backdrop-filter: blur(20px); /* frost */ -webkit-backdrop-filter: blur(20px); /* safari */ border: 1px solid var(--panel-border); /* hairline */ border-radius: var(--radius-card); /* rounded */ padding: 1.5rem; /* internal padding */ display: flex; /* icon + text column */ flex-direction: column; /* stack */ gap: 0.4rem; /* tight stack */ transition: transform var(--dur) var(--ease-soft), /* hover lift */ box-shadow var(--dur) var(--ease-soft); /* hover glow */ } .stat-card:hover { /* gentle hover lift */ transform: translateY(-4px); /* float up */ box-shadow: 0 16px 30px -14px rgba(61, 44, 78, 0.25); /* deeper shadow */ } .stat-card .stat-icon { /* the little svg icon */ width: 30px; /* icon box */ height: 30px; /* icon box */ color: var(--rose); /* rose icon */ margin-bottom: 0.3rem; /* gap to number */ } .stat-card .stat-num { /* the big number */ font-family: var(--font-display); /* Comfortaa */ font-size: clamp(1.8rem, 4vw, 2.6rem); /* big */ font-weight: 700; /* bold */ color: var(--ink); /* plum */ line-height: 1; /* tight */ } .stat-card .stat-label { /* the label under the number */ font-size: var(--step-small); /* small */ color: var(--ink-soft); /* muted */ font-weight: 600; /* semibold */ letter-spacing: 0.04em; /* tracked */ text-transform: uppercase; /* caps label */ } .stat-card.is-good .stat-num { color: #5BB89E; } /* green for healthy */ .stat-card.is-warn .stat-num { color: var(--rose-deep); } /* rose for issues */ /* ---- section headings ------------------------------------------------- */ .dash-section { /* a dashboard section */ margin-top: 2.5rem; /* space above each section */ } .dash-section > h2 { /* section heading */ font-family: var(--font-display); /* Comfortaa */ font-size: var(--step-h3); /* h3 scale */ font-weight: 700; /* bold */ color: var(--ink); /* plum */ margin: 0 0 1.25rem; /* space below */ } /* ---- model grid ------------------------------------------------------- */ .model-grid { /* responsive grid of model chips */ display: grid; /* grid */ grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); /* fluid columns */ gap: 0.75rem; /* chip gap */ } .model-chip { /* one model tile */ background: var(--panel); /* frosted */ border: 1px solid var(--panel-border); /* hairline */ border-radius: 16px; /* rounded */ padding: 0.85rem 1rem; /* internal */ display: flex; /* name + meta row */ align-items: center; /* center */ justify-content: space-between; /* push apart */ gap: 0.75rem; /* gap */ transition: transform var(--dur-fast) var(--ease-soft), /* hover */ border-color var(--dur-fast) var(--ease-soft); /* hover */ } .model-chip:hover { /* hover lift */ transform: translateY(-2px); /* small float */ border-color: var(--rose); /* rose border */ } .model-chip .mc-name { /* the model id */ font-family: 'JetBrains Mono', monospace; /* mono */ font-size: var(--step-mono); /* small mono */ color: var(--ink); /* plum */ font-weight: 600; /* semibold */ word-break: break-all; /* wrap long ids */ } .model-chip .mc-badge { /* the target count badge */ flex-shrink: 0; /* don't shrink */ font-size: 0.7rem; /* tiny */ font-weight: 700; /* bold */ padding: 0.25rem 0.55rem; /* pill padding */ border-radius: var(--radius-pill); /* pill */ background: rgba(255, 143, 171, 0.16); /* rose wash */ color: var(--rose-deep); /* rose text */ white-space: nowrap; /* no wrap */ } .model-chip.is-anthropic .mc-badge { /* anthropic = cloud badge */ background: rgba(157, 170, 242, 0.22); /* periwinkle wash */ color: #6B7AD6; /* periwinkle text */ } /* ---- playground ------------------------------------------------------- */ .playground { /* the try-it card */ background: var(--panel); /* frosted */ backdrop-filter: blur(20px); /* frost */ -webkit-backdrop-filter: blur(20px); /* safari */ border: 1px solid var(--panel-border); /* hairline */ border-radius: var(--radius-card); /* rounded */ padding: clamp(1.25rem, 3vw, 2rem); /* padding */ } .pg-row { /* a playground form row */ display: grid; /* grid */ grid-template-columns: 1fr; /* single column default */ gap: 1rem; /* gap */ margin-bottom: 1rem; /* row gap */ } @media (min-width: 640px) { /* on wider screens */ .pg-row.split { grid-template-columns: 1fr 1fr; } /* two columns */ } .pg-actions { /* send + clear row */ display: flex; /* flex */ gap: 0.75rem; /* gap */ align-items: center; /* center */ flex-wrap: wrap; /* wrap */ } .pg-status { /* tiny status text next to buttons */ font-size: var(--step-small); /* small */ color: var(--ink-soft); /* muted */ font-weight: 600; /* semibold */ } .pg-status.is-error { color: var(--rose-deep); } /* error color */ .pg-status.is-ok { color: #5BB89E; } /* ok color */ .pg-output { /* the streaming response box */ margin-top: 1.25rem; /* gap above */ min-height: 140px; /* visible area */ max-height: 420px; /* cap height */ overflow-y: auto; /* scroll if long */ background: rgba(255, 255, 255, 0.5); /* translucent */ border: 1px dashed var(--panel-border); /* dashed to signal "live" */ border-radius: 14px; /* rounded */ padding: 1rem; /* internal */ font-family: 'JetBrains Mono', monospace; /* mono output */ font-size: var(--step-mono); /* small mono */ color: var(--ink); /* plum */ line-height: 1.6; /* readable */ white-space: pre-wrap; /* preserve newlines + wrap */ word-break: break-word; /* wrap long tokens */ } .pg-output:empty::before { /* placeholder when empty */ content: 'the response will stream here…'; /* hint */ color: rgba(107, 90, 126, 0.5); /* faint */ font-style: italic; /* italic hint */ } .pg-output .cursor { /* blinking caret while streaming */ display: inline-block; /* inline */ width: 8px; /* caret width */ height: 1.1em; /* caret height */ background: var(--rose); /* rose caret */ vertical-align: text-bottom; /* align to text */ margin-left: 2px; /* tiny gap */ animation: blink 1s steps(2) infinite; /* blink */ } @keyframes blink { 50% { opacity: 0; } } /* blink off at halfway */ /* ---- loading skeleton ------------------------------------------------- */ .skeleton { /* shimmering placeholder */ background: linear-gradient(90deg, /* moving shimmer */ rgba(255, 143, 171, 0.08) 25%, /* dim */ rgba(255, 143, 171, 0.18) 37%, /* bright */ rgba(255, 143, 171, 0.08) 63%); /* dim */ background-size: 400% 100%; /* wide gradient to animate */ animation: shimmer 1.4s var(--ease-flow) infinite; /* loop */ border-radius: 8px; /* rounded */ color: transparent !important; /* hide text */ user-select: none; /* not selectable */ } @keyframes shimmer { /* sweep the gradient */ from { background-position: 100% 0; } /* start right */ to { background-position: 0 0; } /* sweep left */ } /* ---- logout button (ghost) ------------------------------------------- */ .logout-btn { /* the logout button */ background: transparent; /* no fill */ border: 1.5px solid var(--panel-border); /* hairline */ color: var(--ink-soft); /* muted */ padding: 0.6rem 1.2rem; /* pill padding */ border-radius: var(--radius-pill); /* pill */ font-family: var(--font-body); /* Nunito */ font-size: var(--step-small); /* small */ font-weight: 700; /* bold */ cursor: pointer; /* pointer */ transition: all var(--dur-fast) var(--ease-gentle); /* smooth */ display: inline-flex; /* icon + text */ align-items: center; /* center */ gap: 0.4rem; /* gap */ min-height: 44px; /* touch target */ } .logout-btn:hover { /* hover */ border-color: var(--rose); /* rose border */ color: var(--rose-deep); /* rose text */ background: rgba(255, 143, 171, 0.08); /* faint wash */ } /* ---- Google SSO button ----------------------------------------------- */ /* When it's the only sign-in (inside .auth-card--sso) it lives within the card. */ .auth-card--sso .btn-sso { /* the Google pill, now hero inside the card */ margin-top: 0.5rem; /* small gap below the subtitle */ } .btn-sso { /* the Google SSO pill */ width: 100%; /* full width */ min-height: 54px; /* generous touch target */ display: inline-flex; /* icon + text */ align-items: center; /* center */ justify-content: center; /* center */ gap: 0.65rem; /* icon/text gap */ font-family: var(--font-body); /* Nunito (Google uses a sans-serif) */ font-size: 1.05rem; /* readable */ font-weight: 700; /* medium-bold */ color: var(--ink); /* dark ink text */ background: #fff; /* white (official Google button) */ border-radius: 14px; /* rounded */ border: 1.5px solid var(--panel-border); /* hairline */ text-decoration: none; /* no underline */ cursor: pointer; /* pointer */ transition: transform var(--dur-fast) var(--ease-spring), /* press physics */ background var(--dur-fast) var(--ease-gentle), /* color */ box-shadow var(--dur-fast) var(--ease-gentle); /* glow */ box-shadow: 0 8px 20px -6px rgba(61, 44, 78, 0.18); /* soft shadow */ } .btn-sso:hover { /* hover */ background: #faf8fc; /* faint warm wash */ transform: translateY(-2px); /* lift */ box-shadow: 0 12px 26px -6px rgba(61, 44, 78, 0.22); /* stronger shadow */ } .btn-sso:active { /* press */ transform: translateY(0) scale(0.99); /* physical push */ } .btn-sso:focus-visible { /* keyboard focus */ outline: 3px solid var(--rose); /* rose ring */ outline-offset: 2px; /* gap */ } /* tiny muted line under the SSO button */ .auth-fine { /* the 'by continuing…' fine print */ text-align: center; /* centered */ font-size: var(--step-small); /* small */ color: var(--ink-soft); /* muted */ margin: 1rem 0 0; /* gap above */ opacity: 0.85; /* slightly dim */ } /* ---- error toast (Google callback errors) ---------------------------- */ .auth-toast { /* error banner above the card */ width: 100%; /* match card */ max-width: 460px; /* same max */ background: rgba(232, 111, 146, 0.12); /* rose wash */ border: 1px solid rgba(232, 111, 146, 0.35); /* rose border */ color: var(--rose-deep); /* rose text */ padding: 0.85rem 1rem; /* internal */ border-radius: 14px; /* rounded */ font-size: var(--step-small); /* small */ font-weight: 600; /* semibold */ margin-bottom: 1rem; /* gap */ display: flex; /* icon + text */ align-items: center; /* center */ gap: 0.5rem; /* gap */ animation: card-rise 0.4s var(--ease-soft) both; /* entrance */ }