/* ============================================================
   qtracker.css — the Q-Tracker family hub
   ============================================================

   Built for a screen that stays on: a wall tablet or a TV in the
   kitchen, viewed from a metre or more away and operated with a
   thumb. Three rules follow from that and are applied everywhere:

     1. Nothing depends on hover. Hover states exist, but every
        piece of information and every affordance is visible
        without one.
     2. No tap target below 56px. The counters and toggles that
        get hit dozens of times a day are 64px.
     3. Type is one step larger than a desktop app would use, and
        the family view is larger again so it reads across a room.

   Dark by default — a bright panel on a wall at night is not
   welcome — with a light scheme for daytime tablets.
   ============================================================ */

:root {
    /* Spacing: a 4px base, but the rhythm starts higher than a
       pointer-driven UI would. */
    --qt-1: 4px;
    --qt-2: 8px;
    --qt-3: 14px;
    --qt-4: 20px;
    --qt-5: 28px;
    --qt-6: 40px;
    --qt-7: 56px;

    --qt-tap: 56px;          /* floor for anything tappable */
    --qt-tap-lg: 64px;       /* counters, toggles, primary actions */
    --qt-rail-w: 116px;
    --qt-tabbar-h: 76px;
    --qt-radius: 18px;
    --qt-radius-sm: 12px;

    --qt-text-xs: 0.85rem;
    --qt-text-sm: 0.95rem;
    --qt-text-base: 1.06rem;
    --qt-text-lg: 1.3rem;
    --qt-text-xl: 1.7rem;
    --qt-text-2xl: 2.3rem;
    --qt-text-3xl: 3.4rem;

    /* Dark scheme (default) */
    --qt-canvas: #0b0f1c;
    --qt-surface: #151b30;
    --qt-surface-2: #1d2440;
    --qt-inset: #0f1425;
    --qt-line: #2a3352;
    --qt-line-soft: #212942;
    --qt-ink: #eef1fb;
    --qt-ink-soft: #b9c1dd;
    --qt-ink-muted: #8892b4;
    --qt-accent: #6366f1;
    --qt-accent-soft: rgba(99, 102, 241, .18);
    --qt-accent-ink: #ffffff;
    --qt-ok: #22c55e;
    --qt-ok-soft: rgba(34, 197, 94, .16);
    --qt-warn: #f59e0b;
    --qt-warn-soft: rgba(245, 158, 11, .16);
    --qt-bad: #ef4444;
    --qt-bad-soft: rgba(239, 68, 68, .16);
    --qt-shadow: 0 10px 30px rgba(0, 0, 0, .35);
}

/* Daytime scheme. Opt-in via the Setup page, stored in localStorage
   and applied by qtracker.js before first paint. */
body.qt[data-qt-scheme="light"] {
    --qt-canvas: #f4f6fc;
    --qt-surface: #ffffff;
    --qt-surface-2: #eef1f9;
    --qt-inset: #e8ecf7;
    --qt-line: #d5dcee;
    --qt-line-soft: #e4e9f5;
    --qt-ink: #131829;
    --qt-ink-soft: #3d4665;
    --qt-ink-muted: #6b7699;
    --qt-accent-soft: rgba(99, 102, 241, .12);
    --qt-shadow: 0 10px 30px rgba(23, 31, 56, .12);
}

/* ------------------------------------------------------------
   Base
   ------------------------------------------------------------ */
* { box-sizing: border-box; }

body.qt {
    margin: 0;
    background: var(--qt-canvas);
    color: var(--qt-ink);
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    font-size: var(--qt-text-base);
    line-height: 1.45;
    -webkit-text-size-adjust: 100%;
    /* A wall panel should never rubber-band or offer a text cursor. */
    -webkit-tap-highlight-color: transparent;
    overscroll-behavior-y: none;
}

.qt h1, .qt h2, .qt h3 { margin: 0; line-height: 1.2; }
.qt p { margin: 0; }
.qt a { color: inherit; text-decoration: none; }
.qt img { max-width: 100%; display: block; }

.qt-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;
}

/* ------------------------------------------------------------
   App frame
   ------------------------------------------------------------ */
.qt-app {
    display: grid;
    grid-template-columns: var(--qt-rail-w) minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
    grid-template-areas:
        "top  top"
        "rail main";
    min-height: 100vh;
    min-height: 100dvh;
}

.qt-topbar {
    grid-area: top;
    display: flex;
    align-items: center;
    gap: var(--qt-4);
    padding: var(--qt-3) var(--qt-4);
    background: var(--qt-surface);
    border-bottom: 1px solid var(--qt-line);
}

