/* Family and instructor views: their own parts, on top of style.css (which carries the app's
   tokens and the website's design) */
.fam { max-width: 760px; margin: 0 auto; padding: calc(env(safe-area-inset-top, 0px) + 20px) 16px calc(env(safe-area-inset-bottom, 0px) + 32px); display: grid; gap: 22px; }
.fam h1 { font-size: clamp(1.8rem, 6vw, 2.4rem); }
.fam h2 { margin: 0; font-size: 1.1rem; }
.card-block { display: grid; gap: 12px; padding: 18px; border: 1px solid var(--line); border-radius: 16px; background: var(--ink-2); }
.row-between { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; }
.banner { margin: 0; padding: 12px 16px; border-radius: 12px; background: color-mix(in srgb, var(--ok) 18%, var(--ink-2)); border: 1px solid color-mix(in srgb, var(--ok) 50%, transparent); }
.banner.err { background: color-mix(in srgb, var(--bad) 18%, var(--ink-2)); border-color: color-mix(in srgb, var(--bad) 50%, transparent); }
.sample-note { margin: 0; padding: 10px 14px; border-radius: 10px; border: 1px dashed var(--warn); color: var(--warn); font-size: 0.9rem; }
.driver-pick, .goal-set, .import-row label { display: inline-flex; align-items: center; gap: 8px; color: var(--fog); font-size: 0.95rem; }
select, .goal-set input, .import-row input[type=text] { min-height: 40px; border-radius: 10px; border: 1px solid var(--line); background: var(--ink-3); color: var(--paper); padding: 6px 10px; font: inherit; }
.goal-set input { width: 4.2em; }
.weeknav { display: inline-flex; align-items: center; gap: 10px; font-weight: 700; }
.weeknav .btn { min-height: 40px; width: 44px; padding: 0; font-size: 1.2rem; margin: 0; }

.tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.tile { display: grid; gap: 2px; align-content: start; padding: 14px; border-radius: 14px; border: 1px solid var(--line); background: var(--ink-2); min-width: 0; }
.tile b { font: 700 1.6rem ui-monospace, Menlo, monospace; font-variant-numeric: tabular-nums; }
.tile.hero { grid-column: 1 / -1; }
.tile.hero b { font-size: 3.2rem; line-height: 1.05; }
.tile .sub, .tile .delta { color: var(--fog); font-size: 0.85rem; }
.delta.up::before { content: "▲ "; color: var(--ok); }
.delta.down::before { content: "▼ "; color: var(--warn); }
@media (min-width: 640px) { .tiles { grid-template-columns: 1.4fr 1fr 1fr; } .tile.hero { grid-column: 1; grid-row: span 2; } }
#dash { display: grid; gap: 22px; }
#dash[hidden] { display: none; }
/* first-paint.js: on a device that already has drives, the app draws the dashboard a moment
   after the page appears. Until its first render removes .has-data, everything below the header
   stays invisible, so nothing jumps; if the app never loads, it shows on its own after 2.5 s. */
.has-data #app > :not(.top) { visibility: hidden; animation: as-reveal 0s 2.5s forwards; }
@keyframes as-reveal { to { visibility: visible; } }

.goal-dots { display: flex; gap: 8px; }
.goal-dots span { flex: 1; height: 10px; border-radius: 5px; background: var(--ink-3); }
.goal-dots span.on { background: var(--ok); }

.chart { position: relative; }
#chart-svg { display: block; width: 100%; height: 220px; overflow: visible; }
#chart-svg .grid { stroke: var(--line); stroke-width: 1; }
#chart-svg .axis { fill: var(--fog); font: 11px ui-monospace, Menlo, monospace; }
#chart-svg .line { fill: none; stroke: var(--signal); stroke-width: 2; stroke-linejoin: round; }
#chart-svg .dot { fill: var(--signal); stroke: var(--ink-2); stroke-width: 2; }
#chart-svg .dot.hot { stroke: var(--paper); }
#chart-svg .goal { stroke: var(--fog); stroke-width: 1; stroke-dasharray: 4 4; }
#chart-svg .hit { fill: transparent; cursor: pointer; }
.tip { position: absolute; pointer-events: none; transform: translate(-50%, calc(-100% - 12px)); padding: 8px 10px; border-radius: 8px; background: var(--ink); border: 1px solid var(--line); font-size: 0.82rem; white-space: nowrap; box-shadow: 0 6px 20px rgba(0,0,0,0.35); }
.tip b { font-family: ui-monospace, Menlo, monospace; }
.table-view summary { cursor: pointer; color: var(--fog); font-size: 0.9rem; }
.table-view table { width: 100%; border-collapse: collapse; margin-top: 8px; font-size: 0.88rem; }
.table-view th, .table-view td { text-align: left; padding: 6px 4px; border-bottom: 1px solid var(--line); }
.table-view td { font-variant-numeric: tabular-nums; }

