/* Internet Use Control — Control Service UI Built on the Family Home Lab design tokens (tokens.css). Rules: canvas-soft app background, white cards, hairlines, one action blue, pill CTAs, 8px grid, touch targets >= 44px, dark mode from the tokens. */ *, *::before, *::after { box-sizing: border-box; } html { font-size: 16px; } body { margin: 0; background: var(--canvas-soft); color: var(--ink-secondary); font: var(--type-body-md); -webkit-font-smoothing: antialiased; min-height: 100dvh; } h1, h2, h3 { margin: 0; color: var(--ink); } a { color: var(--primary); text-decoration: none; } a:hover { text-decoration: underline; } code { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 0.9em; background: var(--surface-2); padding: 1px 5px; border-radius: var(--rounded-xs); } /* ---------- Login ---------- */ .login-page { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-lg); padding: var(--space-lg); background: radial-gradient(1200px 600px at 15% 0%, #2b3d93 0%, transparent 60%), var(--secondary); } .login-band { width: 100%; max-width: 960px; display: grid; grid-template-columns: 1.1fr 0.9fr; gap: var(--space-xxl); align-items: center; padding: var(--space-xxl) 0; } .login-eyebrow { margin: 0 0 var(--space-sm); font: var(--type-eyebrow); text-transform: uppercase; letter-spacing: 0.14em; color: rgba(255, 255, 255, 0.72); } .login-headline { margin: 0; font: var(--type-display-1); letter-spacing: -1.5px; color: #ffffff; } .login-sub { margin: var(--space-md) 0 0; font: var(--type-body-md); color: rgba(255, 255, 255, 0.78); } .auth-card { background: var(--surface); border-radius: var(--rounded-lg); box-shadow: var(--shadow-level-2); padding: var(--space-xl); } .auth-card__title { font: var(--type-heading-2); margin-bottom: var(--space-lg); } .auth-form { display: grid; gap: var(--space-md); } .auth-error { margin: 0 0 var(--space-md); padding: var(--space-sm) var(--space-md); border: 1px solid var(--sticker-red); border-left-width: 3px; border-radius: var(--rounded-sm); color: var(--sticker-red); background: color-mix(in srgb, var(--sticker-red) 8%, var(--surface)); font: var(--type-body-sm); } .field { display: grid; gap: var(--space-xs); } .field__label { font: var(--type-eyebrow); text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-muted); } .text-input { width: 100%; min-height: 44px; padding: 10px 12px; font: var(--type-body-md); color: var(--ink); background: var(--surface); border: 1px solid #dddddd; border-radius: var(--rounded-xs); } [data-theme="dark"] .text-input { border-color: var(--hairline); } .text-input:focus { outline: none; border-color: var(--primary); box-shadow: var(--shadow-level-1), 0 0 0 3px color-mix(in srgb, var(--primary) 25%, transparent); } /* ---------- Buttons ---------- */ .button-primary, .button-utility { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 10px 20px; font: var(--type-button); cursor: pointer; transition: background 120ms ease, transform 80ms ease, box-shadow 120ms ease; } .button-primary { border: 0; border-radius: var(--rounded-full); background: var(--primary); color: var(--on-primary); } .button-primary:active { background: var(--primary-active); transform: scale(0.97); } .button-primary:focus-visible { outline: 3px solid color-mix(in srgb, var(--primary) 35%, transparent); outline-offset: 2px; } .button-utility { border: 1px solid var(--hairline); border-radius: var(--rounded-md); background: var(--surface); color: var(--ink); padding: 8px 14px; } .button-utility:hover { box-shadow: var(--shadow-level-1); } /* ---------- App shell ---------- */ .app { display: flex; flex-direction: column; min-height: 100dvh; } .nav-bar { position: sticky; top: 0; z-index: 10; display: flex; align-items: center; justify-content: space-between; gap: var(--space-md); padding: var(--space-sm) var(--space-lg); background: var(--surface); border-bottom: 1px solid var(--hairline); } .nav-bar__brand { display: inline-flex; align-items: center; gap: var(--space-xs); color: var(--ink); font: var(--type-title); } .nav-bar__brand:hover { text-decoration: none; } .nav-bar__mark { width: 12px; height: 12px; border-radius: var(--rounded-full); background: var(--primary); box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary) 18%, transparent); } .nav-bar__right { display: flex; align-items: center; gap: var(--space-md); } .nav-bar__user { font: var(--type-body-sm); color: var(--ink-muted); } .nav-bar__logout { margin: 0; } .container { width: 100%; max-width: var(--container-max); margin: 0 auto; padding: var(--space-xxl) var(--space-lg); display: grid; gap: var(--space-xxl); flex: 1; } .page-head { display: grid; gap: var(--space-xs); } .heading-1 { font: var(--type-heading-1); letter-spacing: -0.8px; } .heading-2 { font: var(--type-heading-2); letter-spacing: -0.25px; } .page-head__sub { margin: 0; color: var(--ink-muted); font: var(--type-body-md); } /* ---------- Cards ---------- */ .card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: var(--space-md); } .tool-card { background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--rounded-lg); padding: var(--space-lg); display: grid; gap: var(--space-xs); align-content: start; } .tool-card__icon { width: 40px; height: 40px; display: grid; place-items: center; border-radius: var(--rounded-full); color: #ffffff; font-size: 15px; margin-bottom: var(--space-xs); } .tool-card__icon--green { background: var(--sticker-green); } .tool-card__icon--sky { background: var(--sticker-sky); } .tool-card__icon--purple { background: var(--sticker-purple); color: var(--sticker-purple-deep); } .tool-card__icon--orange { background: var(--sticker-orange); } .tool-card__title { font: var(--type-title); } .tool-card__desc { margin: 0; color: var(--ink-muted); font: var(--type-body-sm); } .status-pill { justify-self: start; display: inline-flex; align-items: center; gap: 6px; margin-top: var(--space-xs); padding: 4px 10px; border: 1px solid var(--hairline); border-radius: var(--rounded-full); font: var(--type-eyebrow); color: var(--ink-muted); } .status-pill--on { color: var(--sticker-green); border-color: color-mix(in srgb, var(--sticker-green) 40%, var(--hairline)); } .status-pill--off { color: var(--sticker-red); border-color: color-mix(in srgb, var(--sticker-red) 40%, var(--hairline)); } .dot { width: 8px; height: 8px; border-radius: var(--rounded-full); display: inline-block; } .dot--on { background: var(--sticker-green); } .dot--off { background: var(--sticker-red); } .dot--faint { background: var(--ink-faint); } .category-pill { display: inline-flex; align-items: center; gap: 6px; padding: 4px 8px; background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--rounded-full); font: var(--type-eyebrow); color: var(--ink-muted); } /* ---------- Sections ---------- */ .section { display: grid; gap: var(--space-md); } .section__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-md); } .empty-state { background: var(--surface); border: 1px dashed var(--hairline); border-radius: var(--rounded-lg); padding: var(--space-xl); text-align: center; } .empty-state__title { margin: 0 0 var(--space-xs); font: var(--type-title); color: var(--ink); } .empty-state__body { margin: 0 auto; max-width: 52ch; color: var(--ink-muted); font: var(--type-body-sm); } /* ---------- Footer ---------- */ .app-foot, .login-foot { display: flex; align-items: center; gap: var(--space-xs); padding: var(--space-lg); color: var(--ink-faint); font: var(--type-caption); } .app-foot { justify-content: center; border-top: 1px solid var(--hairline); background: var(--surface); } .login-foot { color: rgba(255, 255, 255, 0.6); } .app-foot__sep { opacity: 0.5; } /* ---------- Flash messages ---------- */ .flash { margin: 0; padding: var(--space-sm) var(--space-md); border-radius: var(--rounded-md); border: 1px solid var(--hairline); border-left-width: 3px; font: var(--type-body-sm); } .flash--ok { color: var(--sticker-green); border-left-color: var(--sticker-green); background: color-mix(in srgb, var(--sticker-green) 8%, var(--surface)); } .flash--error { color: var(--sticker-red); border-left-color: var(--sticker-red); background: color-mix(in srgb, var(--sticker-red) 8%, var(--surface)); } /* ---------- Device cards ---------- */ .section__actions { display: flex; align-items: center; gap: var(--space-sm); } a.button-primary { text-decoration: none; } a.button-primary:hover { text-decoration: none; } .device-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: var(--space-md); } .device-card { background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--rounded-lg); padding: var(--space-lg); display: grid; gap: var(--space-sm); align-content: start; } .device-card__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-sm); } .device-card__id { min-width: 0; } .device-card__name { font: var(--type-title); } .device-card__meta { margin: 2px 0 0; color: var(--ink-muted); font: var(--type-body-sm); } .device-card__state { margin: 0; color: var(--ink); font: var(--type-body-md); } .device-card__until { margin: 0; color: var(--ink-muted); font: var(--type-caption); } .device-card__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-xs); margin-top: var(--space-xs); } .inline-form { display: flex; align-items: center; gap: var(--space-xs); margin: 0; } .inline-form .button-primary, .inline-form .button-utility { padding: 10px 16px; } .select-input { min-height: 44px; padding: 10px 12px; font: var(--type-body-sm); color: var(--ink); background: var(--surface); border: 1px solid #dddddd; border-radius: var(--rounded-md); } [data-theme="dark"] .select-input { border-color: var(--hairline); } .select-input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 25%, transparent); } .device-card__foot { margin: var(--space-xs) 0 0; display: flex; align-items: center; gap: 6px; color: var(--ink-faint); font: var(--type-caption); } .device-card__presence { display: inline-flex; align-items: center; gap: 6px; } .device-card__topic { margin: 0; color: var(--ink-faint); font: var(--type-caption); word-break: break-all; } /* ---------- Audit list ---------- */ .audit-list { list-style: none; margin: 0; padding: 0; background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--rounded-lg); overflow: hidden; } .audit-item { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-xs) var(--space-sm); padding: var(--space-sm) var(--space-md); border-top: 1px solid var(--hairline); font: var(--type-body-sm); } .audit-item:first-child { border-top: 0; } .audit-item--empty { color: var(--ink-muted); font-style: italic; } .audit-item__badge { padding: 2px 8px; border-radius: var(--rounded-full); background: var(--surface-2); color: var(--ink-muted); font: var(--type-eyebrow); white-space: nowrap; } .audit-item__body { color: var(--ink-secondary); } .audit-item__detail { color: var(--ink-muted); } .audit-item__meta { margin-left: auto; color: var(--ink-faint); font: var(--type-caption); white-space: nowrap; } /* ---------- Forms / narrow pages ---------- */ .container--narrow { max-width: 640px; } .page-head__eyebrow { margin: 0; font: var(--type-body-sm); } .page-head__eyebrow a { color: var(--ink-muted); } .card-panel { background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--rounded-lg); box-shadow: var(--shadow-level-1); padding: var(--space-xl); } .stack-form { display: grid; gap: var(--space-lg); } .fieldset, fieldset.field { border: 0; padding: 0; margin: 0; } .radio-row { display: flex; flex-wrap: wrap; gap: var(--space-sm); margin-top: var(--space-xs); } .radio-chip { display: inline-flex; align-items: center; gap: var(--space-xs); min-height: 44px; padding: 8px 16px; border: 1px solid var(--hairline); border-radius: var(--rounded-full); background: var(--surface); font: var(--type-body-md); color: var(--ink); cursor: pointer; } .radio-chip:has(input:checked) { border-color: var(--primary); box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 20%, transparent); } .radio-chip input { accent-color: var(--primary); width: 18px; height: 18px; } .form-actions { display: flex; flex-wrap: wrap; gap: var(--space-sm); align-items: center; } a.button-utility { text-decoration: none; } /* ---------- Weekly schedule editor (Phase 6) ---------- */ .visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; } .schedule-note { background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--rounded-lg); padding: var(--space-md) var(--space-lg); display: grid; gap: var(--space-xs); } .schedule-note__now { margin: 0; display: flex; align-items: center; gap: 8px; color: var(--ink); font: var(--type-body-md); } .schedule-note__next { margin: 0; color: var(--ink-muted); font: var(--type-body-sm); } .schedule-note__hint { margin: 0; color: var(--ink-muted); font: var(--type-body-sm); max-width: 70ch; } .schedule-scroll { overflow-x: auto; } .schedule-grid { width: 100%; border-collapse: collapse; min-width: 520px; } .schedule-grid th, .schedule-grid td { text-align: left; padding: var(--space-xs) var(--space-sm); border-bottom: 1px solid var(--hairline); vertical-align: middle; } .schedule-grid thead th { font: var(--type-eyebrow); text-transform: uppercase; letter-spacing: 0.08em; color: var(--ink-muted); } .schedule-grid tbody th { font: var(--type-body-md); color: var(--ink); white-space: nowrap; } .schedule-grid__slot { white-space: nowrap; } .schedule-grid__dash { padding: 0 6px; color: var(--ink-faint); } .time-input { width: auto; min-width: 120px; display: inline-block; } /* ---------- Blocklist / allowlist editor (Phase 6) ---------- */ .list-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: var(--space-md); align-items: start; } .list-panel { display: grid; gap: var(--space-sm); } .list-panel__sub { margin: 0; color: var(--ink-muted); font: var(--type-body-sm); } .list-add { display: flex; flex-wrap: wrap; gap: var(--space-xs); } .list-add .text-input { flex: 1 1 160px; min-width: 0; } .list-entries { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-xs); } .list-entry { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-xs) var(--space-sm); padding: var(--space-xs) 0; border-top: 1px solid var(--hairline); } .list-entry--empty { color: var(--ink-muted); font-style: italic; border-top: 0; } .list-entry__kind { padding: 2px 8px; border-radius: var(--rounded-full); background: var(--surface-2); color: var(--ink-muted); font: var(--type-eyebrow); } .list-entry__value { flex: 1 1 auto; word-break: break-all; } .list-entry__remove { margin: 0; } /* ---------- Responsive ---------- */ @media (max-width: 760px) { .login-band { grid-template-columns: 1fr; gap: var(--space-xl); text-align: left; } .login-headline { font: var(--type-heading-1); letter-spacing: -0.8px; } .container { padding: var(--space-lg) var(--space-md); gap: var(--space-xl); } .nav-bar { padding: var(--space-sm) var(--space-md); } .nav-bar__user { display: none; } .section__head { flex-wrap: wrap; } .audit-item__meta { margin-left: 0; width: 100%; } .list-add .button-primary { flex: 1 1 auto; } }