.qt-brand { display: flex; align-items: center; gap: var(--qt-3); min-width: 0; }
.qt-brand__mark {
    display: grid; place-items: center;
    width: 46px; height: 46px;
    border-radius: 14px;
    background: linear-gradient(135deg, var(--qt-accent), #a855f7);
    color: #fff; font-weight: 900; font-size: 1.4rem;
}
.qt-brand__text { display: grid; min-width: 0; }
.qt-brand__name {
    font-weight: 800; font-size: var(--qt-text-lg);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.qt-brand__sub {
    font-size: var(--qt-text-xs); color: var(--qt-ink-muted);
    letter-spacing: .08em; text-transform: uppercase; font-weight: 700;
}

/* The clock is the reason a wall panel earns its place. */
.qt-clock { margin-inline: auto; text-align: center; line-height: 1.05; }
.qt-clock__time {
    display: block;
    font-size: var(--qt-text-2xl); font-weight: 800;
    font-variant-numeric: tabular-nums;
}
.qt-clock__date {
    display: block;
    font-size: var(--qt-text-sm); color: var(--qt-ink-muted); font-weight: 600;
}

.qt-topbar__tools { display: flex; align-items: center; gap: var(--qt-2); }

/* ------------------------------------------------------------
   Navigation
   ------------------------------------------------------------ */
.qt-rail {
    grid-area: rail;
    display: flex; flex-direction: column; gap: var(--qt-2);
    padding: var(--qt-3) var(--qt-2);
    background: var(--qt-surface);
    border-right: 1px solid var(--qt-line);
}
.qt-rail__link {
    display: grid; gap: 6px; place-items: center;
    min-height: var(--qt-tap-lg);
    padding: var(--qt-3) var(--qt-1);
    border-radius: var(--qt-radius-sm);
    color: var(--qt-ink-muted);
    transition: background-color .15s, color .15s;
}
.qt-rail__link:hover { background: var(--qt-surface-2); color: var(--qt-ink); }
.qt-rail__link.is-active { background: var(--qt-accent); color: var(--qt-accent-ink); }
.qt-rail__icon { font-size: 1.7rem; line-height: 1; }
.qt-rail__label { font-size: var(--qt-text-xs); font-weight: 800; }

.qt-tabbar {
    position: fixed; inset-inline: 0; bottom: 0; z-index: 40;
    display: none;
    grid-auto-flow: column; grid-auto-columns: 1fr;
    padding: var(--qt-2) var(--qt-2) calc(var(--qt-2) + env(safe-area-inset-bottom, 0px));
    background: var(--qt-surface);
    border-top: 1px solid var(--qt-line);
}
.qt-tabbar__link {
    display: grid; gap: 3px; place-items: center;
    min-height: var(--qt-tap);
    border-radius: var(--qt-radius-sm);
    color: var(--qt-ink-muted); font-size: 1.4rem;
}
.qt-tabbar__link.is-active { background: var(--qt-accent-soft); color: var(--qt-ink); }
.qt-tabbar__label { font-size: 11px; font-weight: 800; }

.qt-main {
    grid-area: main;
    min-width: 0;
    padding: var(--qt-4);
    display: flex; flex-direction: column; gap: var(--qt-4);
}

/* ------------------------------------------------------------
   Buttons — the floor is 56px, everywhere
   ------------------------------------------------------------ */
.qt-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--qt-2);
    min-height: var(--qt-tap);
    padding: 0 var(--qt-4);
    border: 1px solid transparent;
    border-radius: var(--qt-radius-sm);
    background: var(--qt-surface-2);
    color: var(--qt-ink);
    font: inherit; font-weight: 700;
    cursor: pointer;
    transition: transform .08s, background-color .15s, border-color .15s;
    user-select: none;
}
.qt-btn:active { transform: scale(.97); }
.qt-btn--primary { background: var(--qt-accent); color: var(--qt-accent-ink); }
.qt-btn--ok { background: var(--qt-ok); color: #06210f; }
.qt-btn--bad { background: var(--qt-bad); color: #fff; }
.qt-btn--warn { background: var(--qt-warn); color: #2a1a00; }
.qt-btn--ghost { background: transparent; border-color: var(--qt-line); color: var(--qt-ink-soft); }
.qt-btn--ghost:hover { background: var(--qt-surface-2); color: var(--qt-ink); }
.qt-btn--lg { min-height: var(--qt-tap-lg); font-size: var(--qt-text-lg); padding: 0 var(--qt-5); }
.qt-btn--icon { padding: 0; width: var(--qt-tap); }
.qt-btn[disabled] { opacity: .45; pointer-events: none; }

.qt-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 8px var(--qt-3);
    border-radius: 999px;
    background: var(--qt-surface-2);
    font-size: var(--qt-text-sm); font-weight: 700;
}
.qt-chip--ok   { background: var(--qt-ok-soft);   color: var(--qt-ok); }
.qt-chip--warn { background: var(--qt-warn-soft); color: var(--qt-warn); }
.qt-chip--bad  { background: var(--qt-bad-soft);  color: var(--qt-bad); }

/* ------------------------------------------------------------
   Surfaces
   ------------------------------------------------------------ */
.qt-card {
    background: var(--qt-surface);
    border: 1px solid var(--qt-line);
    border-radius: var(--qt-radius);
    box-shadow: var(--qt-shadow);
    overflow: hidden;
}
.qt-card__head {
    display: flex; align-items: center; gap: var(--qt-3);
    padding: var(--qt-3) var(--qt-4);
    border-bottom: 1px solid var(--qt-line-soft);
}
.qt-card__title { font-size: var(--qt-text-lg); font-weight: 800; }
.qt-card__tools { margin-inline-start: auto; display: flex; gap: var(--qt-2); }
.qt-card__body { padding: var(--qt-4); display: flex; flex-direction: column; gap: var(--qt-3); }

.qt-pagehead {
    display: flex; align-items: flex-end; gap: var(--qt-4); flex-wrap: wrap;
}
.qt-pagehead__title { font-size: var(--qt-text-2xl); font-weight: 900; }
.qt-pagehead__sub { color: var(--qt-ink-muted); font-size: var(--qt-text-sm); }
.qt-pagehead__actions { margin-inline-start: auto; display: flex; gap: var(--qt-2); flex-wrap: wrap; }

.qt-grid { display: grid; gap: var(--qt-4); }
.qt-grid--2 { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }
.qt-grid--3 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }

.qt-alert {
    display: flex; align-items: center; gap: var(--qt-3);
    padding: var(--qt-3) var(--qt-4);
    border-radius: var(--qt-radius-sm);
    border: 1px solid var(--qt-line);
    background: var(--qt-surface);
    font-weight: 600;
}
.qt-alert--ok   { border-color: var(--qt-ok);   background: var(--qt-ok-soft); }
.qt-alert--bad  { border-color: var(--qt-bad);  background: var(--qt-bad-soft); }
.qt-alert--warn { border-color: var(--qt-warn); background: var(--qt-warn-soft); }

/* The seconds left on a self-dismissing confirmation. Pushed to the far end
   and tabular so the digits do not shuffle as it counts down. */
.qt-alert__countdown {
    margin-inline-start: auto;
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
    font-size: var(--qt-text-sm);
    opacity: .65;
}

/* Fades and collapses together, so the page closes the gap rather than
   leaving a hole where the band was. */
.qt-alert[data-qt-autodismiss] {
    transition: opacity .35s ease, margin .35s ease, padding .35s ease,
                max-height .35s ease, border-width .35s ease;
    max-height: 12rem;
    overflow: hidden;
}
.qt-alert.is-going {
    opacity: 0;
    max-height: 0;
    padding-block: 0;
    margin-block: 0;
    border-width: 0;
}

/* Someone who asked for less motion gets the dismissal without the animation. */
@media (prefers-reduced-motion: reduce) {
    .qt-alert[data-qt-autodismiss] { transition: none; }
}

.qt-empty {
    display: grid; gap: var(--qt-2); place-items: center;
    padding: var(--qt-6) var(--qt-4);
    text-align: center; color: var(--qt-ink-muted);
}
.qt-empty__icon { font-size: 3rem; }
.qt-empty__title { font-size: var(--qt-text-lg); font-weight: 800; color: var(--qt-ink); }

.qt-muted { color: var(--qt-ink-muted); }
.qt-tiny  { font-size: var(--qt-text-sm); }

/* ------------------------------------------------------------
   Avatars & child colour coding
   ------------------------------------------------------------ */
.qt-avatar {
    display: inline-grid; place-items: center;
    width: 44px; height: 44px; flex: 0 0 44px;
    border-radius: 999px;
    background: var(--qt-avatar-color, var(--qt-accent));
    color: #fff; font-weight: 900; font-size: var(--qt-text-base);
    box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .18);
}
.qt-avatar--lg { width: 64px; height: 64px; flex-basis: 64px; font-size: var(--qt-text-xl); }
.qt-avatar--sm { width: 32px; height: 32px; flex-basis: 32px; font-size: var(--qt-text-sm); }

