/* ============================================================ Family Home Lab — Components & Layout Builds strictly from tokens.css variables per DESIGN.md. ============================================================ */ * { box-sizing: border-box; } body { margin: 0; font-family: var(--font-family); background: var(--canvas-soft); color: var(--ink-secondary); font: var(--type-body-md); -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; } a { color: var(--primary); text-decoration: none; } a:hover { text-decoration: underline; } /* -------------------------------------------------- Login */ .login-screen { min-height: 100vh; display: flex; align-items: center; justify-content: center; background: var(--secondary); color: var(--surface); position: relative; overflow: hidden; padding: var(--space-lg); } /* Subtle starfield/sticker dots */ .login-screen::before { content: ""; position: absolute; inset: 0; background-image: radial-gradient(rgba(255,255,255,.16) 1px, transparent 1.5px), radial-gradient(rgba(255,255,255,.1) 1px, transparent 1.5px); background-size: 44px 44px, 71px 71px; background-position: 0 0, 17px 21px; pointer-events: none; } .login-wrap { position: relative; z-index: 1; width: 100%; max-width: 400px; } .login-greeting { margin: 0 0 var(--space-xxl); font: var(--type-display-1); color: var(--surface); letter-spacing: -1.5px; } .auth-card { background: var(--surface); border-radius: var(--rounded-lg); box-shadow: var(--shadow-level-2); padding: var(--space-xl) var(--space-xl); color: var(--ink-secondary); } .auth-title { font: var(--type-title); margin: 0 0 var(--space-md); color: var(--ink); } /* -------------------------------------------------- Form bits */ .form-field { margin-bottom: var(--space-md); } .form-field label { display: block; font: var(--type-eyebrow); letter-spacing: 0.125px; color: var(--ink-muted); margin-bottom: var(--space-xs); } .text-input { width: 100%; padding: 10px 12px; font: var(--type-body-sm); color: var(--ink); border: 1px solid rgb(221, 221, 221); border-radius: var(--rounded-xs); background: var(--surface); } .text-input:focus { outline: none; border-color: var(--primary); box-shadow: var(--shadow-level-1), 0 0 0 3px rgba(0, 117, 222, 0.18); } .form-error { background: #fdecec; color: #b3261e; border: 1px solid #f5c6c4; border-radius: var(--rounded-sm); padding: var(--space-sm); font: var(--type-body-sm); margin-bottom: var(--space-md); } /* -------------------------------------------------- Buttons */ .button { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-xs); border: none; cursor: pointer; font: var(--type-button); text-decoration: none; transition: transform .08s ease, background .15s ease, box-shadow .15s ease; } .button:active { transform: scale(0.97); } button.button, input[type="submit"].button { font-family: inherit; } .button-primary { background: var(--primary); color: var(--on-primary); border-radius: var(--rounded-full); padding: 12px 28px; } .button-primary:hover { background: var(--primary-active); color: var(--on-primary); text-decoration: none; } .button-secondary { background: var(--surface); color: var(--ink); border-radius: var(--rounded-full); padding: 11px 26px; box-shadow: var(--shadow-level-1); border: 1px solid var(--hairline); } .button-secondary:hover { box-shadow: var(--shadow-level-1); } .button-utility { background: var(--surface); color: var(--ink); border-radius: var(--rounded-md); padding: 4px 14px; border: 1px solid var(--hairline); font: var(--type-body-sm); } .button-utility:hover { background: var(--canvas-soft); } .width-full { width: 100%; } /* -------------------------------------------------- Nav bar */ .nav-bar { position: sticky; top: 0; z-index: 20; display: flex; align-items: center; justify-content: space-between; gap: var(--space-lg); background: var(--surface); border-bottom: 1px solid var(--hairline); padding: var(--space-sm) var(--space-xxl); } .nav-wordmark { font: var(--type-heading-2); color: var(--ink); letter-spacing: -0.25px; text-decoration: none; } .nav-wordmark:hover { text-decoration: none; } .nav-right { display: flex; align-items: center; gap: var(--space-md); } .nav-user { display: flex; align-items: center; gap: var(--space-xs); font: var(--type-body-sm); color: var(--ink-secondary); } .nav-avatar { width: 28px; height: 28px; border-radius: var(--rounded-full); background: var(--primary); color: var(--on-primary); display: flex; align-items: center; justify-content: center; font: var(--type-button); } /* -------------------------------------------------- Layout */ .page { max-width: var(--container-max); margin: 0 auto; padding: var(--space-xxl) var(--space-lg); } .greeting { font: var(--type-heading-1); color: var(--ink); margin: 0 0 var(--space-xxl); } .section { margin-bottom: var(--space-xl); } .section-head { display: flex; align-items: center; gap: var(--space-sm); margin-bottom: var(--space-md); } .category-pill { display: inline-flex; align-items: center; gap: 6px; font: var(--type-eyebrow); letter-spacing: 0.125px; background: var(--surface); border-radius: var(--rounded-full); padding: 4px 8px; border: 1px solid var(--hairline); } .pill-dot { width: 8px; height: 8px; border-radius: var(--rounded-full); } .section-title { font: var(--type-heading-2); color: var(--ink); margin: 0; } /* -------------------------------------------------- Tool grid */ .tool-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-lg); } @media (max-width: 840px) { .tool-grid { grid-template-columns: repeat(2, 1fr); } } @media (max-width: 600px) { .tool-grid { grid-template-columns: 1fr; } } .tool-card { display: flex; flex-direction: column; gap: var(--space-sm); background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--rounded-lg); padding: var(--space-lg); text-decoration: none; color: var(--ink-secondary); transition: box-shadow .18s ease, transform .18s ease; } .tool-card:hover { box-shadow: var(--shadow-level-1); transform: translateY(-1px); text-decoration: none; } .tool-card-top { display: flex; align-items: flex-start; justify-content: space-between; } .tool-icon { width: 40px; height: 40px; border-radius: var(--rounded-full); display: flex; align-items: center; justify-content: center; color: var(--surface); font: var(--type-title); flex: none; } .tool-card .tool-name { font: var(--type-title); color: var(--ink); margin: 0; } .tool-card .tool-desc { font: var(--type-body-sm); color: var(--ink-muted); margin: 0; flex: 1; } .tool-card-bottom { display: flex; align-items: center; justify-content: space-between; } .launch-chip { font: var(--type-caption); color: var(--ink-faint); } .tag-chip { font: var(--type-caption); color: var(--ink-muted); border: 1px solid var(--hairline); border-radius: var(--rounded-full); padding: 1px 8px; background: var(--surface-2); } .tag-chip-login { color: var(--sticker-orange); border-color: color-mix(in srgb, var(--sticker-orange) 40%, transparent); } .tag-chip-admin { color: var(--ink-muted); border-style: dashed; } /* catalogue search */ .dash-search { max-width: 480px; margin-bottom: var(--space-lg); } .tool-grid .tool-card.hidden { display: none; } .section.hidden-section { display: none; } /* status dot levels */ .status-dot { width: 8px; height: 8px; border-radius: var(--rounded-full); display: inline-block; } .status-online { background: var(--sticker-green); } .status-starting { background: var(--sticker-orange); } .status-offline { background: var(--ink-faint); } /* loading pulse for polling */ .tool-grid.htmx-request .tool-card { opacity: .6; transition: opacity .2s; } /* -------------------------------------------------- Tool embed */ .tool-bar { position: sticky; top: 52px; z-index: 15; display: flex; align-items: center; justify-content: space-between; gap: var(--space-md); background: var(--surface); border-bottom: 1px solid var(--hairline); padding: var(--space-sm) var(--space-xxl); } .embed-well { background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--rounded-lg); overflow: hidden; height: calc(100vh - 170px); box-shadow: var(--shadow-level-1); } .embed-well iframe { width: 100%; height: 100%; border: 0; display: block; } /* -------------------------------------------------- Link-out fallback */ .linkout-card { background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--rounded-lg); padding: var(--space-xl); max-width: 520px; box-shadow: var(--shadow-level-1); } /* -------------------------------------------------- Partial rows (status) */ .status-refresh { display: contents; /* keeps the HTMX swap invisible-pressure-free */ } /* -------------------------------------------------- Admin */ .user-table { width: 100%; border-collapse: collapse; background: var(--surface); border-radius: var(--rounded-lg); overflow: hidden; border: 1px solid var(--hairline); } .user-table th, .user-table td { text-align: left; padding: var(--space-sm) var(--space-md); border-bottom: 1px solid var(--hairline); font: var(--type-body-sm); } .user-table th { background: var(--canvas-soft); color: var(--ink-muted); font: var(--type-eyebrow); letter-spacing: .125px; } .user-table tr:last-child td { border-bottom: none; } .badge { display: inline-block; font: var(--type-eyebrow); border-radius: var(--rounded-full); padding: 2px 8px; background: var(--canvas-soft); color: var(--ink-muted); } .badge-admin { background: var(--secondary); color: var(--surface); } .admin-panel { display: grid; grid-template-columns: 2fr 1fr; gap: var(--space-xxl); align-items: start; } @media (max-width: 840px) { .admin-panel { grid-template-columns: 1fr; } } /* -------------------------------------------------- Workspace / file list */ .tool-detail { display: flex; flex-direction: column; gap: var(--space-lg); } .workspace { background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--rounded-lg); padding: var(--space-lg) var(--space-xl); box-shadow: var(--shadow-level-1); } .workspace-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-md); margin-bottom: var(--space-sm); } .file-list { list-style: none; margin: 0; padding: 0; } .file-list li { display: flex; align-items: center; justify-content: space-between; gap: var(--space-md); padding: 10px 2px; border-bottom: 1px solid var(--hairline); font: var(--type-body-sm); } .file-list li:last-child { border-bottom: none; } .file-name { color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .file-meta { color: var(--ink-faint); font: var(--type-caption); white-space: nowrap; } /* -------------------------------------------------- Minimal, generic */ .muted { color: var(--ink-muted); } .faint { color: var(--ink-faint); } .margin-top { margin-top: var(--space-lg); } .stack > * + * { margin-top: var(--space-lg); }