.insights, .flags { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.insights li, .flags li { padding: 10px 12px 10px 36px; border-radius: 10px; background: var(--ink-3); position: relative; line-height: 1.45; }
.insights li::before, .flags li::before { position: absolute; left: 12px; top: 10px; font-weight: 800; }
.insights li.good::before, .flags li.ok::before { content: "✓"; color: var(--ok); }
.insights li.watch::before, .flags li.flag::before { content: "!"; color: var(--warn); }
.insights li.neutral::before { content: "·"; color: var(--fog); }

.drives { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 8px; }
.drive { border: 1px solid var(--line); border-radius: 14px; background: var(--ink-2); overflow: hidden; }
.drive > button { all: unset; box-sizing: border-box; width: 100%; display: grid; grid-template-columns: 1fr auto; gap: 4px 12px; padding: 14px 16px; cursor: pointer; }
.drive > button:focus-visible { outline: 3px solid var(--signal); outline-offset: -3px; }
.drive .when { font-weight: 700; }
.drive .meta { color: var(--fog); font-size: 0.85rem; grid-column: 1; }
.drive .sc { grid-row: 1 / span 2; grid-column: 2; align-self: center; font: 700 1.6rem ui-monospace, Menlo, monospace; }
.drive .badge { display: inline-block; margin-left: 6px; padding: 1px 8px; border-radius: 999px; font-size: 0.72rem; border: 1px solid var(--line); color: var(--fog); font-weight: 600; }
.drive .badge.warn { border-color: var(--warn); color: var(--warn); }
.drive .body { padding: 0 16px 14px; display: grid; gap: 10px; }
.drive .timeline { margin-top: 4px; }
.drive .events { margin: 0; }
.drive .events li { align-items: center; }

.import-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.file-btn { position: relative; overflow: hidden; margin: 0; display: inline-flex; align-items: center; }
.file-btn input { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.fam-foot { display: grid; gap: 6px; }
.fam-foot a, .fam code { color: var(--fog); }
#replay { scroll-margin-top: 20px; }

.sync-state { font: 600 0.8rem ui-monospace, Menlo, monospace; letter-spacing: 0.05em; text-transform: uppercase; color: var(--fog); border: 1px solid var(--line); border-radius: 999px; padding: 3px 10px; }
.sync-state.on { color: var(--ok); border-color: var(--ok); }
.sync-state.err { color: var(--warn); border-color: var(--warn); }
.pair-steps { margin: 0; padding-left: 1.2em; display: grid; gap: 12px; color: var(--fog); }
.pair-row { display: flex; gap: 8px; margin-top: 6px; }
.pair-row input { flex: 1; min-width: 0; min-height: 40px; border-radius: 10px; border: 1px solid var(--line); background: var(--ink-3); color: var(--paper); padding: 6px 10px; font: 0.8rem ui-monospace, Menlo, monospace; }
.pair-row .btn { margin: 0; }

/* ---------- instructor view ---------- */
.school-title { margin: 0; font-size: clamp(1.6rem, 5vw, 2.1rem); }
.sub-h { margin: 6px 0 0; font-size: 1rem; }
.table-scroll { overflow-x: auto; margin: 0 -4px; }
.roster { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
.roster th, .roster td { text-align: left; padding: 10px 8px; border-bottom: 1px solid var(--line); vertical-align: middle; white-space: nowrap; }
.roster thead th { color: var(--fog); font-weight: 600; font-size: 0.8rem; }
.roster tbody tr { cursor: pointer; }
.roster tbody tr:hover, .roster tbody tr.sel { background: var(--ink-3); }
.roster tbody tr:focus-visible { outline: 3px solid var(--signal); outline-offset: -3px; }
.roster td.num { font-family: ui-monospace, Menlo, monospace; font-variant-numeric: tabular-nums; }
.roster td.up { color: var(--ok); }
.roster td.down { color: var(--warn); }
.roster .badge { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 0.75rem; border: 1px solid var(--line); color: var(--fog); white-space: nowrap; }
.roster .badge.warn { border-color: var(--warn); color: var(--warn); }
#student { scroll-margin-top: 16px; }

/* pilot check-in */
.survey { display: grid; gap: 14px; }
.survey-q { display: grid; gap: 8px; margin: 0; padding: 0; border: 0; color: var(--paper); font-weight: 600; font-size: 0.95rem; }
.survey-q legend { padding: 0; margin-bottom: 8px; }
.survey-q .check { display: flex; align-items: center; gap: 10px; min-height: 40px; padding: 4px 12px; border: 1px solid var(--line); border-radius: 10px; font-weight: 500; color: var(--paper); cursor: pointer; }
.survey-q .check + .check { margin-top: 6px; }
.survey-q .check:has(input:checked) { border-color: var(--signal); background: color-mix(in srgb, var(--signal) 12%, transparent); }
.survey-q textarea, .survey-q input[type=email] { min-height: 40px; border-radius: 10px; border: 1px solid var(--line); background: var(--ink-3); color: var(--paper); padding: 8px 10px; font: inherit; font-weight: 400; resize: vertical; }

/* ---------- the dashboard building itself, the first time it appears (family-page.js) ----------
   Every part ends where it always was; with reduced motion none of it runs (style.css). */
.reveal .tile { animation: as-enter 560ms cubic-bezier(0.2, 0.7, 0.2, 1) backwards; }
.reveal .tile:nth-child(2) { animation-delay: 70ms; }
.reveal .tile:nth-child(3) { animation-delay: 140ms; }
.reveal .tile:nth-child(4) { animation-delay: 210ms; }
.reveal .tile:nth-child(5) { animation-delay: 280ms; }
.reveal > .card-block, .reveal > section:not(:first-of-type) { animation: as-enter 600ms 200ms cubic-bezier(0.2, 0.7, 0.2, 1) backwards; }
@keyframes as-line { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
.reveal #chart-svg .line { stroke-dasharray: 1; animation: as-line 1400ms 350ms cubic-bezier(0.4, 0, 0.2, 1) backwards; }
@keyframes as-pop { from { opacity: 0; transform: scale(0.2); } }
.reveal #chart-svg .dot { transform-box: fill-box; transform-origin: center; animation: as-pop 420ms cubic-bezier(0.2, 0.7, 0.2, 1.3) backwards; animation-delay: calc(450ms + var(--i, 0) * 70ms); }
@keyframes as-fill { from { background: var(--ink-3); } }
.reveal .goal-dots span.on { animation: as-fill 500ms ease-out backwards; animation-delay: calc(700ms + var(--i, 0) * 160ms); }
.reveal .drive, .reveal .insights li { animation: as-enter 520ms 400ms cubic-bezier(0.2, 0.7, 0.2, 1) backwards; }
.reveal .roster tbody tr { animation: as-enter 480ms cubic-bezier(0.2, 0.7, 0.2, 1) backwards; animation-delay: calc(150ms + var(--i, 0) * 60ms); }

/* ---------- moments after that (family-page.js, instructor-page.js) ----------
   A drive just opened draws its timeline across and lists its moments in turn; a new week's
   numbers roll in; a student's panel builds in when opened; a Moment Replay eases in. */
.drive .body.opening { animation: as-enter 420ms cubic-bezier(0.2, 0.7, 0.2, 1) backwards; }
.drive .body.opening .timeline { animation: as-draw 900ms 120ms cubic-bezier(0.4, 0, 0.2, 1) backwards; }
.drive .body.opening .events li { animation: as-enter 420ms cubic-bezier(0.2, 0.7, 0.2, 1) backwards; animation-delay: 200ms; }
.drive .body.opening .events li:nth-child(2) { animation-delay: 260ms; }
.drive .body.opening .events li:nth-child(3) { animation-delay: 320ms; }
.drive .body.opening .events li:nth-child(n+4) { animation-delay: 380ms; }
@keyframes as-tick { from { opacity: 0.15; transform: translateY(8px); } }
.tick .tile b, .tick .tile .sub, .tick .tile .delta { display: inline-block; animation: as-tick 420ms cubic-bezier(0.2, 0.7, 0.2, 1) backwards; }
.tick #w-label { display: inline-block; animation: as-tick 320ms cubic-bezier(0.2, 0.7, 0.2, 1) backwards; }
.tick .drive, .tick .insights li { animation: as-enter 420ms 80ms cubic-bezier(0.2, 0.7, 0.2, 1) backwards; }
#student.opening .tile { animation: as-enter 480ms cubic-bezier(0.2, 0.7, 0.2, 1) backwards; }
#student.opening .tile:nth-child(2) { animation-delay: 60ms; }
#student.opening .tile:nth-child(3) { animation-delay: 120ms; }
#student.opening .tile:nth-child(4) { animation-delay: 180ms; }
#student.opening .drive { animation: as-enter 460ms 220ms cubic-bezier(0.2, 0.7, 0.2, 1) backwards; }
.replay:not([hidden]) { animation: as-enter 460ms cubic-bezier(0.2, 0.7, 0.2, 1); }
.tip:not([hidden]) { animation: as-tip 160ms ease-out; }
@keyframes as-tip { from { opacity: 0; } }

/* ======================= the views in the website's design =======================
   style.css carries the design for the whole app (tokens, type, buttons, the shared parts); these
   are the family and instructor views' own parts in it. */
.fam h1, .school-title { font-size: clamp(2.1rem, 7vw, 3rem); font-weight: 700; letter-spacing: -0.035em; line-height: 1.02; }
.fam h2 { font-size: 1.25rem; font-weight: 650; letter-spacing: -0.015em; }

/* cards: the site's glass, a hairline and a soft top light */
.card-block, .tile, .drive, .survey-card { background: linear-gradient(180deg, rgba(255, 255, 255, 0.045), rgba(255, 255, 255, 0.015)), var(--ink-2); border: 1px solid var(--line); border-radius: 20px; }
.card-block { padding: 22px; gap: 14px; }
.tile { padding: 16px 18px; border-radius: 18px; }
.tile.hero { background: radial-gradient(90% 120% at 100% 0%, rgba(79, 210, 255, 0.16), transparent 60%), var(--ink-2); border-color: rgba(79, 210, 255, 0.3); }
.tile b, .drive .sc { font-family: var(--font-head); font-weight: 700; font-stretch: 112%; letter-spacing: -0.04em; font-variant-numeric: tabular-nums; }
.tile b { font-size: 1.9rem; line-height: 1.1; }
.tile.hero b { font-size: 3.8rem; line-height: 1; }
.drive .sc { font-size: 1.8rem; }
.tile .sub, .tile .delta { color: var(--fog); }
.weeknav { font-family: var(--font-head); font-stretch: 108%; letter-spacing: -0.01em; }
select, .goal-set input, .import-row input[type=text], .pair-row input, .survey-q textarea, .survey-q input[type=email] { border-color: var(--line-2); }

/* notes */
.banner { border-radius: 14px; }
.sample-note { border-radius: 14px; }
.sync-state { font-family: var(--font-mono); font-weight: 500; letter-spacing: 0.1em; }

/* the goal, the chart, the lists */
.goal-dots span { height: 8px; border-radius: 8px; }
#chart-svg .axis { font-family: var(--font-mono); }
#chart-svg .line { stroke-width: 2.4; }
.tip { font-family: var(--font-body); border-radius: 10px; background: var(--ink-2); border-color: var(--line-2); }
.insights li, .flags li { background: rgba(255, 255, 255, 0.035); border: 1px solid var(--line); border-radius: 14px; }
.drive { border-radius: 18px; }
.drive .when { font-weight: 600; }
.drive .badge, .roster .badge { font-family: var(--font-mono); font-weight: 500; letter-spacing: 0.04em; }
.roster thead th { font: 500 0.7rem var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; }
.roster td.num { font-family: var(--font-mono); }
.roster tbody tr:hover, .roster tbody tr.sel { background: rgba(255, 255, 255, 0.04); }
.fam-foot { padding-top: 18px; border-top: 1px solid var(--line); }