/* ------------------------------------------------------------
   Forms
   ------------------------------------------------------------ */
.qt-field { display: grid; gap: 6px; }
.qt-field__label { font-size: var(--qt-text-sm); font-weight: 800; color: var(--qt-ink-soft); }
.qt-input, .qt-select, .qt-textarea {
    width: 100%;
    min-height: var(--qt-tap);
    padding: var(--qt-2) var(--qt-3);
    border: 1px solid var(--qt-line);
    border-radius: var(--qt-radius-sm);
    background: var(--qt-inset);
    color: var(--qt-ink);
    font: inherit;
}
.qt-textarea { min-height: 110px; padding-top: var(--qt-3); resize: vertical; }
.qt-input:focus, .qt-select:focus, .qt-textarea:focus {
    outline: 3px solid var(--qt-accent-soft);
    border-color: var(--qt-accent);
}
.qt-form-row { display: flex; gap: var(--qt-3); flex-wrap: wrap; }
.qt-form-row > * { flex: 1 1 220px; }

/* Colour-swatch radio group, used to pick a child's highlight. */
.qt-swatches { display: flex; gap: var(--qt-2); flex-wrap: wrap; }
.qt-swatch { position: relative; }
.qt-swatch input { position: absolute; opacity: 0; inset: 0; }
.qt-swatch span {
    display: block; width: 44px; height: 44px;
    border-radius: 999px; cursor: pointer;
    box-shadow: inset 0 0 0 3px rgba(255, 255, 255, .2);
}
.qt-swatch input:checked + span { box-shadow: 0 0 0 3px var(--qt-ink), inset 0 0 0 3px rgba(255,255,255,.35); }

/* ------------------------------------------------------------
   Trackers
   ------------------------------------------------------------ */
.qt-tracker { display: flex; flex-direction: column; }
.qt-tracker__head {
    display: flex; align-items: center; gap: var(--qt-3);
    padding: var(--qt-3) var(--qt-4);
    border-bottom: 1px solid var(--qt-line-soft);
}
.qt-tracker__icon { font-size: 1.8rem; }
.qt-tracker__title { font-size: var(--qt-text-lg); font-weight: 800; }
.qt-tracker__reset {
    font-size: var(--qt-text-xs); font-weight: 700;
    color: var(--qt-ink-muted); text-transform: uppercase; letter-spacing: .05em;
}
.qt-tracker__progress {
    margin-inline-start: auto;
    display: grid; place-items: center; gap: 2px;
}
.qt-tracker__pct { font-size: var(--qt-text-lg); font-weight: 900; font-variant-numeric: tabular-nums; }

.qt-bar { height: 8px; border-radius: 999px; background: var(--qt-inset); overflow: hidden; }
.qt-bar__fill { height: 100%; background: var(--qt-ok); border-radius: 999px; transition: width .3s; }

.qt-items { display: flex; flex-direction: column; }
.qt-item {
    display: flex; align-items: center; gap: var(--qt-3);
    padding: var(--qt-3) var(--qt-4);
    border-bottom: 1px solid var(--qt-line-soft);
}
.qt-item:last-child { border-bottom: none; }
.qt-item__main { min-width: 0; flex: 1 1 auto; }
.qt-item__label { font-size: var(--qt-text-lg); font-weight: 700; }
.qt-item__meta { font-size: var(--qt-text-sm); color: var(--qt-ink-muted); }
.qt-item.is-done .qt-item__label { color: var(--qt-ink-muted); text-decoration: line-through; }

/* The two item types. Both are built to be hit repeatedly with a thumb. */
.qt-toggle {
    display: grid; place-items: center;
    width: var(--qt-tap-lg); height: var(--qt-tap-lg);
    flex: 0 0 var(--qt-tap-lg);
    border: 3px solid var(--qt-line);
    border-radius: 999px;
    background: var(--qt-inset);
    color: transparent;
    font-size: 1.8rem; font-weight: 900;
    cursor: pointer;
    transition: transform .1s, background-color .15s, border-color .15s, color .15s;
}
.qt-toggle:active { transform: scale(.92); }
.qt-toggle.is-on {
    background: var(--qt-ok); border-color: var(--qt-ok); color: #06210f;
}

.qt-counter { display: flex; align-items: center; gap: var(--qt-2); flex: 0 0 auto; }
.qt-counter__btn {
    display: grid; place-items: center;
    width: var(--qt-tap-lg); height: var(--qt-tap-lg);
    border: 1px solid var(--qt-line);
    border-radius: 999px;
    background: var(--qt-surface-2);
    color: var(--qt-ink);
    font-size: 2rem; font-weight: 800; line-height: 1;
    cursor: pointer;
    transition: transform .08s, background-color .15s;
}
.qt-counter__btn:active { transform: scale(.9); }
.qt-counter__btn--plus { background: var(--qt-accent); color: var(--qt-accent-ink); border-color: transparent; }
.qt-counter__value {
    min-width: 84px; text-align: center;
    font-size: var(--qt-text-xl); font-weight: 900;
    font-variant-numeric: tabular-nums;
}
.qt-counter__value small { display: block; font-size: var(--qt-text-xs); color: var(--qt-ink-muted); font-weight: 700; }
.qt-counter.is-met .qt-counter__value { color: var(--qt-ok); }

