feat: self-host Hobbs Family Organizer (Shield TV dashboard) on hf-pdocker-02:8340
- tv app/Hobbs-Family-Organizer-Self-Hosted-v1.0.0: release bundle (Next.js app + Shield APK v1.4 + source) - compose/hf-pdocker-02/hobbs-organizer: override (local-disk secrets, watchtower off), .env (port 8340), Shield provisioning script - CLAUDE.md: service tree + internal ports Trusted-LAN mode. Secrets live only on .100 /var/lib/hobbs-organizer/secrets (not in git). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E9NnVEico3WvFxLyjy1iW3
This commit is contained in:
@@ -0,0 +1,765 @@
|
||||
@import "tailwindcss";
|
||||
@import "tw-animate-css";
|
||||
@import "../vendor/shadcn-tailwind-4.13.0.css";
|
||||
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
--background: #070b12;
|
||||
--foreground: #f8fafc;
|
||||
--card: #0c121d;
|
||||
--card-foreground: #f8fafc;
|
||||
--popover: #0c121d;
|
||||
--popover-foreground: #f8fafc;
|
||||
--primary: #a5f3fc;
|
||||
--primary-foreground: #071018;
|
||||
--secondary: #121a28;
|
||||
--secondary-foreground: #e2e8f0;
|
||||
--muted: #121a28;
|
||||
--muted-foreground: #64748b;
|
||||
--accent: #162132;
|
||||
--accent-foreground: #f8fafc;
|
||||
--destructive: #fb7185;
|
||||
--border: #ffffff12;
|
||||
--input: #ffffff16;
|
||||
--ring: #67e8f9;
|
||||
--radius: 1rem;
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-card: var(--card);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-border: var(--border);
|
||||
--color-input: var(--input);
|
||||
--color-ring: var(--ring);
|
||||
--radius-sm: calc(var(--radius) - 6px);
|
||||
--radius-md: calc(var(--radius) - 3px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 6px);
|
||||
--font-sans: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
html,
|
||||
body {
|
||||
min-height: 100%;
|
||||
margin: 0;
|
||||
background: #070b12;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow: hidden;
|
||||
color: var(--foreground);
|
||||
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
}
|
||||
|
||||
.dashboard-shell {
|
||||
position: relative;
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
height: 100vh;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
isolation: isolate;
|
||||
background:
|
||||
radial-gradient(circle at 24% 0%, rgb(34 211 238 / 7%), transparent 34%),
|
||||
radial-gradient(circle at 82% 18%, rgb(167 139 250 / 7%), transparent 30%),
|
||||
linear-gradient(145deg, #080d16 0%, #060a11 48%, #080c14 100%);
|
||||
}
|
||||
|
||||
.dashboard-shell::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: -2;
|
||||
opacity: 0.24;
|
||||
background-image:
|
||||
linear-gradient(rgb(255 255 255 / 2.4%) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgb(255 255 255 / 2.4%) 1px, transparent 1px);
|
||||
background-size: 64px 64px;
|
||||
mask-image: linear-gradient(to bottom, black, transparent 72%);
|
||||
}
|
||||
|
||||
.ambient {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
width: 34vw;
|
||||
height: 34vw;
|
||||
border-radius: 999px;
|
||||
filter: blur(120px);
|
||||
opacity: 0.08;
|
||||
animation: ambient-drift 22s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
.ambient-one { left: -14vw; top: 22vh; background: #22d3ee; }
|
||||
.ambient-two { right: -12vw; top: 10vh; background: #8b5cf6; animation-delay: -9s; }
|
||||
|
||||
.brand-mark {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 7px);
|
||||
align-items: end;
|
||||
gap: 4px;
|
||||
width: 43px;
|
||||
height: 43px;
|
||||
padding: 9px;
|
||||
border: 1px solid rgb(103 232 249 / 22%);
|
||||
border-radius: 13px;
|
||||
background: linear-gradient(145deg, rgb(103 232 249 / 13%), rgb(103 232 249 / 3%));
|
||||
box-shadow: inset 0 1px 0 rgb(255 255 255 / 8%), 0 10px 30px rgb(0 0 0 / 18%);
|
||||
}
|
||||
|
||||
.brand-mark span { display: block; border-radius: 99px; background: linear-gradient(to top, #22d3ee, #a5f3fc); }
|
||||
.brand-mark span:nth-child(1) { height: 46%; }
|
||||
.brand-mark span:nth-child(2) { height: 100%; }
|
||||
.brand-mark span:nth-child(3) { height: 72%; }
|
||||
|
||||
.panel {
|
||||
border: 1px solid rgb(255 255 255 / 8%);
|
||||
border-radius: 22px;
|
||||
padding: 20px;
|
||||
background: linear-gradient(155deg, rgb(17 25 39 / 88%), rgb(9 15 25 / 86%));
|
||||
box-shadow: inset 0 1px 0 rgb(255 255 255 / 5%), 0 24px 70px rgb(0 0 0 / 16%);
|
||||
backdrop-filter: blur(20px);
|
||||
}
|
||||
|
||||
.panel-heading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.panel-heading h2 { font-size: 1.1rem; font-weight: 800; letter-spacing: -0.02em; color: #f8fafc; }
|
||||
|
||||
.source-pill {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
border: 1px solid rgb(255 255 255 / 8%);
|
||||
border-radius: 999px;
|
||||
padding: 6px 10px;
|
||||
color: #94a3b8;
|
||||
background: rgb(255 255 255 / 3%);
|
||||
font-size: 0.66rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.09em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.source-demo { border-color: rgb(251 191 36 / 15%); color: #fde68a; background: rgb(251 191 36 / 5%); }
|
||||
|
||||
.source-live {
|
||||
border-color: rgb(52 211 153 / 18%);
|
||||
color: #a7f3d0;
|
||||
background: rgb(52 211 153 / 6%);
|
||||
}
|
||||
|
||||
.source-loading { border-color: rgb(103 232 249 / 15%); color: #a5f3fc; background: rgb(103 232 249 / 5%); }
|
||||
|
||||
.source-partial,
|
||||
.source-stale,
|
||||
.source-error {
|
||||
border-color: rgb(251 191 36 / 18%);
|
||||
color: #fde68a;
|
||||
background: rgb(251 191 36 / 6%);
|
||||
}
|
||||
|
||||
.weather-strip {
|
||||
display: grid;
|
||||
min-height: 112px;
|
||||
grid-template-columns: minmax(190px, 0.9fr) minmax(0, 5.1fr);
|
||||
gap: 9px;
|
||||
margin: 14px 24px 0;
|
||||
border: 1px solid rgb(255 255 255 / 8%);
|
||||
border-radius: 20px;
|
||||
padding: 9px;
|
||||
background: linear-gradient(105deg, rgb(34 211 238 / 6%), rgb(9 15 25 / 86%) 42%, rgb(251 191 36 / 4%));
|
||||
box-shadow: inset 0 1px 0 rgb(255 255 255 / 5%), 0 18px 50px rgb(0 0 0 / 12%);
|
||||
backdrop-filter: blur(18px);
|
||||
}
|
||||
|
||||
.weather-summary {
|
||||
min-width: 0;
|
||||
border: 1px solid rgb(103 232 249 / 12%);
|
||||
border-radius: 14px;
|
||||
padding: 10px 12px;
|
||||
background: rgb(103 232 249 / 4%);
|
||||
}
|
||||
|
||||
.weather-summary-top,
|
||||
.forecast-day-heading,
|
||||
.weather-location,
|
||||
.weather-now,
|
||||
.forecast-condition,
|
||||
.sun-times,
|
||||
.sun-times span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.weather-summary-top,
|
||||
.forecast-day-heading,
|
||||
.sun-times { justify-content: space-between; }
|
||||
|
||||
.weather-location {
|
||||
min-width: 0;
|
||||
gap: 5px;
|
||||
color: #cbd5e1;
|
||||
font-size: 0.64rem;
|
||||
font-weight: 850;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.weather-location span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
|
||||
.weather-status {
|
||||
flex: none;
|
||||
color: #6ee7b7;
|
||||
font-size: 0.54rem;
|
||||
font-weight: 850;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.weather-loading,
|
||||
.weather-stale,
|
||||
.weather-error { color: #fcd34d; }
|
||||
|
||||
.weather-now { gap: 10px; margin-top: 8px; }
|
||||
.weather-now-icon { width: 38px; height: 38px; flex: none; color: #fde68a; stroke-width: 1.65; }
|
||||
.weather-now-temp { display: flex; align-items: baseline; gap: 7px; line-height: 1; }
|
||||
.weather-now-temp span { color: #fff; font-size: 1.65rem; font-weight: 300; letter-spacing: -0.06em; }
|
||||
.weather-now-temp small { color: #64748b; font-size: 0.9rem; font-weight: 650; }
|
||||
.weather-now p { overflow: hidden; margin-top: 4px; color: #94a3b8; font-size: 0.67rem; font-weight: 650; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.weather-pending { opacity: 0.72; }
|
||||
|
||||
.forecast-grid {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
grid-template-columns: repeat(7, minmax(0, 1fr));
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.forecast-day {
|
||||
min-width: 0;
|
||||
border: 1px solid rgb(255 255 255 / 7%);
|
||||
border-radius: 12px;
|
||||
padding: 7px 8px;
|
||||
background: rgb(255 255 255 / 2.2%);
|
||||
}
|
||||
|
||||
.forecast-today {
|
||||
border-color: rgb(103 232 249 / 24%);
|
||||
background: rgb(103 232 249 / 5.5%);
|
||||
}
|
||||
|
||||
.forecast-day-heading span { color: #94a3b8; font-size: 0.59rem; font-weight: 900; letter-spacing: 0.09em; }
|
||||
.forecast-today .forecast-day-heading span { color: #a5f3fc; }
|
||||
.forecast-day-heading small { color: #475569; font-size: 0.54rem; font-weight: 700; }
|
||||
.forecast-condition { justify-content: center; gap: 8px; margin-top: 5px; }
|
||||
.forecast-icon { width: 25px; height: 25px; flex: none; color: #fde68a; stroke-width: 1.6; }
|
||||
.forecast-condition > span { display: flex; align-items: baseline; gap: 4px; }
|
||||
.forecast-condition strong { color: #f8fafc; font-size: 1rem; font-weight: 650; }
|
||||
.forecast-condition small { color: #64748b; font-size: 0.68rem; font-weight: 650; }
|
||||
.forecast-rain { margin-top: 3px; color: #64748b; font-size: 0.49rem; font-weight: 800; letter-spacing: 0.08em; text-align: center; }
|
||||
.sun-times { gap: 4px; margin-top: 5px; color: #64748b; font-size: 0.51rem; font-weight: 650; }
|
||||
.sun-times span { min-width: 0; gap: 2px; }
|
||||
.sun-times svg { width: 10px; height: 10px; flex: none; color: #fcd34d; }
|
||||
.forecast-placeholder { display: grid; align-content: center; gap: 8px; opacity: 0.45; }
|
||||
.forecast-placeholder span { height: 7px; border-radius: 999px; background: rgb(148 163 184 / 12%); }
|
||||
.forecast-placeholder span:nth-child(2) { width: 70%; }
|
||||
.forecast-placeholder span:nth-child(3) { width: 48%; }
|
||||
|
||||
.calendar-heading-actions,
|
||||
.calendar-view-tabs,
|
||||
.calendar-period-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.calendar-heading-actions { gap: 10px; }
|
||||
|
||||
.calendar-view-tabs {
|
||||
gap: 2px;
|
||||
border: 1px solid rgb(255 255 255 / 8%);
|
||||
border-radius: 999px;
|
||||
padding: 2px;
|
||||
background: rgb(255 255 255 / 3%);
|
||||
}
|
||||
|
||||
.calendar-view-tabs button {
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
padding: 5px 10px;
|
||||
color: #64748b;
|
||||
background: transparent;
|
||||
font-size: 0.62rem;
|
||||
font-weight: 850;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.calendar-view-tabs button.is-active {
|
||||
color: #cffafe;
|
||||
background: rgb(34 211 238 / 13%);
|
||||
box-shadow: inset 0 0 0 1px rgb(103 232 249 / 18%);
|
||||
}
|
||||
|
||||
.calendar-view-tabs button:focus-visible,
|
||||
.calendar-period-bar button:focus-visible,
|
||||
.week-event:focus-visible {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 2px rgb(103 232 249 / 60%), 0 0 0 5px rgb(34 211 238 / 12%);
|
||||
}
|
||||
|
||||
.calendar-view-content {
|
||||
display: flex;
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.calendar-period-bar {
|
||||
min-height: 34px;
|
||||
justify-content: flex-end;
|
||||
gap: 6px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.calendar-period-bar p {
|
||||
min-width: 150px;
|
||||
margin-right: auto;
|
||||
color: #cbd5e1;
|
||||
font-size: 0.77rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.calendar-period-bar button {
|
||||
display: grid;
|
||||
width: 30px;
|
||||
height: 28px;
|
||||
place-items: center;
|
||||
border: 1px solid rgb(255 255 255 / 9%);
|
||||
border-radius: 8px;
|
||||
color: #94a3b8;
|
||||
background: rgb(255 255 255 / 3%);
|
||||
}
|
||||
|
||||
.calendar-period-bar button svg { width: 15px; height: 15px; }
|
||||
.calendar-period-bar .calendar-today-button { width: auto; padding: 0 10px; font-size: 0.58rem; font-weight: 850; letter-spacing: 0.08em; text-transform: uppercase; }
|
||||
|
||||
.week-grid {
|
||||
display: grid;
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
grid-template-columns: repeat(7, minmax(0, 1fr));
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.week-day {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgb(255 255 255 / 7%);
|
||||
border-radius: 12px;
|
||||
padding: 7px;
|
||||
background: rgb(255 255 255 / 2%);
|
||||
}
|
||||
|
||||
.week-day.is-today { border-color: rgb(103 232 249 / 26%); background: rgb(103 232 249 / 4.5%); }
|
||||
.week-day-heading { display: flex; align-items: baseline; justify-content: space-between; border-bottom: 1px solid rgb(255 255 255 / 6%); padding-bottom: 6px; }
|
||||
.week-day-heading span { color: #64748b; font-size: 0.57rem; font-weight: 900; letter-spacing: 0.08em; }
|
||||
.week-day-heading strong { color: #cbd5e1; font-size: 0.92rem; font-weight: 500; }
|
||||
.week-day.is-today .week-day-heading span,
|
||||
.week-day.is-today .week-day-heading strong { color: #a5f3fc; }
|
||||
.week-events { display: grid; gap: 5px; margin-top: 7px; }
|
||||
.week-event { min-width: 0; border: 1px solid rgb(255 255 255 / 6%); border-left: 3px solid; border-radius: 7px; padding: 6px; background: rgb(2 6 13 / 32%); }
|
||||
.week-event strong,
|
||||
.week-event span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.week-event strong { color: #e2e8f0; font-size: 0.65rem; font-weight: 750; }
|
||||
.week-event span { margin-top: 2px; color: #64748b; font-size: 0.55rem; font-weight: 650; }
|
||||
.calendar-no-events { display: block; padding-top: 8px; color: #334155; font-size: 0.78rem; text-align: center; }
|
||||
.calendar-more { color: #67e8f9; font-size: 0.54rem; font-weight: 800; }
|
||||
|
||||
.month-grid {
|
||||
display: grid;
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
grid-template-columns: repeat(7, minmax(0, 1fr));
|
||||
grid-template-rows: auto repeat(6, minmax(0, 1fr));
|
||||
gap: 3px;
|
||||
}
|
||||
|
||||
.month-weekday { padding: 0 5px 3px; color: #475569; font-size: 0.55rem; font-weight: 900; letter-spacing: 0.1em; text-align: right; }
|
||||
.month-cell { min-width: 0; overflow: hidden; border: 1px solid rgb(255 255 255 / 6%); border-radius: 8px; padding: 4px 5px; background: rgb(255 255 255 / 1.8%); }
|
||||
.month-cell.is-outside { opacity: 0.34; }
|
||||
.month-cell.is-today { border-color: rgb(103 232 249 / 45%); background: rgb(103 232 249 / 6%); box-shadow: inset 0 0 0 1px rgb(103 232 249 / 10%); }
|
||||
.month-date { display: block; color: #94a3b8; font-size: 0.61rem; font-weight: 750; line-height: 1; text-align: right; }
|
||||
.month-cell.is-today .month-date { color: #cffafe; }
|
||||
.month-events { display: grid; gap: 2px; margin-top: 3px; }
|
||||
.month-event { display: flex; min-width: 0; align-items: center; gap: 4px; overflow: hidden; color: #cbd5e1; font-size: 0.53rem; font-weight: 650; line-height: 1.2; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.month-event span { width: 5px; height: 5px; flex: none; border-radius: 999px; }
|
||||
|
||||
.next-event-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-height: 128px;
|
||||
border: 1px solid rgb(103 232 249 / 14%);
|
||||
border-radius: 18px;
|
||||
padding: 19px 22px;
|
||||
background: linear-gradient(100deg, rgb(34 211 238 / 10%), transparent 58%), rgb(255 255 255 / 2%);
|
||||
}
|
||||
|
||||
.eyebrow { font-size: 0.66rem; font-weight: 900; letter-spacing: 0.18em; color: #64748b; }
|
||||
|
||||
.calendar-row,
|
||||
.headline-row,
|
||||
.ticker-cell {
|
||||
outline: none;
|
||||
transition: border-color 160ms ease, background-color 160ms ease, transform 160ms ease;
|
||||
}
|
||||
|
||||
.calendar-row {
|
||||
display: flex;
|
||||
min-height: 72px;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 15px;
|
||||
padding: 8px 13px;
|
||||
background: rgb(255 255 255 / 2.3%);
|
||||
}
|
||||
|
||||
.calendar-accent {
|
||||
width: 4px;
|
||||
height: 38px;
|
||||
flex: none;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.calendar-detail {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
margin-top: 2px;
|
||||
color: #64748b;
|
||||
font-size: 0.78rem;
|
||||
}
|
||||
|
||||
.calendar-dot {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
flex: none;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.calendar-empty {
|
||||
display: grid;
|
||||
min-height: 210px;
|
||||
place-items: center;
|
||||
border: 1px dashed rgb(255 255 255 / 10%);
|
||||
border-radius: 16px;
|
||||
color: #64748b;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.calendar-row:focus-visible,
|
||||
.headline-row:focus-visible,
|
||||
.ticker-cell:focus-visible {
|
||||
border-color: rgb(103 232 249 / 65%);
|
||||
background: rgb(103 232 249 / 7%);
|
||||
box-shadow: 0 0 0 3px rgb(34 211 238 / 12%);
|
||||
}
|
||||
|
||||
.calendar-row:focus-visible { transform: translateX(4px); }
|
||||
|
||||
.headline-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 13px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 12px;
|
||||
padding: 13px 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.headline-row:disabled { cursor: default; }
|
||||
|
||||
.headline-qr-cue {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
border: 1px solid rgb(196 181 253 / 16%);
|
||||
border-radius: 999px;
|
||||
padding: 2px 6px;
|
||||
color: #c4b5fd;
|
||||
background: rgb(196 181 253 / 5%);
|
||||
font-size: 0.54rem;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
.headline-row:focus-visible { transform: translateX(-3px); }
|
||||
|
||||
.pulse-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 999px;
|
||||
background: #34d399;
|
||||
box-shadow: 0 0 0 0 rgb(52 211 153 / 45%);
|
||||
animation: pulse-ring 2.4s ease-out infinite;
|
||||
}
|
||||
|
||||
.market-pulse-loading,
|
||||
.market-pulse-demo,
|
||||
.market-pulse-stale,
|
||||
.market-pulse-partial {
|
||||
background: #fbbf24;
|
||||
box-shadow: 0 0 0 0 rgb(251 191 36 / 45%);
|
||||
}
|
||||
|
||||
.ticker-window {
|
||||
overflow: hidden;
|
||||
mask-image: linear-gradient(90deg, transparent, black 3.5%, black 96.5%, transparent);
|
||||
}
|
||||
|
||||
.ticker-track { display: flex; width: max-content; animation: ticker-scroll 38s linear infinite; }
|
||||
|
||||
.ticker-cell {
|
||||
width: 290px;
|
||||
flex: none;
|
||||
border: 1px solid transparent;
|
||||
border-right-color: rgb(255 255 255 / 8%);
|
||||
padding: 4px 24px;
|
||||
}
|
||||
|
||||
.qr-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 50;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: 24px;
|
||||
background: rgb(2 6 13 / 88%);
|
||||
backdrop-filter: blur(18px);
|
||||
}
|
||||
|
||||
.qr-dialog {
|
||||
position: relative;
|
||||
display: grid;
|
||||
width: min(820px, calc(100vw - 48px));
|
||||
grid-template-columns: auto minmax(0, 1fr);
|
||||
align-items: center;
|
||||
gap: 30px;
|
||||
border: 1px solid rgb(196 181 253 / 24%);
|
||||
border-radius: 28px;
|
||||
padding: 26px;
|
||||
background:
|
||||
radial-gradient(circle at 12% 16%, rgb(34 211 238 / 10%), transparent 38%),
|
||||
linear-gradient(145deg, #111a2a, #090f1a);
|
||||
box-shadow: 0 36px 120px rgb(0 0 0 / 60%), inset 0 1px 0 rgb(255 255 255 / 7%);
|
||||
}
|
||||
|
||||
.qr-code-frame {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: 20px;
|
||||
padding: 17px;
|
||||
background: #fff;
|
||||
box-shadow: 0 18px 55px rgb(34 211 238 / 14%);
|
||||
}
|
||||
|
||||
.qr-code-frame svg { display: block; width: 264px; height: 264px; }
|
||||
|
||||
.qr-copy { min-width: 0; padding-right: 8px; }
|
||||
|
||||
.qr-source {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: #c4b5fd;
|
||||
font-size: 0.66rem;
|
||||
font-weight: 900;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.qr-source span { color: #475569; }
|
||||
|
||||
.qr-copy h2 {
|
||||
margin: 12px 0 10px;
|
||||
color: #fff;
|
||||
font-size: 1.65rem;
|
||||
font-weight: 750;
|
||||
line-height: 1.16;
|
||||
letter-spacing: -0.035em;
|
||||
}
|
||||
|
||||
.qr-copy p { margin: 0; color: #94a3b8; font-size: 0.92rem; line-height: 1.55; }
|
||||
|
||||
.qr-close {
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
right: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
border: 1px solid rgb(255 255 255 / 10%);
|
||||
border-radius: 999px;
|
||||
padding: 7px 11px;
|
||||
color: #cbd5e1;
|
||||
background: rgb(255 255 255 / 5%);
|
||||
font-size: 0.7rem;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.qr-close:focus-visible {
|
||||
outline: none;
|
||||
border-color: rgb(103 232 249 / 70%);
|
||||
box-shadow: 0 0 0 4px rgb(34 211 238 / 14%);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@keyframes ticker-scroll { to { transform: translateX(-50%); } }
|
||||
@keyframes pulse-ring { 70% { box-shadow: 0 0 0 8px rgb(52 211 153 / 0%); } 100% { box-shadow: 0 0 0 0 rgb(52 211 153 / 0%); } }
|
||||
@keyframes ambient-drift { from { transform: translate3d(0, -2%, 0) scale(0.96); } to { transform: translate3d(5%, 5%, 0) scale(1.07); } }
|
||||
|
||||
@media (max-width: 1280px) {
|
||||
.dashboard-shell { display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: 60px 86px minmax(0, 1fr) 56px; }
|
||||
.dashboard-header { min-height: 60px; padding: 7px 14px; }
|
||||
.brand-group { gap: 11px; }
|
||||
.brand-mark { width: 35px; height: 35px; padding: 7px; border-radius: 11px; }
|
||||
.weather-strip { min-height: 0; margin: 5px 11px 0; gap: 5px; border-radius: 14px; padding: 5px; }
|
||||
.weather-summary { border-radius: 10px; padding: 5px 8px; }
|
||||
.weather-location { gap: 3px; font-size: 0.51rem; }
|
||||
.weather-location svg { width: 10px; height: 10px; }
|
||||
.weather-status { font-size: 0.45rem; }
|
||||
.weather-now { gap: 6px; margin-top: 4px; }
|
||||
.weather-now-icon { width: 27px; height: 27px; }
|
||||
.weather-now-temp { gap: 4px; }
|
||||
.weather-now-temp span { font-size: 1.15rem; }
|
||||
.weather-now-temp small { font-size: 0.66rem; }
|
||||
.weather-now p { margin-top: 2px; font-size: 0.52rem; }
|
||||
.forecast-grid { gap: 4px; }
|
||||
.forecast-day { border-radius: 9px; padding: 3px 5px; }
|
||||
.forecast-day-heading span { font-size: 0.48rem; }
|
||||
.forecast-day-heading small { font-size: 0.44rem; }
|
||||
.forecast-condition { gap: 4px; margin-top: 2px; }
|
||||
.forecast-icon { width: 17px; height: 17px; }
|
||||
.forecast-condition > span { gap: 3px; }
|
||||
.forecast-condition strong { font-size: 0.76rem; }
|
||||
.forecast-condition small { font-size: 0.53rem; }
|
||||
.forecast-rain { margin-top: 1px; font-size: 0.4rem; }
|
||||
.sun-times { gap: 2px; margin-top: 2px; font-size: 0.43rem; }
|
||||
.sun-times svg { width: 8px; height: 8px; }
|
||||
.dashboard-grid { grid-template-columns: minmax(0, 1.6fr) minmax(310px, 0.9fr); gap: 8px; padding: 7px 11px; }
|
||||
.panel { padding: 10px; border-radius: 16px; }
|
||||
.panel-heading { margin-bottom: 7px; }
|
||||
.panel-heading h2 { font-size: 0.96rem; }
|
||||
.source-pill { gap: 5px; padding: 4px 8px; font-size: 0.57rem; }
|
||||
.calendar-heading-actions { gap: 6px; }
|
||||
.calendar-view-tabs button { padding: 4px 7px; font-size: 0.51rem; }
|
||||
.calendar-period-bar { min-height: 25px; gap: 4px; margin-bottom: 5px; }
|
||||
.calendar-period-bar p { min-width: 120px; font-size: 0.59rem; }
|
||||
.calendar-period-bar button { width: 25px; height: 23px; border-radius: 6px; }
|
||||
.calendar-period-bar button svg { width: 13px; height: 13px; }
|
||||
.calendar-period-bar .calendar-today-button { padding-inline: 7px; font-size: 0.48rem; }
|
||||
.next-event-card { min-height: 66px; padding: 7px 11px; border-radius: 13px; }
|
||||
.next-event-title { margin-top: 3px; font-size: 1.22rem; }
|
||||
.next-event-meta { margin-top: 1px; font-size: 0.73rem; }
|
||||
.next-event-countdown { padding-left: 12px; }
|
||||
.next-event-countdown > p:first-child { font-size: 1.45rem; }
|
||||
.next-event-countdown > p:last-child { margin-top: 0; font-size: 0.56rem; }
|
||||
.eyebrow { font-size: 0.55rem; }
|
||||
.event-list { margin-top: 7px; }
|
||||
.event-list-heading { margin-bottom: 4px; }
|
||||
.event-list-heading > p:last-child { font-size: 0.62rem; }
|
||||
.event-list-grid { gap: 4px; }
|
||||
.calendar-row { min-height: 43px; gap: 7px; border-radius: 10px; padding: 3px 7px; }
|
||||
.calendar-date { width: 53px; padding-right: 7px; }
|
||||
.calendar-day { font-size: 0.51rem; }
|
||||
.calendar-date-number { margin-top: 0; font-size: 1.12rem; line-height: 1.05; }
|
||||
.calendar-accent { width: 3px; height: 25px; }
|
||||
.calendar-event-title { font-size: 0.83rem; }
|
||||
.calendar-event-time { font-size: 0.69rem; }
|
||||
.calendar-detail { gap: 4px; margin-top: 0; font-size: 0.62rem; }
|
||||
.calendar-dot { width: 5px; height: 5px; }
|
||||
.week-grid { gap: 4px; }
|
||||
.week-day { border-radius: 9px; padding: 5px; }
|
||||
.week-day-heading { padding-bottom: 4px; }
|
||||
.week-day-heading span { font-size: 0.47rem; }
|
||||
.week-day-heading strong { font-size: 0.72rem; }
|
||||
.week-events { gap: 4px; margin-top: 5px; }
|
||||
.week-event { border-radius: 6px; padding: 4px; }
|
||||
.week-event strong { font-size: 0.55rem; }
|
||||
.week-event span { margin-top: 1px; font-size: 0.47rem; }
|
||||
.calendar-more { font-size: 0.47rem; }
|
||||
.month-grid { gap: 2px; }
|
||||
.month-weekday { padding: 0 3px 2px; font-size: 0.45rem; }
|
||||
.month-cell { border-radius: 6px; padding: 3px 4px; }
|
||||
.month-date { font-size: 0.5rem; }
|
||||
.month-events { gap: 1px; margin-top: 2px; }
|
||||
.month-event { gap: 3px; font-size: 0.44rem; }
|
||||
.month-event span { width: 4px; height: 4px; }
|
||||
.headline-row { gap: 8px; padding: 5px 6px; border-radius: 9px; }
|
||||
.headline-row > div:first-child { width: 7px; height: 7px; }
|
||||
.headline-row h3 { margin-top: 3px; font-size: 0.79rem; line-height: 1.2; }
|
||||
.headline-row:first-child h3 { font-size: 0.87rem; }
|
||||
.headline-qr-cue { padding: 1px 5px; font-size: 0.48rem; }
|
||||
.phone-handoff { margin-top: 6px; padding: 7px 10px; border-radius: 12px; }
|
||||
.phone-handoff p:first-child { font-size: 0.76rem; }
|
||||
.phone-handoff p:last-child { font-size: 0.64rem; }
|
||||
.dashboard-footer { overflow: hidden; padding-block: 2px; }
|
||||
.footer-meta { min-height: 14px; margin-bottom: 0; padding-inline: 14px; line-height: 1; }
|
||||
.ticker-cell { display: flex; width: 224px; height: 36px; flex-direction: column; justify-content: center; padding: 0 16px; }
|
||||
.ticker-cell > div:first-child { min-height: 11px; line-height: 1; }
|
||||
.ticker-cell > div:nth-child(2) { min-height: 18px; margin-top: 1px; line-height: 1; }
|
||||
.quote-symbol { font-size: 0.63rem; line-height: 1; }
|
||||
.quote-name { font-size: 0.58rem; line-height: 1; }
|
||||
.quote-value { font-size: 0.96rem; line-height: 1; }
|
||||
.quote-move { font-size: 0.68rem; line-height: 1; }
|
||||
.quote-move svg { width: 12px; height: 12px; }
|
||||
.qr-dialog { width: min(720px, calc(100vw - 28px)); gap: 20px; border-radius: 20px; padding: 18px; }
|
||||
.qr-code-frame { border-radius: 14px; padding: 12px; }
|
||||
.qr-code-frame svg { width: 220px; height: 220px; }
|
||||
.qr-copy h2 { margin-block: 8px; font-size: 1.22rem; }
|
||||
.qr-copy p { font-size: 0.72rem; line-height: 1.42; }
|
||||
.qr-source { gap: 6px; font-size: 0.56rem; }
|
||||
.qr-close { top: 9px; right: 9px; padding: 5px 8px; font-size: 0.62rem; }
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
body { overflow: auto; }
|
||||
.dashboard-shell { display: flex; height: auto; min-height: 100vh; overflow: visible; }
|
||||
.dashboard-shell > section { grid-template-columns: 1fr; }
|
||||
.weather-strip { min-height: 208px; margin: 10px; }
|
||||
.weather-summary { min-height: 70px; }
|
||||
.forecast-grid { grid-template-columns: repeat(7, minmax(76px, 1fr)); overflow-x: auto; }
|
||||
.panel { min-height: 560px; }
|
||||
.qr-dialog { grid-template-columns: 1fr; text-align: center; }
|
||||
.qr-code-frame { width: max-content; margin: 0 auto; }
|
||||
.qr-copy { padding: 0; }
|
||||
.qr-source { justify-content: center; }
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.ticker-track,
|
||||
.pulse-dot,
|
||||
.ambient { animation: none; }
|
||||
}
|
||||
Reference in New Issue
Block a user