/* ------------------------------------------------------------
   Calendar & Screen-Responsive Layout
   ------------------------------------------------------------ */

/* When on the calendar page, lock the viewport so everything fits within 100dvh without outer window scroll */
body.qt[data-qt-page="calendar"] {
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
}
body.qt[data-qt-page="calendar"] .qt-app {
    height: 100vh;
    height: 100dvh;
    max-height: 100dvh;
    overflow: hidden;
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
}
body.qt[data-qt-page="calendar"] .qt-main {
    height: 100%;
    max-height: 100%;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding: var(--qt-3) var(--qt-4);
    gap: var(--qt-2);
}

.qt-cal-toolbar {
    display: flex;
    align-items: center;
    gap: var(--qt-2);
    flex-wrap: wrap;
    flex: 0 0 auto;
    min-height: 44px;
}
.qt-cal-toolbar__nav {
    display: flex;
    align-items: center;
    gap: var(--qt-2);
    flex-wrap: wrap;
}
.qt-cal-toolbar__title {
    font-size: clamp(1.15rem, 1.8vw, 1.45rem);
    font-weight: 900;
    letter-spacing: -0.01em;
    min-width: 160px;
}
.qt-cal-toolbar__actions {
    margin-inline-start: auto;
    display: flex;
    gap: var(--qt-2);
    flex-wrap: wrap;
    align-items: center;
}

.qt-segmented {
    display: inline-flex;
    gap: 2px;
    padding: 3px;
    background: var(--qt-inset);
    border-radius: 999px;
}
.qt-segmented a {
    display: grid;
    place-items: center;
    min-height: 40px;
    padding: 0 var(--qt-3);
    border-radius: 999px;
    font-weight: 800;
    font-size: var(--qt-text-sm);
    color: var(--qt-ink-muted);
    transition: background-color .15s, color .15s;
}
.qt-segmented a.is-active {
    background: var(--qt-accent);
    color: var(--qt-accent-ink);
}

/* Card container for calendar view */
.qt-card--calendar {
    flex: 1 1 auto;
    min-height: 0;
    height: 100%;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* Month grid: dynamic 1fr row distribution per week */
.qt-month {
    flex: 1 1 auto;
    min-height: 0;
    height: 100%;
    width: 100%;
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    grid-template-rows: auto repeat(var(--qt-month-weeks, 5), minmax(0, 1fr));
    gap: 1px;
    background: var(--qt-line-soft);
}
.qt-month__dow {
    padding: clamp(3px, 0.6vh, 6px) var(--qt-1);
    text-align: center;
    background: var(--qt-surface-2);
    font-size: clamp(0.68rem, 1vw, 0.8rem);
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--qt-ink-muted);
    display: flex;
    align-items: center;
    justify-content: center;
}
.qt-day {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-height: 0;
    height: 100%;
    padding: clamp(3px, 0.6vh, 6px);
    background: var(--qt-surface);
    text-align: start;
    border: none;
    font: inherit;
    color: inherit;
    cursor: pointer;
    overflow: hidden;
    position: relative;
    transition: background-color .12s;
}
.qt-day:hover {
    background: var(--qt-surface-2);
}
.qt-day.is-outside {
    background: var(--qt-inset);
    color: var(--qt-ink-muted);
    opacity: 0.75;
}
.qt-day.is-today {
    box-shadow: inset 0 0 0 2px var(--qt-accent);
}
.qt-day__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    flex: 0 0 auto;
    margin-bottom: 1px;
}
.qt-day__n {
    font-weight: 800;
    font-size: clamp(0.78rem, 1.2vh, 0.95rem);
    line-height: 1;
}
.qt-day.is-today .qt-day__n {
    color: var(--qt-accent);
}
.qt-day__events {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-height: 0;
    flex: 1 1 auto;
    overflow: hidden;
}
.qt-pill {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: clamp(1px, 0.3vh, 3px) clamp(4px, 0.5vw, 7px);
    border-radius: 5px;
    background: var(--qt-pill-color, var(--qt-accent));
    color: #fff;
    font-size: clamp(0.65rem, 1vh, 0.8rem);
    font-weight: 700;
    line-height: 1.25;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-height: 0;
    flex-shrink: 0;
}
/* The repeat marker on a chip. Sized in em so it tracks the chip's own
   clamped font-size instead of growing out of it on a big panel. */
.qt-pill__repeat {
    flex: none;
    font-size: 0.85em;
    opacity: .85;
}
.qt-day__more {
    font-size: clamp(0.62rem, 0.9vh, 0.75rem);
    color: var(--qt-ink-muted);
    font-weight: 700;
    margin-top: auto;
    padding-top: 1px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex: 0 0 auto;
}

/* Week and day: a time grid with contained scrolling */
.qt-timegrid-container {
    flex: 1 1 auto;
    min-height: 0;
    height: 100%;
    overflow: auto;
    position: relative;
    background: var(--qt-line-soft);
}
.qt-timegrid {
    display: grid;
    grid-template-columns: clamp(52px, 5vw, 68px) repeat(var(--qt-cols, 7), minmax(90px, 1fr));
    gap: 1px;
    background: var(--qt-line-soft);
    min-width: 100%;
}
.qt-timegrid--day {
    grid-template-columns: clamp(52px, 5vw, 68px) minmax(0, 1fr);
}
.qt-timegrid__corner {
    position: sticky;
    top: 0;
    left: 0;
    z-index: 15;
    background: var(--qt-surface-2);
}
.qt-timegrid__head {
    position: sticky;
    top: 0;
    z-index: 10;
    padding: var(--qt-2);
    text-align: center;
    background: var(--qt-surface-2);
    font-weight: 800;
    font-size: var(--qt-text-sm);
    line-height: 1.2;
}
.qt-timegrid__head.is-today {
    color: var(--qt-accent);
}
.qt-timegrid__hour {
    position: sticky;
    left: 0;
    z-index: 5;
    padding: var(--qt-1) var(--qt-2);
    background: var(--qt-inset);
    font-size: var(--qt-text-xs);
    color: var(--qt-ink-muted);
    text-align: end;
    font-variant-numeric: tabular-nums;
    display: flex;
    align-items: center;
    justify-content: flex-end;
}
.qt-timegrid__cell {
    position: relative;
    min-height: clamp(36px, 4.5vh, 52px);
    background: var(--qt-surface);
    border: none;
    padding: 2px 4px;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    gap: 2px;
    transition: background-color .1s;
}
.qt-timegrid__cell:hover {
    background: var(--qt-surface-2);
}
.qt-timegrid__cell:active {
    background: var(--qt-surface-2);
}

.qt-legend {
    display: flex;
    gap: var(--qt-2);
    flex-wrap: wrap;
    align-items: center;
    flex: 0 0 auto;
    padding: 1px 0;
}
.qt-legend__item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-weight: 700;
    font-size: var(--qt-text-xs);
    padding: 4px 10px;
    border-radius: 999px;
    background: var(--qt-surface-2);
    border: 1px solid var(--qt-line-soft);
    cursor: pointer;
    user-select: none;
    transition: opacity .15s, background-color .15s, border-color .15s;
}
.qt-legend__item:hover {
    border-color: var(--qt-line);
}
.qt-legend__dot {
    width: 10px;
    height: 10px;
    border-radius: 999px;
    background: var(--qt-legend-color);
    flex-shrink: 0;
}
.qt-legend__item.is-off {
    opacity: .35;
    background: transparent;
}

/* ------------------------------------------------------------
   Sheets (the touch-friendly stand-in for a dialog)
   ------------------------------------------------------------ */
.qt-sheet {
    position: fixed; inset: 0; z-index: 60;
    display: flex; align-items: center; justify-content: center;
    padding: var(--qt-4);
    background: rgba(4, 7, 16, .62);
}
.qt-sheet[hidden] { display: none; }
.qt-sheet__panel {
    width: min(620px, 100%);
    max-height: 88vh; overflow: auto;
    background: var(--qt-surface);
    border: 1px solid var(--qt-line);
    border-radius: var(--qt-radius);
    box-shadow: var(--qt-shadow);
}
.qt-sheet__head {
    display: flex; align-items: center; gap: var(--qt-3);
    padding: var(--qt-4);
    border-bottom: 1px solid var(--qt-line-soft);
}
.qt-sheet__title { font-size: var(--qt-text-xl); font-weight: 900; }
.qt-sheet__body { padding: var(--qt-4); display: flex; flex-direction: column; gap: var(--qt-3); }
.qt-sheet__foot {
    display: flex; gap: var(--qt-2); justify-content: flex-end; flex-wrap: wrap;
    padding: var(--qt-4); border-top: 1px solid var(--qt-line-soft);
}

/* ------------------------------------------------------------
   Repeating events, inside the event sheet

   Everything here is a tap target first. A radio's own dot is only a
   few millimetres across, so the input is hidden and the label around
   it becomes the button — which is also why the boxes carry their
   selected state with a border and a tint rather than a tick.
   ------------------------------------------------------------ */
.qt-repeat { box-shadow: none; }
.qt-repeat__head { padding: var(--qt-3); min-height: var(--qt-tap); }
.qt-repeat__title { font-weight: 800; }
.qt-repeat__body {
    padding: var(--qt-3);
    display: flex;
    flex-direction: column;
    gap: var(--qt-3);
    background: var(--qt-inset);
}
.qt-repeat.is-on > .qt-repeat__head .qt-badge {
    background: var(--qt-accent-soft);
    border-color: var(--qt-accent);
    color: var(--qt-ink);
}

/* Choice tiles: presets, and the "carry on until" row. */
.qt-picks {
    display: grid;
    gap: var(--qt-2);
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
}
.qt-picks--sm { grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); }
.qt-pick { position: relative; display: block; }
.qt-pick input {
    position: absolute;
    inset: 0;
    opacity: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    cursor: pointer;
}
.qt-pick__box {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    min-height: var(--qt-tap);
    padding: var(--qt-2) var(--qt-3);
    border: 2px solid var(--qt-line);
    border-radius: var(--qt-radius-sm);
    background: var(--qt-surface);
    transition: border-color .15s, background-color .15s;
}
.qt-pick__box b { font-size: var(--qt-text-sm); font-weight: 800; }
.qt-pick__box small { font-size: var(--qt-text-xs); color: var(--qt-ink-muted); font-weight: 700; }
.qt-pick input:checked + .qt-pick__box {
    border-color: var(--qt-accent);
    background: var(--qt-accent-soft);
}
.qt-pick input:focus-visible + .qt-pick__box { outline: 2px solid var(--qt-accent); outline-offset: 2px; }

/* "Repeat every [2] [weeks]" reads as one control, so it is laid out as one. */
.qt-repeat__every { display: flex; gap: var(--qt-2); }
.qt-repeat__every .qt-input { flex: 0 0 96px; text-align: center; }
.qt-repeat__every .qt-select { flex: 1 1 auto; min-width: 0; }

.qt-repeat__custom { display: flex; flex-direction: column; gap: var(--qt-3); }
.qt-repeat__custom[hidden] { display: none; }

/* Weekday picker: seven squares that stay on one row where there is room. */
.qt-days { display: flex; gap: var(--qt-2); flex-wrap: wrap; }
.qt-day-pick { position: relative; flex: 1 1 56px; }
.qt-day-pick input { position: absolute; inset: 0; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.qt-day-pick span {
    display: grid;
    place-items: center;
    min-height: var(--qt-tap);
    border: 2px solid var(--qt-line);
    border-radius: var(--qt-radius-sm);
    background: var(--qt-surface);
    font-size: var(--qt-text-sm);
    font-weight: 800;
    transition: border-color .15s, background-color .15s;
}
.qt-day-pick input:checked + span {
    border-color: var(--qt-accent);
    background: var(--qt-accent-soft);
}
.qt-day-pick input:focus-visible + span { outline: 2px solid var(--qt-accent); outline-offset: 2px; }

/* The plain-English read-back. It is the thing people actually check. */
.qt-repeat__summary {
    margin: 0;
    padding: var(--qt-3);
    border-radius: var(--qt-radius-sm);
    background: var(--qt-surface);
    border: 1px dashed var(--qt-line);
    color: var(--qt-ink-soft);
    font-size: var(--qt-text-sm);
    font-weight: 700;
}
.qt-repeat__summary.is-on { border-style: solid; border-color: var(--qt-accent); color: var(--qt-ink); }

.qt-series-note {
    margin: 0;
    padding: var(--qt-2) var(--qt-3);
    border-radius: var(--qt-radius-sm);
    background: var(--qt-accent-soft);
    color: var(--qt-ink-soft);
    font-size: var(--qt-text-sm);
    font-weight: 700;
}
.qt-series-note[hidden] { display: none; }

/* ------------------------------------------------------------
   Whiteboard
   ------------------------------------------------------------ */
.qt-board { position: relative; display: grid; gap: var(--qt-3); }

.qt-board__workspace {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 340px;
    gap: var(--qt-3);
    align-items: start;
}
.qt-board.is-sidebar-collapsed .qt-board__workspace {
    grid-template-columns: minmax(0, 1fr);
}
.qt-board.is-sidebar-collapsed .qt-board__sidebar {
    display: none;
}

@media (max-width: 960px) {
    .qt-board__workspace {
        display: flex;
        flex-direction: column;
        gap: var(--qt-3);
    }
}

.qt-board__stage-wrap {
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.qt-board__stage {
    position: relative;
    /* Every child — the backdrop and each layer canvas — is absolutely
       positioned, so the stage has no content to be sized by and would
       collapse to nothing. Its height has to be stated. */
    min-height: clamp(380px, 64vh, 780px);
    border: 1px solid var(--qt-line);
    border-radius: var(--qt-radius);
    background: var(--qt-surface);
    overflow: hidden;
    touch-action: none;   /* the canvas handles the pointer, not the browser */
}
/* Every layer is stacked in the same box; the snapshot sits underneath them. */
.qt-board__under { position: absolute; inset: 0; width: 100%; height: 100%; }
.qt-board__canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.qt-board__canvas.is-hidden { display: none; }
.qt-board__canvas.is-active { cursor: crosshair; }

.qt-board__sidebar {
    display: flex;
    flex-direction: column;
    gap: var(--qt-3);
    min-width: 0;
}

.qt-tools { display: flex; gap: var(--qt-2); flex-wrap: wrap; align-items: center; }
.qt-sidebar-toggle {
    margin-inline-start: auto;
}
.qt-sidebar-toggle.is-active {
    background: var(--qt-surface-2);
    border-color: var(--qt-accent);
    color: var(--qt-ink);
}

.qt-pen {
    width: 48px; height: 48px; border-radius: 999px;
    border: 3px solid transparent; cursor: pointer;
    background: var(--qt-pen-color);
}
.qt-pen.is-active { border-color: var(--qt-ink); }

/* Collapsible panels / details */
details.qt-collapse {
    border: 1px solid var(--qt-line);
    border-radius: var(--qt-radius);
    background: var(--qt-surface);
    box-shadow: var(--qt-shadow);
    overflow: hidden;
}
summary.qt-collapse__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--qt-3);
    padding: var(--qt-3) var(--qt-4);
    cursor: pointer;
    user-select: none;
    background: var(--qt-surface);
    border-bottom: 1px solid transparent;
    transition: background-color .15s, border-color .15s;
    list-style: none;
}
summary.qt-collapse__head::-webkit-details-marker {
    display: none;
}
summary.qt-collapse__head:hover {
    background: var(--qt-surface-2);
}
details.qt-collapse[open] > summary.qt-collapse__head {
    border-bottom-color: var(--qt-line-soft);
}
.qt-collapse__title-group {
    display: flex;
    align-items: center;
    gap: var(--qt-2);
    min-width: 0;
}
.qt-collapse__chevron {
    display: inline-grid;
    place-items: center;
    width: 24px;
    height: 24px;
    border-radius: 999px;
    font-size: 0.85rem;
    color: var(--qt-ink-muted);
    transition: transform .2s cubic-bezier(0.4, 0, 0.2, 1);
    transform: rotate(-90deg);
}
details.qt-collapse[open] > summary .qt-collapse__chevron {
    transform: rotate(0deg);
}
.qt-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 24px;
    height: 24px;
    padding: 0 8px;
    border-radius: 999px;
    background: var(--qt-surface-2);
    border: 1px solid var(--qt-line);
    font-size: var(--qt-text-xs);
    font-weight: 800;
    color: var(--qt-ink-muted);
}

.qt-layers { display: flex; flex-direction: column; gap: var(--qt-2); max-height: 320px; overflow-y: auto; padding-right: 2px; }
.qt-layer {
    display: flex; align-items: center; gap: var(--qt-3);
    padding: var(--qt-2) var(--qt-3);
    border: 1px solid var(--qt-line);
    border-radius: var(--qt-radius-sm);
    background: var(--qt-surface-2);
    min-height: 48px;
}
.qt-layer.is-active { border-color: var(--qt-accent); background: var(--qt-accent-soft); }
.qt-layer__name { flex: 1 1 auto; font-weight: 700; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qt-eye {
    width: var(--qt-tap); height: var(--qt-tap);
    display: grid; place-items: center;
    border: none; background: none; color: var(--qt-ink);
    font-size: 1.3rem; cursor: pointer; border-radius: 999px;
    flex-shrink: 0;
}
.qt-eye.is-off { opacity: .35; }

.qt-saved-boards__list {
    display: flex;
    flex-direction: column;
    gap: var(--qt-2);
    max-height: 320px;
    overflow-y: auto;
    padding-right: 2px;
}
.qt-saved-boards__group-title {
    font-size: var(--qt-text-xs);
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--qt-ink-muted);
    padding-top: var(--qt-2);
}

/* ------------------------------------------------------------
   Safe web & YouTube
   ------------------------------------------------------------ */
.qt-tiles { display: grid; gap: var(--qt-3); grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
.qt-tile {
    display: flex; flex-direction: column;
    border: 1px solid var(--qt-line);
    border-radius: var(--qt-radius);
    background: var(--qt-surface);
    overflow: hidden;
    text-align: start;
}
.qt-tile__thumb {
    aspect-ratio: 16 / 9; width: 100%; object-fit: cover;
    background: var(--qt-inset);
}
.qt-tile__body { padding: var(--qt-3); display: grid; gap: 6px; }
.qt-tile__title { font-weight: 800; font-size: var(--qt-text-base); }
.qt-tile__meta { font-size: var(--qt-text-xs); color: var(--qt-ink-muted); }
.qt-tile__actions { display: flex; gap: var(--qt-2); padding: 0 var(--qt-3) var(--qt-3); flex-wrap: wrap; }
.qt-tile.is-pending { border-color: var(--qt-warn); }
.qt-tile.is-hidden-by-child { opacity: .6; border-style: dashed; }

/* The "open it and look at it" link in the approval queues.

   Underlined rather than merely coloured, because this panel is read from a
   metre away and colour alone is not a strong enough signal that a title is
   pressable — nor a signal at all to anyone who cannot separate the two.
   The row is padded out to the tap floor so it is a thumb target, not a
   text-sized one. */
/* Written as a.qt-review-link, not .qt-review-link: `.qt a` above resets
   text-decoration and would otherwise out-specify this and take the
   underline straight back off. */
a.qt-review-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    min-height: var(--qt-tap);
    padding: var(--qt-2) 0;
    color: var(--qt-ink);
    text-decoration: underline;
    text-underline-offset: 3px;
    text-decoration-thickness: 2px;
    text-decoration-color: var(--qt-line);
    transition: color .15s, text-decoration-color .15s;
}
a.qt-review-link:hover,
a.qt-review-link:focus-visible {
    color: var(--qt-accent);
    text-decoration-color: var(--qt-accent);
}
.qt-review-link__mark { font-size: .85em; opacity: .7; }

/* The address itself, wrapped rather than clipped: the tail of a link is
   often the part worth reading before allowing it. */
.qt-review-url {
    overflow-wrap: anywhere;
    color: var(--qt-ink-muted);
    font-size: var(--qt-text-xs);
}

/* A tile whose picture is also the link should say so on hover. */
.qt-tile a:hover .qt-tile__thumb { opacity: .85; }

.qt-viewer { display: grid; gap: var(--qt-3); }
.qt-viewer__frame {
    width: 100%; aspect-ratio: 16 / 9; min-height: 380px;
    border: 1px solid var(--qt-line);
    border-radius: var(--qt-radius);
    background: #000;
}

/* ------------------------------------------------------------
   Family view
   ------------------------------------------------------------ */
.qt-hero {
    display: flex; align-items: center; gap: var(--qt-5); flex-wrap: wrap;
    padding: var(--qt-5);
    border-radius: var(--qt-radius);
    background: linear-gradient(135deg, rgba(99,102,241,.22), rgba(168,85,247,.14));
    border: 1px solid var(--qt-line);
}
.qt-hero__greeting { font-size: var(--qt-text-3xl); font-weight: 900; line-height: 1; }
.qt-hero__sub { color: var(--qt-ink-soft); font-size: var(--qt-text-lg); margin-top: var(--qt-2); }
.qt-hero__kids { margin-inline-start: auto; display: flex; gap: var(--qt-3); flex-wrap: wrap; }
.qt-kid {
    display: grid; gap: 6px; place-items: center;
    min-width: 104px; padding: var(--qt-3);
    border-radius: var(--qt-radius-sm);
    background: var(--qt-surface);
    border: 1px solid var(--qt-line);
}
.qt-kid__name { font-weight: 800; font-size: var(--qt-text-sm); }
.qt-kid__stat { font-size: var(--qt-text-xs); color: var(--qt-ink-muted); font-weight: 700; }

.qt-agenda { display: flex; flex-direction: column; }
.qt-agenda__row {
    display: flex; align-items: center; gap: var(--qt-3);
    padding: var(--qt-3) 0;
    border-bottom: 1px solid var(--qt-line-soft);
}
.qt-agenda__row:last-child { border-bottom: none; }
.qt-agenda__when {
    min-width: 96px; font-weight: 800; font-variant-numeric: tabular-nums;
    font-size: var(--qt-text-base);
}
.qt-agenda__bar { width: 5px; align-self: stretch; border-radius: 999px; background: var(--qt-agenda-color, var(--qt-accent)); }
.qt-agenda__title { font-weight: 700; font-size: var(--qt-text-base); }
.qt-agenda__meta { font-size: var(--qt-text-sm); color: var(--qt-ink-muted); }

/* ------------------------------------------------------------
   Child safety lock
   ------------------------------------------------------------ */
/* ------------------------------------------------------------
   Unlock keypad
   ------------------------------------------------------------ */
.qt-keypad { display: grid; gap: var(--qt-4); justify-items: center; }

/* Fixed height so the panel does not jump as digits are added. */
.qt-keypad__dots {
    display: flex; gap: var(--qt-2); align-items: center;
    min-height: 1.5rem;
}
.qt-keypad__dot {
    width: .85rem; height: .85rem; border-radius: 50%;
    background: var(--qt-accent);
}

.qt-keypad__grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--qt-3);
    width: min(20rem, 100%);
}
.qt-keypad__key {
    /* Deliberately past the 56px floor the rest of the hub keeps: this one is
       used standing at arm's length, often by someone holding something. */
    min-height: 4.25rem;
    font-size: 1.6rem;
    font-weight: 700;
    border-radius: var(--qt-radius-sm);
    border: 1px solid var(--qt-line);
    background: var(--qt-surface-2);
    color: var(--qt-ink);
    cursor: pointer;
}
.qt-keypad__key:active { background: var(--qt-accent-soft); transform: translateY(1px); }
.qt-keypad__key--soft { font-size: 1.2rem; color: var(--qt-ink-muted); }

/* ------------------------------------------------------------
   Displays
   ------------------------------------------------------------ */
.qt-displays { display: grid; gap: var(--qt-3); }

.qt-display {
    display: grid; gap: var(--qt-2);
    padding: var(--qt-3) var(--qt-4);
    border: 1px solid var(--qt-line);
    border-radius: var(--qt-radius-sm);
    background: var(--qt-surface-2);
}
.qt-display.is-asking { border-color: var(--qt-warn); background: var(--qt-warn-soft); }

.qt-display__head { display: flex; gap: var(--qt-3); align-items: center; justify-content: space-between; flex-wrap: wrap; }
.qt-display__name { font-weight: 700; font-size: var(--qt-text-lg); display: flex; gap: var(--qt-2); align-items: center; flex-wrap: wrap; }
.qt-display__meta { margin: 0; color: var(--qt-ink-muted); font-size: var(--qt-text-sm); }
.qt-display__actions { display: flex; gap: var(--qt-2); flex-wrap: wrap; align-items: center; }
.qt-display__actions form { margin: 0; }

/* Count of screens waiting on an unlock, on the rail's Displays link. */
.qt-rail__badge {
    margin-inline-start: auto;
    min-width: 1.5rem; height: 1.5rem; padding: 0 .35rem;
    display: grid; place-items: center;
    border-radius: 999px;
    background: var(--qt-warn);
    color: #1b1300;
    font-size: var(--qt-text-sm); font-weight: 700;
}

/* The locked state is announced by the topbar chip and its Unlock button.
   There is deliberately no banner under it: on the wall panel this mode is
   for, a second copy of the same two controls costs a band of screen to
   repeat itself to an audience that cannot act on it. */

/* Without the rail and tab bar the main column has no reason to leave a
   gap for them. */
.qt-app.is-locked { grid-template-columns: minmax(0, 1fr); grid-template-areas: "top" "main"; }
.qt-app.is-locked .qt-main { padding-bottom: var(--qt-4); }

/* PIN entry: wide, spaced digits that read at arm's length. */
.qt-pinbox {
    font-size: var(--qt-text-xl);
    letter-spacing: .4em;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------
   Screensaver
   ------------------------------------------------------------ */
.qt-saver {
    position: fixed; inset: 0; z-index: 90;
    background: #000; color: #fff;
    display: grid; place-items: center;
}
.qt-saver[hidden] { display: none; }
.qt-saver__stage { position: absolute; inset: 0; }
.qt-saver__slide {
    position: absolute; inset: 0; margin: 0;
    opacity: 0; transition: opacity 1.4s ease;
}
.qt-saver__slide.is-on { opacity: 1; }

/* Photos are whatever shape the phone took them in, and a family album is
   mostly portrait. `cover` filled the frame but guillotined heads off tall
   shots; `contain` alone leaves dead black bars either side.
   So: two copies of the same file. The backdrop covers the frame, blurred and
   dimmed and scaled past the edges so the blur has no hard border; the real
   photo sits on top, contained, whole. A portrait fills the height and the
   backdrop fills the width — and a wide panorama gets the same treatment
   rotated ninety degrees, with no per-image markup either way. */
.qt-saver__blur {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
    filter: blur(38px) saturate(1.25) brightness(.55);
    /* Blur samples past the element's edge and would otherwise fade to
       transparent at the border; overscaling hides that. */
    transform: scale(1.18);
}
.qt-saver__photo {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: contain;
    /* Lifts the photo off its own blurred backdrop. */
    filter: drop-shadow(0 10px 40px rgba(0, 0, 0, .55));
}
.qt-saver__slide figcaption {
    position: absolute; inset-inline: 0; bottom: 12%;
    text-align: center; font-size: var(--qt-text-xl); font-weight: 700;
    text-shadow: 0 2px 18px rgba(0, 0, 0, .9);
}
.qt-saver__clock {
    position: relative; text-align: center;
    text-shadow: 0 4px 30px rgba(0, 0, 0, .85);
}
.qt-saver__clock span { display: block; font-size: 6rem; font-weight: 900; font-variant-numeric: tabular-nums; line-height: 1; }
.qt-saver__clock small { display: block; font-size: var(--qt-text-xl); font-weight: 700; opacity: .9; }
.qt-saver__hint {
    position: absolute; inset-inline: 0; bottom: var(--qt-5);
    text-align: center; opacity: .55; font-size: var(--qt-text-sm);
}

/* ------------------------------------------------------------
   Toast
   ------------------------------------------------------------ */
.qt-toast {
    position: fixed; z-index: 80;
    inset-inline: 0; bottom: calc(var(--qt-tabbar-h) + var(--qt-4));
    margin-inline: auto; width: max-content; max-width: 90vw;
    padding: var(--qt-3) var(--qt-5);
    border-radius: 999px;
    background: var(--qt-ink); color: var(--qt-canvas);
    font-weight: 800;
    opacity: 0; transform: translateY(14px);
    transition: opacity .2s, transform .2s;
    pointer-events: none;
}
.qt-toast.is-on { opacity: 1; transform: none; }

/* ============================================================
   Responsive
   ============================================================ */

/* Tablet portrait and phones: rail becomes the bottom bar. */
@media (max-width: 900px) {
    .qt-app { grid-template-columns: minmax(0, 1fr); grid-template-areas: "top" "main"; }
    .qt-rail { display: none; }
    .qt-tabbar { display: grid; }
    .qt-main { padding: var(--qt-3) var(--qt-3) calc(var(--qt-tabbar-h) + var(--qt-5)); }
    body.qt[data-qt-page="calendar"] .qt-main { padding: var(--qt-2) var(--qt-2) calc(var(--qt-tabbar-h) + var(--qt-2)); gap: 4px; }
    .qt-clock__time { font-size: var(--qt-text-xl); }
    .qt-hero__greeting { font-size: var(--qt-text-2xl); }
    .qt-hero__kids { margin-inline-start: 0; }
    .qt-hide-sm { display: none !important; }
}

@media (max-width: 620px) {
    .qt-topbar { gap: var(--qt-2); padding: var(--qt-2) var(--qt-3); }
    .qt-clock { display: none; }
    .qt-pagehead__title { font-size: var(--qt-text-xl); }
    .qt-cal-toolbar { gap: 4px; }
    .qt-cal-toolbar__title { font-size: 1.05rem; min-width: 0; }
    .qt-day { padding: 2px; }
    .qt-day__n { font-size: 0.72rem; }
    .qt-pill { font-size: 0.62rem; padding: 1px 3px; border-radius: 4px; }
    .qt-counter__value { min-width: 60px; }
    .qt-sheet { padding: 0; align-items: flex-end; }
    .qt-sheet__panel { max-height: 92vh; border-radius: var(--qt-radius) var(--qt-radius) 0 0; }
    .qt-viewer__frame { min-height: 220px; }
}

/* A large wall display: give the reading sizes more room. */
@media (min-width: 1600px) {
    :root {
        --qt-text-base: 1.15rem;
        --qt-text-lg: 1.45rem;
        --qt-text-xl: 2rem;
        --qt-text-2xl: 2.8rem;
        --qt-text-3xl: 4.2rem;
        --qt-rail-w: 140px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .qt *, .qt *::before, .qt *::after {
        animation-duration: .001ms !important;
        transition-duration: .001ms !important;
    }
}
