/*
 * Display styles. No web fonts, no inline styles (CSP). Landscape-first, responsive, large touch
 * targets for a 15.6" panel viewed from a few metres; every dimension is relative.
 */

:root {
    --bg: #05070a;
    --text: #f2f4f7;
    --muted: #9aa3b2;
    --ok: #7fb069;
    --warn: #d9a55b;
    --error: #e06c75;
    --info: #5b9dd9;
    --mute: #b48ede;
    --strip: rgba(5, 7, 10, 0.55);
    --brightness: 1;
    /* Height of the status strip while it heads the chores panel (one row: the mute pill's 4.4vmin
       plus the strip's padding); the roster starts below it. */
    --panel-head: 6.6vmin;
}

* {
    box-sizing: border-box;
}

html, body {
    margin: 0;
    height: 100%;
    background: var(--bg);
    color: var(--text);
    font-family: "Segoe UI", "Noto Sans Hebrew", system-ui, sans-serif;
    overflow: hidden;
    user-select: none;
}

.hidden {
    display: none !important;
}

#stage {
    position: relative;
    width: 100vw;
    height: 100vh;
    filter: brightness(var(--brightness));
}

.layer {
    position: absolute;
    inset: 0;
}

/* Photos: two stacked layers crossfade. */

/* touch-action: a sideways drag is the page's swipe and two fingers are its pinch zoom (shell.js,
   photos/zoom.js). Left to the browser, a drag becomes a pan and a pinch a page zoom: the pointers
   are cancelled mid-gesture and the page never sees them end. Nothing here scrolls.
   overflow: a picture enlarged by a pinch stays inside the photo area, clear of the chores panel. */
.photo {
    background: #000;
    touch-action: none;
    overflow: hidden;
}

/* The image-free neutral screen: shown when even the packaged fallback cannot be decoded. */
.photo.neutral {
    background: var(--bg);
}

.photo-layer {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    opacity: 0;
    transition: opacity 900ms ease-in-out;
    /* A pinch zoom (photos/zoom.js) sets `transform` on the picture, measured from this corner. */
    transform-origin: 0 0;
}

.photo-layer.visible {
    opacity: 1;
}

/* An enlarged picture's way back to its own size (a double tap, the idle timeout): animated, where
   a pinch itself follows the fingers with no transition. zoom.js SETTLE_MS matches the 250ms. */
.photo-layer.zoom-settle {
    transition: opacity 900ms ease-in-out, transform 250ms ease-out;
}

/* A video in the rotation (photos/slideshow.js): no touch target of its own, so a swipe over it is
   the page's and the WebView never offers its own media gestures. */
video.photo-layer {
    pointer-events: none;
}

/* The day the photo on screen was taken, dd/mm/yy, in the picture's own top-right corner. The
   slideshow sets --photo-top / --photo-right to how far the picture's edges sit inside the photo
   area (object-fit: contain leaves bars beside or above a picture of another shape). Where the status
   strip spans the top of the screen (no chores panel) the label keeps below it. Takes no touches. */
.photo-date {
    position: absolute;
    top: max(calc(var(--photo-top, 0px) + 1.6vmin), var(--date-clear-top, 0px));
    right: calc(var(--photo-right, 0px) + 1.6vmin);
    z-index: 2;
    padding: 0.5vmin 1.3vmin;
    border-radius: 1vmin;
    background: rgba(0, 0, 0, 0.35);
    color: #fff;
    font-size: 2.6vmin;
    text-shadow: 0 0.1vmin 0.4vmin rgba(0, 0, 0, 0.6);
    /* The day over the place, both flush with the picture's right edge; a long relative place
       ("26 ק"מ צפונית מערבית ל...") wraps rather than running across the photo. */
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.2vmin;
    max-width: 40%;
    pointer-events: none;
    opacity: 0;
    transition: opacity 600ms ease-in-out;
}

.photo-date.shown {
    opacity: 1;
}

/* Each line keeps its own direction inside the RTL page: the digits in order, the Hebrew as read. */
.photo-date-day {
    direction: ltr;
    unicode-bidi: isolate;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.04em;
}

.photo-date-place {
    direction: rtl;
    unicode-bidi: isolate;
    font-size: 2.2vmin;
    text-align: right;
}

#stage:not(.with-chores) .photo-date {
    --date-clear-top: 8.5vmin;
}

/* The double-tap pause sign (shell.js): two bars in a dark disc over the middle of the photo, shown
   for a moment and faded out. It takes no touches, so a tap or a swipe over it reaches the photo. */
.pause-mark {
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 2;
    width: 16vmin;
    height: 16vmin;
    margin: -8vmin 0 0 -8vmin;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.45);
    opacity: 0;
    pointer-events: none;
    transition: opacity 300ms ease-out;
}

.pause-mark::before,
.pause-mark::after {
    content: "";
    position: absolute;
    top: 4.5vmin;
    width: 2.2vmin;
    height: 7vmin;
    border-radius: 0.6vmin;
    background: rgba(255, 255, 255, 0.92);
}

.pause-mark::before {
    left: 4.7vmin;
}

.pause-mark::after {
    right: 4.7vmin;
}

.pause-mark.show {
    opacity: 1;
}

/* Website slot. */

.website {
    display: none;
}

.website-frame {
    width: 100%;
    height: 100%;
    border: 0;
    background: #fff;
}

.website-fallback {
    position: absolute;
    inset: 0;
    margin: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 3vmin;
    color: var(--muted);
    background: var(--bg);
}

#stage[data-mode="website"] .photo {
    display: none;
}

#stage[data-mode="website"] .website {
    display: block;
}

#stage[data-mode="mixed"] .photo {
    inset: 0 0 0 40%;
}

#stage[data-mode="mixed"] .website {
    display: block;
    inset: 0 60% 0 0;
}

/* Status strip: always visible, unobtrusive, readable from a distance. */

.strip {
    position: absolute;
    top: 0;
    inset-inline: 0;
    /* Content panels are later siblings in the DOM. Keep them from intercepting the strip's
       controls (notably the mute button over the left-hand chores panel). */
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 2vmin;
    padding: 1.2vmin 2.4vmin;
    background: var(--strip);
    backdrop-filter: blur(6px);
    font-size: 2.6vmin;
}

.clock {
    font-variant-numeric: tabular-nums;
    min-width: 8ch;
}

/* The microphone status is secondary to the clock: a small line, kept to one row (a long state
   such as the offline notice ends in an ellipsis rather than growing the strip). */
.indicator {
    display: flex;
    align-items: center;
    gap: 0.8vmin;
    min-width: 0;
    font-size: 1.9vmin;
    line-height: 1.3;
}

#indicator-text {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.dot {
    flex: none;
    width: 1.2vmin;
    height: 1.2vmin;
    border-radius: 50%;
    background: var(--info);
    box-shadow: 0 0 1.2vmin currentColor;
}

.indicator[data-level="ok"] .dot { background: var(--ok); color: var(--ok); }
.indicator[data-level="warn"] .dot { background: var(--warn); color: var(--warn); }
.indicator[data-level="error"] .dot { background: var(--error); color: var(--error); }
.indicator[data-level="muted"] .dot { background: var(--mute); color: var(--mute); }
.indicator[data-level="info"] .dot { background: var(--info); color: var(--info); }

.indicator[data-key="listening"] .dot {
    animation: pulse 2.4s ease-in-out infinite;
}

@keyframes pulse {
    0%, 100% { opacity: 0.55; }
    50% { opacity: 1; }
}

/* "אני מקשיב": the wake word was heard; say the command now. A glass pill centred over the photo
   area (the chores panel keeps its quarter), soft green edge breathing, four sound bars moving.
   Stacking: above the photos, the strip, the takeovers (20), the home board (25) and the
   voice-action card (30); below pairing and the Google Photos setup (40). It takes no touches. */
.listening-badge {
    position: absolute;
    top: 2.4vmin;
    left: 50%;
    z-index: 35;
    display: flex;
    align-items: center;
    gap: 1.4vmin;
    padding: 1.1vmin 2.8vmin 1.1vmin 2.4vmin;
    border-radius: 999px;
    border: 0.2vmin solid rgba(110, 226, 168, 0.6);
    background: rgba(10, 16, 24, 0.6);
    -webkit-backdrop-filter: blur(1.4vmin) saturate(170%);
    backdrop-filter: blur(1.4vmin) saturate(170%);
    color: #fff;
    font-size: 3.2vmin;
    font-weight: 600;
    line-height: 1.2;
    white-space: nowrap;
    transform: translateX(-50%);
    pointer-events: none;
    animation: listening-in 240ms ease-out, listening-glow 1.8s ease-in-out infinite;
}

#stage.with-chores .listening-badge {
    left: 62.5%;
}

.listening-bars {
    display: flex;
    align-items: center;
    gap: 0.45vmin;
    height: 3.2vmin;
}

.listening-bars i {
    width: 0.6vmin;
    height: 100%;
    border-radius: 0.3vmin;
    background: #6fe2a8;
    transform: scaleY(0.35);
    animation: listening-bar 0.9s ease-in-out infinite;
}

.listening-bars i:nth-child(2) { animation-delay: -0.25s; }
.listening-bars i:nth-child(3) { animation-delay: -0.5s; }
.listening-bars i:nth-child(4) { animation-delay: -0.7s; }

@keyframes listening-bar {
    0%, 100% { transform: scaleY(0.35); }
    50% { transform: scaleY(1); }
}

@keyframes listening-in {
    from { opacity: 0; transform: translate(-50%, -1.4vmin); }
    to { opacity: 1; transform: translate(-50%, 0); }
}

@keyframes listening-glow {
    0%, 100% { box-shadow: 0 0.6vmin 2.4vmin rgba(0, 0, 0, 0.35), 0 0 1.2vmin rgba(110, 226, 168, 0.25); }
    50% { box-shadow: 0 0.6vmin 2.4vmin rgba(0, 0, 0, 0.35), 0 0 3vmin rgba(110, 226, 168, 0.6); }
}

/* The privacy mute: a compact pill that stays out of the photo's way, still a comfortable touch
   target (4.4vmin is about 48 px on the 15.6" panel), and unmistakable once muted. */

.mute {
    flex: none;
    min-height: 4.4vmin;
    padding: 0.6vmin 1.8vmin;
    font: inherit;
    font-size: 1.9vmin;
    white-space: nowrap;
    color: var(--text);
    background: rgba(255, 255, 255, 0.08);
    border: 0.25vmin solid var(--muted);
    border-radius: 2.2vmin;
    cursor: pointer;
}

.mute.muted {
    background: var(--mute);
    border-color: var(--mute);
    color: #05070a;
    font-weight: 700;
}

.mute:disabled {
    opacity: 0.4;
    cursor: default;
}

#stage.offline .strip {
    box-shadow: inset 0 -0.4vmin 0 var(--warn);
}

/* Share-to-Telegram: a small round Telegram logo floating over the photo, out of the way in a bottom
   corner. It sits above the photo and website layers but below the setup overlays (pairing, Google
   Photos). The logo is the whole button; its name is in aria-label. */
.share-button {
    position: absolute;
    bottom: 3vmin;
    inset-inline-start: 3vmin;
    z-index: 5;
    width: 5.5vmin;
    height: 5.5vmin;
    min-width: 40px;
    min-height: 40px;
    padding: 0;
    font: inherit;
    font-size: 2.4vmin;
    color: var(--text);
    background: url('telegram.png') center / contain no-repeat;
    border: 0;
    border-radius: 50%;
    box-shadow: 0 0.3vmin 1.2vmin rgba(0, 0, 0, 0.45);
    cursor: pointer;
}

/* The brief outcome after a tap (sent / failed / unavailable): the logo gives way to a text pill,
   dark so it stays readable over a bright photo. */
.share-button.feedback {
    width: auto;
    height: auto;
    min-height: 5.5vmin;
    padding: 1vmin 2.8vmin;
    background: rgba(5, 7, 10, 0.72);
    border-radius: 2.75vmin;
}

.share-button:disabled {
    opacity: 0.6;
    cursor: default;
}

.share-button.feedback:disabled {
    opacity: 1;
}

.share-button.hidden {
    display: none;
}

/* "This clip at full volume": a round speaker button of the same size, directly above the share
   button (its bottom, its height - never under 40px - and a small gap). Dark glass while the clip
   plays at the usual volume; amber while this playback is raised. */
.volume-button {
    position: absolute;
    bottom: calc(3vmin + max(5.5vmin, 40px) + 1.6vmin);
    inset-inline-start: 3vmin;
    z-index: 5;
    width: 5.5vmin;
    height: 5.5vmin;
    min-width: 40px;
    min-height: 40px;
    padding: 0;
    background: rgba(5, 7, 10, 0.62) url('volume.svg') center / 60% no-repeat;
    border: 0.25vmin solid rgba(242, 244, 247, 0.85);
    border-radius: 50%;
    box-shadow: 0 0.3vmin 1.2vmin rgba(0, 0, 0, 0.45);
    cursor: pointer;
}

.volume-button.boosted {
    background-color: var(--warn);
    border-color: var(--warn);
}

.volume-button.hidden {
    display: none;
}

/* The row under the photo while a double tap holds it: the suspend pill centred on the photo area,
   the "?" beside it. Centred on the photo area rather than the screen: the chores panel and the
   mixed mode's website take the rest (--photo-centre follows those layouts below). The photo area
   always reaches the stage's right edge, so the row spans from its mirrored left edge to that one;
   two equal outer columns keep the pill's middle on --photo-centre whatever its words, and the "?"
   sits in the far one against the pill. The row itself takes no touches (a swipe that starts
   beside the buttons still reaches the photo), only its buttons do. */
#stage[data-mode="mixed"] {
    --photo-centre: 70%;
}

#stage.with-chores {
    --photo-centre: 62.5%;
}

#stage.with-chores[data-mode="mixed"] {
    --photo-centre: 77.5%;
}

.pause-actions {
    position: absolute;
    bottom: 3vmin;
    left: calc(var(--photo-centre, 50%) * 2 - 100%);
    right: 0;
    z-index: 5;
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    column-gap: 2vmin;
    pointer-events: none;
}

.pause-actions > button {
    pointer-events: auto;
}

/* "Suspend this photo": a dark glass pill with its words. After a tap the words give way to the
   outcome; a failure gets a red edge. */
.suspend-button {
    grid-column: 2;
    min-height: max(5.5vmin, 44px);
    padding: 1vmin 3.2vmin;
    font: inherit;
    font-size: 2.8vmin;
    font-weight: 600;
    white-space: nowrap;
    color: var(--text);
    background: rgba(5, 7, 10, 0.62);
    border: 0.25vmin solid rgba(242, 244, 247, 0.85);
    border-radius: 999px;
    box-shadow: 0 0.3vmin 1.2vmin rgba(0, 0, 0, 0.45);
    cursor: pointer;
}

.suspend-button:disabled {
    opacity: 0.6;
    cursor: default;
}

.suspend-button.feedback:disabled {
    opacity: 1;
}

.suspend-button.failed {
    border-color: var(--error);
}

.suspend-button.hidden {
    display: none;
}

/* "?": opens the family's guide (#help). A round yellow button with a big dark question mark,
   larger than the pill beside it and softly glowing, so a child sees it at once. */
.help-button {
    grid-column: 3;
    justify-self: start;
    width: max(7.6vmin, 56px);
    height: max(7.6vmin, 56px);
    padding: 0;
    font: inherit;
    font-size: max(5.2vmin, 38px);
    font-weight: 900;
    line-height: 1;
    color: #1d1400;
    background: radial-gradient(circle at 35% 30%, #fff4b0 0%, #ffd23f 48%, #ffae00 100%);
    border: max(0.45vmin, 3px) solid #ffffff;
    border-radius: 50%;
    box-shadow: 0 0.5vmin 1.6vmin rgba(0, 0, 0, 0.5);
    cursor: pointer;
    animation: help-button-in 360ms cubic-bezier(0.34, 1.56, 0.64, 1), help-button-glow 1.8s ease-out 360ms infinite;
}

.help-button.hidden {
    display: none;
}

@keyframes help-button-in {
    from { opacity: 0; transform: scale(0.4); }
    to { opacity: 1; transform: none; }
}

@keyframes help-button-glow {
    0% { box-shadow: 0 0 0 0 rgba(255, 210, 63, 0.75), 0 0.5vmin 1.6vmin rgba(0, 0, 0, 0.5); }
    70% { box-shadow: 0 0 0 2.6vmin rgba(255, 210, 63, 0), 0 0.5vmin 1.6vmin rgba(0, 0, 0, 0.5); }
    100% { box-shadow: 0 0 0 0 rgba(255, 210, 63, 0), 0 0.5vmin 1.6vmin rgba(0, 0, 0, 0.5); }
}

/* Pairing overlay. */

.overlay {
    position: absolute;
    inset: 0;
    /* Pairing/setup/takeover screens intentionally cover the status strip as well. */
    z-index: 20;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3vmin;
    background: rgba(5, 7, 10, 0.92);
    text-align: center;
    padding: 6vmin;
}

.overlay h1 {
    margin: 0;
    font-size: 5vmin;
    font-weight: 600;
}

.code {
    margin: 0;
    font-size: 14vmin;
    letter-spacing: 0.25em;
    font-variant-numeric: tabular-nums;
    font-family: "Consolas", "Courier New", monospace;
}

/* The setup QR (Google Photos): a white quiet zone so any camera reads it off the dark stage. */
.qr {
    width: 34vmin;
    height: 34vmin;
    background: #fff;
    padding: 1.5vmin;
    border-radius: 1.5vmin;
    box-sizing: border-box;
}

.hint {
    margin: 0;
    font-size: 3vmin;
    color: var(--muted);
    max-width: 70vw;
}

/* Pairing and the Google Photos setup stay above every other layer, the voice-action card included
   (a card they cover is never acknowledged, so its action expires unseen and never runs). */
#pairing,
#ambient {
    z-index: 40;
}

/* Voice-action confirmation card: a spoken home-control command, shown for the server's five-second
   window before anything runs. Stacking: above the photo and website layers, the chores panel, the
   share button, the status strip, and the shopping and HTML takeovers (z-index 20); below pairing
   and the Google Photos setup (40). The card says nothing aloud (a video under it is paused), so
   everything the family needs is here and readable across a room: what will happen, how long is
   left, and how to stop it. */

.overlay.voice-action {
    z-index: 30;
    padding: 4vmin;
    background: rgba(5, 7, 10, 0.8);
}

.voice-action-card {
    width: min(92vw, 130vmin);
    max-height: 92vh;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2.4vmin;
    padding: 5vmin 6vmin;
    border-radius: 3vmin;
    background: linear-gradient(160deg, #16202e 0%, #0b1119 100%);
    border: 0.4vmin solid var(--info);
    box-shadow: 0 2vmin 6vmin rgba(0, 0, 0, 0.55);
    text-align: center;
}

#voice-action-title {
    margin: 0;
    font-size: 4.4vmin;
    font-weight: 800;
    color: var(--info);
}

#voice-action-summary {
    margin: 0;
    font-size: 5.4vmin;
    font-weight: 700;
    line-height: 1.3;
    overflow-wrap: anywhere;
}

/* The countdown keeps its height before the window starts, so the card does not jump when the
   first number appears. */
#voice-action-countdown {
    display: block;
    min-height: 1em;
    font-size: 16vmin;
    line-height: 1;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    color: var(--warn);
}

#voice-action-hint {
    margin: 0;
    font-size: 3.2vmin;
    color: var(--muted);
    overflow-wrap: anywhere;
}

.voice-action[data-phase="checking"] #voice-action-hint,
.voice-action[data-phase="executing"] #voice-action-hint {
    font-size: 3.6vmin;
    font-weight: 700;
    color: var(--text);
}

.voice-action[data-phase="checking"] #voice-action-countdown {
    color: var(--muted);
}

.voice-action[data-phase="executing"] #voice-action-countdown,
.voice-action[data-phase="done"] #voice-action-countdown,
.voice-action[data-phase="done"] #voice-action-hint,
.voice-action[data-phase="done"] .voice-action-buttons {
    display: none;
}

.voice-action-buttons {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 3vmin;
    margin-top: 1vmin;
}

/* Large, high-contrast touch targets: at least 9vmin tall (about 95 px on the 15.6 inch panel). */
.voice-action-buttons button {
    min-width: 28vmin;
    min-height: 9vmin;
    padding: 1.4vmin 4vmin;
    font: inherit;
    font-size: 3.6vmin;
    font-weight: 800;
    color: #05070a;
    border: 0.4vmin solid transparent;
    border-radius: 4.5vmin;
    cursor: pointer;
}

#voice-action-approve {
    background: var(--ok);
}

#voice-action-reject {
    background: var(--error);
}

.voice-action-buttons button:focus-visible {
    outline: 0.5vmin solid var(--text);
    outline-offset: 0.6vmin;
}

.voice-action-buttons button:disabled {
    opacity: 0.45;
    cursor: default;
}

/* The outcome colours the card's frame: confirmed success, a definite failure or expiry, a cancel. */
.voice-action[data-outcome="completed"] .voice-action-card {
    border-color: var(--ok);
}

.voice-action[data-outcome="failed"] .voice-action-card,
.voice-action[data-outcome="expired"] .voice-action-card {
    border-color: var(--error);
}

.voice-action[data-outcome="cancelled"] .voice-action-card {
    border-color: var(--muted);
}

/* "Not understood": the wake word was heard and nothing came of it. The same card in amber, with
   only the title and what to do; no countdown and no buttons. */
.voice-action[data-phase="unrecognized"] .voice-action-card {
    border-color: var(--warn);
}

.voice-action[data-phase="unrecognized"] #voice-action-title {
    color: var(--warn);
}

.voice-action[data-phase="unrecognized"] #voice-action-countdown,
.voice-action[data-phase="unrecognized"] #voice-action-hint,
.voice-action[data-phase="unrecognized"] .voice-action-buttons {
    display: none;
}

/* A chore claim ("I understood that Noam emptied the dishwasher"): its countdown is the number inside
   the line under the summary, so the large digits give way and that line is set large and bright -
   it is the instruction the child reads. The approve button ("give me the points now") is longer. */
.voice-action[data-action-type="chore.done"] #voice-action-countdown {
    display: none;
}

.voice-action[data-action-type="chore.done"] #voice-action-hint {
    font-size: 4.2vmin;
    font-weight: 700;
    line-height: 1.35;
    color: var(--text);
}

.voice-action[data-action-type="chore.done"] #voice-action-approve {
    min-width: 40vmin;
}

@media (orientation: portrait) {
    .voice-action-card {
        width: 94vw;
        padding: 5vmin 4vmin;
    }
    .voice-action-buttons button {
        min-width: 36vmin;
    }
}

@media (orientation: portrait) {
    #stage[data-mode="mixed"] .photo { inset: 45% 0 0 0; }
    #stage[data-mode="mixed"] { --photo-centre: 50%; }
    #stage[data-mode="mixed"] .website { inset: 0 0 55% 0; }
    .strip { font-size: 2.2vmin; }
}

/* HTML takeover overlay: an admin page filling the whole screen edge to edge. No padding and no
   centering (the page owns its own layout); the sandboxed iframe covers the stage. White backdrop
   like a normal browser canvas, so a page that sets no background of its own (default black text)
   stays readable instead of black-on-black. */
.overlay.custom-html {
    padding: 0;
    gap: 0;
    background: #fff;
}

.custom-html-frame {
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
    background: #fff;
}

/* Shopping list overlay: a deliberately cheerful takeover, nothing like the dark setup overlays.
   A warm "paper" scene, a marker-underlined title, and a checklist of sticky notes. No emojis;
   the personality is in the colour, the tilt and the entrance. Readable across a room. */

.overlay.shopping {
    justify-content: center;
    padding: 4vmin;
    color: #2b2622;
    background:
        radial-gradient(120vmin 80vmin at 80% -10%, #ffe6a7 0%, rgba(255, 230, 167, 0) 60%),
        radial-gradient(120vmin 80vmin at 0% 110%, #bfe3d6 0%, rgba(191, 227, 214, 0) 55%),
        linear-gradient(135deg, #fff7ea 0%, #ffeede 100%);
}

.shopping-card {
    width: min(88vw, 150vmin);
    max-height: 88vh;
    display: flex;
    flex-direction: column;
    gap: 2.4vmin;
    overflow: hidden;
}

.shopping-head {
    position: relative;
    text-align: start;
}

.shopping-title {
    margin: 0;
    font-size: 8vmin;
    font-weight: 800;
    line-height: 1.05;
    letter-spacing: -0.01em;
}

/* A hand-drawn marker swipe under the title. */
.shopping-title::after {
    content: "";
    display: block;
    width: 22vmin;
    height: 1.2vmin;
    margin-top: 1vmin;
    border-radius: 1vmin;
    background: linear-gradient(90deg, #e0533d, #f0a03d);
    transform: rotate(-1.2deg);
}

.shopping-subtitle {
    margin: 1.2vmin 0 0;
    font-size: 3.4vmin;
    font-weight: 600;
    color: #6a5f54;
}

.shopping-count {
    position: absolute;
    inset-inline-end: 0;
    top: 0;
    min-width: 8vmin;
    padding: 1vmin 2vmin;
    font-size: 4.4vmin;
    font-weight: 800;
    text-align: center;
    color: #fff;
    background: #2f6f5e;
    border-radius: 3vmin;
    transform: rotate(3deg);
    box-shadow: 0 1vmin 2.5vmin rgba(47, 111, 94, 0.35);
}

.shopping-count:empty {
    display: none;
}

.shopping-list {
    list-style: none;
    margin: 0;
    padding: 0.5vmin;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(38vmin, 1fr));
    gap: 2vmin;
    overflow: hidden auto;
}

.shopping-item {
    display: flex;
    align-items: center;
    gap: 2vmin;
    padding: 2.2vmin 2.6vmin;
    background: #fffdf8;
    border-radius: 2vmin;
    box-shadow: 0 1.4vmin 3vmin rgba(43, 38, 34, 0.12);
    font-size: 4vmin;
    font-weight: 700;
    transform-origin: center;
    animation: shopping-pop 480ms cubic-bezier(0.2, 0.9, 0.3, 1.3) both;
}

/* A drawn, unticked checkbox: this is a to-buy list, so nothing is crossed off. */
.shopping-item::before {
    content: "";
    flex: none;
    width: 4vmin;
    height: 4vmin;
    border: 0.6vmin solid #2f6f5e;
    border-radius: 1vmin;
    background: #fff;
    transform: rotate(-4deg);
}

.shopping-item-text {
    flex: 1 1 auto;
    min-width: 0;
    overflow-wrap: anywhere;
}

.shopping-item-author {
    flex: none;
    font-size: 2.4vmin;
    font-weight: 600;
    color: #9a8f82;
}

/* Alternating tilt so the notes look pinned by hand, not printed. */
.shopping-item:nth-child(even) { transform: rotate(0.8deg); }
.shopping-item:nth-child(odd) { transform: rotate(-0.7deg); }

/* Staggered entrance for the first dozen; the rest simply appear. */
.shopping-item:nth-child(1) { animation-delay: 40ms; }
.shopping-item:nth-child(2) { animation-delay: 100ms; }
.shopping-item:nth-child(3) { animation-delay: 160ms; }
.shopping-item:nth-child(4) { animation-delay: 220ms; }
.shopping-item:nth-child(5) { animation-delay: 280ms; }
.shopping-item:nth-child(6) { animation-delay: 340ms; }
.shopping-item:nth-child(7) { animation-delay: 400ms; }
.shopping-item:nth-child(8) { animation-delay: 460ms; }
.shopping-item:nth-child(9) { animation-delay: 520ms; }
.shopping-item:nth-child(10) { animation-delay: 580ms; }
.shopping-item:nth-child(11) { animation-delay: 640ms; }
.shopping-item:nth-child(12) { animation-delay: 700ms; }

@keyframes shopping-pop {
    from { opacity: 0; transform: translateY(3vmin) rotate(-3deg) scale(0.96); }
    to { opacity: 1; }
}

.shopping-empty {
    margin: 6vmin 0;
    text-align: center;
    font-size: 4.6vmin;
    font-weight: 700;
    color: #6a5f54;
}

@media (prefers-reduced-motion: reduce) {
    .shopping-item { animation: none; }
}

/* Chore ("dishwasher duty") roster: a persistent panel that keeps its quarter of the screen while
   the photos rotate. The family chose the left side. It is not an overlay; the photo and website
   layers make room for it, so it stays visible through every crossfade. */

#stage.with-chores .photo,
#stage.with-chores .website {
    left: 25%;
}

/* Mixed mode still splits the remaining area (rare on this display): panel | website | photo. */
#stage.with-chores[data-mode="mixed"] .website {
    inset: 0 auto 0 25%;
    width: 30%;
}

#stage.with-chores[data-mode="mixed"] .photo {
    inset: 0 0 0 55%;
}

/* With the roster on screen the status strip leaves the photo and becomes the panel's head, on one
   row: the clock (its usual size), the microphone status right beside it, and the mute pill at the
   far end. The status column takes the leftover width, so a long state ends in an ellipsis rather
   than wrapping. Its height is fixed (--panel-head) so the roster below always starts clear of it. */
#stage.with-chores .strip {
    left: 0;
    right: auto;
    width: 25%;
    height: var(--panel-head);
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "clock status mute";
    align-content: center;
    align-items: center;
    gap: 1.6vmin;
    /* The panel's own side padding, so the clock lines up with the roster title under it. */
    padding: 1vmin 2vmin;
    background: transparent;
    backdrop-filter: none;
}

#stage.with-chores .clock {
    grid-area: clock;
    min-width: 0;
}

#stage.with-chores .indicator {
    grid-area: status;
}

#stage.with-chores .mute {
    grid-area: mute;
}

.chores {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    width: 25%;
    display: flex;
    flex-direction: column;
    /* Sized so a roster of 8 fits the panel's height without scrolling (about 94vmin of 100 in
       use); each extra member needs about 8.7vmin more. */
    gap: 1.4vmin;
    /* Start below the strip heading the panel so the duty spotlight never sits under the clock. */
    padding: calc(var(--panel-head) + 0.4vmin) 2vmin 1.6vmin;
    background: linear-gradient(180deg, rgba(20, 26, 36, 0.96) 0%, rgba(9, 12, 18, 0.96) 100%);
    box-shadow: inset -0.4vmin 0 1.2vmin rgba(0, 0, 0, 0.35);
    overflow: hidden;
}

/* The on-duty spotlight: one row, the "on duty:" label, the member's avatar and their name. */
.chores-duty {
    position: relative;
    display: flex;
    align-items: center;
    gap: 2vmin;
    padding: 1.2vmin 2vmin;
    border-radius: 2vmin;
    background: linear-gradient(135deg, rgba(91, 157, 217, 0.22), rgba(127, 176, 105, 0.18));
    border: 0.3vmin solid rgba(91, 157, 217, 0.5);
}

/* On a rotating weekday: who takes it next week, the name only, small in the spotlight's far bottom
   corner (left, in the RTL display). Positioned out of the row's flow, so it neither adds height to
   the spotlight (the roster's fit below depends on it) nor squeezes today's name; it sits below the
   vertically centred name, and its width is capped so a long name ends in an ellipsis short of the
   avatar. */
.chores-duty-next {
    position: absolute;
    inset-inline-end: 1.6vmin;
    bottom: 0.7vmin;
    max-width: 45%;
    font-size: 1.7vmin;
    font-weight: 600;
    line-height: 1.2;
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.chores-duty-label {
    font-size: 3vmin;
    font-weight: 800;
    color: var(--info);
}

.chores-duty-card {
    display: flex;
    align-items: center;
    gap: 1.6vmin;
    min-width: 0;
}

/* Kept to the one row: a long name ends in an ellipsis rather than growing the spotlight, whose
   height the roster's fit below depends on. */
.chores-duty-name {
    min-width: 0;
    font-size: 3.4vmin;
    font-weight: 800;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.chores-duty.chores-duty-empty {
    background: rgba(255, 255, 255, 0.05);
    border-color: rgba(154, 163, 178, 0.3);
}

.chores-duty.chores-duty-empty .chores-duty-label {
    color: var(--muted);
}

.chores-duty-empty .chores-duty-card {
    display: none;
}

/* Avatars: a round image, or the name's initial on a soft disc when there is none. */
.chores-avatar {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.1);
}

.chores-avatar-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.chores-avatar-initial {
    font-weight: 800;
    color: var(--text);
}

.chores-duty-avatar {
    width: 8vmin;
    height: 8vmin;
}

.chores-duty-avatar .chores-avatar-initial {
    font-size: 4vmin;
}

.chores-member-avatar {
    width: 6vmin;
    height: 6vmin;
}

.chores-member-avatar .chores-avatar-initial {
    font-size: 2.9vmin;
}

/* A column header above the roster, aligned over the countdown column via the same row shape
   (avatar/name/countdown/points) as .chores-member, with everything but the countdown label
   invisible spacing. */
.chores-list-header {
    display: flex;
    align-items: center;
    gap: 1.6vmin;
    padding: 0 1.6vmin;
}

.chores-header-avatar {
    flex: none;
    width: 6vmin;
}

.chores-header-name {
    flex: 1 1 auto;
    min-width: 0;
}

.chores-header-countdown {
    flex: none;
    /* Match .chores-member-countdown's inline-start margin so the label lines up with the values,
       nudging it toward the start (right, in the RTL display) over the countdown column. */
    margin-inline-start: 0.8vmin;
    font-size: 1.9vmin;
    font-weight: 700;
    color: var(--muted);
}

.chores-header-points {
    flex: none;
    /* Stand in for the member row's points column so the label sits over the countdown, not to its
       left; without a width this spacer collapses and pulls the label off the column. */
    width: 5vmin;
}

/* The full roster with points. */
.chores-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.9vmin;
    overflow: hidden auto;
}

.chores-member {
    position: relative;
    overflow: hidden;
    display: flex;
    align-items: center;
    gap: 1.6vmin;
    padding: 0.9vmin 1.6vmin;
    border-radius: 1.6vmin;
    background: rgba(255, 255, 255, 0.05);
}

.chores-member-duty {
    background: rgba(91, 157, 217, 0.18);
    box-shadow: inset 0 0 0 0.25vmin rgba(91, 157, 217, 0.45);
}

/* The "time until home" fill: covers the whole row on departure and loses width toward the end
   (physical right, independent of the RTL reading direction) as the countdown runs out, cooling
   from red through yellow to green. Styled as frosted glass (low opacity + blur + a soft top gloss
   and a bright trailing edge) rather than a flat color, so it reads as a layer over the row, not a
   block sitting on top of the name and points. JS (chores.js applyMemberFill) only ever sets width
   and background-color; the rest is static here. */
.chores-member-fill {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 0;
    background: var(--error);
    backdrop-filter: blur(1.2vmin) saturate(180%);
    -webkit-backdrop-filter: blur(1.2vmin) saturate(180%);
    box-shadow:
        inset 0 0.1vmin 0 rgba(255, 255, 255, 0.35),
        inset 0 -0.1vmin 0 rgba(0, 0, 0, 0.12),
        inset -0.1vmin 0 0 rgba(255, 255, 255, 0.4);
    z-index: 0;
    transition: width 0.3s linear, background-color 0.3s linear;
}

.chores-member-fill::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.28) 0%, rgba(255, 255, 255, 0) 55%);
}

.chores-member-avatar,
.chores-member-name,
.chores-member-countdown,
.chores-member-points {
    position: relative;
    z-index: 1;
}

.chores-member-name {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 2.7vmin;
    font-weight: 600;
    color: var(--text);
    overflow-wrap: anywhere;
}

.chores-member-countdown {
    flex: none;
    margin-inline-start: 0.8vmin;
    font-size: 2.1vmin;
    font-weight: 700;
    color: var(--warn);
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.02em;
}

/* Over the fill, --warn's orange loses contrast against the same-hued glass; plain text reads
   better there, with a shadow to stay legible as the fill cools toward green. */
.chores-member-active-fill .chores-member-countdown {
    color: var(--text);
    text-shadow: 0 0.1vmin 0.4vmin rgba(0, 0, 0, 0.5);
}

.chores-member-countdown-home {
    color: var(--ok);
    font-weight: 600;
    letter-spacing: normal;
}

.chores-member-countdown-empty {
    display: none;
}

.chores-member-points {
    flex: none;
    font-size: 2.4vmin;
    font-weight: 800;
    color: var(--ok);
    font-variant-numeric: tabular-nums;
}

@media (orientation: portrait) {
    #stage.with-chores .photo,
    #stage.with-chores .website {
        left: 30%;
    }
    .chores { width: 30%; }
    #stage.with-chores .strip { width: 30%; }
    #stage.with-chores { --photo-centre: 65%; }
}

/* The duty row is the home dashboard's double-tap target: no browser double-tap zoom on it, and a
   brief ring confirms the double tap (shell.js). */
.chores-duty {
    touch-action: manipulation;
    transition: box-shadow 200ms ease-out;
}

.chores-duty.tapped {
    box-shadow: 0 0 0 0.5vmin var(--info), 0 0 3vmin rgba(91, 157, 217, 0.7);
}

/* Home devices dashboard (home/dashboard.js): the air conditioners in a grid of tiles, Gimli and the
   boiler as two cards under them. It covers the photo area (the chores panel keeps its quarter) or
   the whole screen when there is no panel. Stacking: above the photos, the buttons over them, the
   strip and the shopping / HTML takeovers (20); below the voice-action card (30), so a spoken
   command still shows over it, and below pairing and the Google Photos setup (40). */
.home {
    position: absolute;
    inset: 0;
    z-index: 25;
    display: flex;
    flex-direction: column;
    gap: 1.4vmin;
    padding: 2vmin 2.6vmin 2.2vmin;
    background:
        radial-gradient(120% 80% at 85% 0%, rgba(91, 157, 217, 0.16), transparent 60%),
        linear-gradient(180deg, #0c1119 0%, #06090e 100%);
    touch-action: manipulation;
    animation: home-in 260ms ease-out;
}

#stage.with-chores .home {
    left: 25%;
}

@keyframes home-in {
    from { opacity: 0; transform: translateY(1.5vmin); }
    to { opacity: 1; transform: none; }
}

.home-head {
    display: flex;
    align-items: center;
    gap: 2.4vmin;
}

.home-title {
    margin: 0;
    font-size: 4.2vmin;
    font-weight: 800;
}

.home-updated {
    font-size: 2.1vmin;
    color: var(--muted);
}

.home-updated[data-tone="ok"] {
    color: var(--ok);
}

.home-updated[data-tone="warn"] {
    color: var(--warn);
}

.home-close {
    margin-inline-start: auto;
    min-width: 17vmin;
    min-height: max(6vmin, 44px);
    padding: 0 3vmin;
    font: inherit;
    font-size: 2.9vmin;
    font-weight: 700;
    color: var(--text);
    background: rgba(255, 255, 255, 0.08);
    border: 0.25vmin solid rgba(242, 244, 247, 0.55);
    border-radius: 999px;
    cursor: pointer;
}

.home-notice {
    margin: 0;
    padding: 2vmin;
    font-size: 3.2vmin;
    font-weight: 700;
    text-align: center;
    color: var(--warn);
}

.home-section-head {
    display: flex;
    align-items: baseline;
    gap: 1.6vmin;
    margin-bottom: 0.8vmin;
}

.home-section-title {
    margin: 0;
    font-size: 2.6vmin;
    font-weight: 800;
    color: var(--info);
}

.home-section-status {
    font-size: 2vmin;
    color: var(--muted);
}

/* Air conditioners: four tiles to a row; a tile that is on glows blue (cooling) or orange (heating). */
.home-ac-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1.6vmin;
}

.home-ac-tile {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.6vmin;
    min-width: 0;
    padding: 1.2vmin 1.6vmin;
    border-radius: 2.2vmin;
    background: rgba(255, 255, 255, 0.05);
    border: 0.25vmin solid rgba(154, 163, 178, 0.18);
    transition: background 300ms, border-color 300ms;
}

.home-ac-tile.on {
    background: linear-gradient(160deg, rgba(111, 182, 232, 0.22), rgba(111, 182, 232, 0.07));
    border-color: rgba(111, 182, 232, 0.6);
}

.home-ac-tile.on.heat {
    background: linear-gradient(160deg, rgba(232, 149, 95, 0.22), rgba(232, 149, 95, 0.07));
    border-color: rgba(232, 149, 95, 0.6);
}

.home-ac-tile.offline {
    opacity: 0.55;
}

.home-ac-top {
    display: flex;
    align-items: baseline;
    gap: 1vmin;
    min-width: 0;
}

.home-ac-name {
    flex: none;
    font-size: 3.1vmin;
    font-weight: 800;
}

.home-ac-room {
    flex: 1;
    min-width: 0;
    font-size: 1.8vmin;
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.home-ac-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.home-ac-middle {
    display: flex;
    flex-direction: column;
    align-items: center;
}

/* The digits and the degree sign read left to right inside the Hebrew page. */
.home-ac-temp {
    font-size: 5.2vmin;
    font-weight: 800;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    direction: ltr;
    unicode-bidi: isolate;
}

.home-ac-tile:not(.on) .home-ac-temp {
    color: var(--muted);
}

.home-ac-mode {
    margin-top: 0.2vmin;
    font-size: 1.6vmin;
    font-weight: 700;
    color: #6fb6e8;
}

.home-ac-tile.heat .home-ac-mode {
    color: #e8955f;
}

.home-ac-tile:not(.on) .home-ac-mode {
    color: var(--muted);
}

.home-step {
    width: 5.4vmin;
    height: 5.4vmin;
    min-width: 40px;
    min-height: 40px;
    padding: 0;
    font: inherit;
    font-size: 3.4vmin;
    font-weight: 700;
    line-height: 1;
    color: var(--text);
    background: rgba(255, 255, 255, 0.1);
    border: 0;
    border-radius: 50%;
    cursor: pointer;
}

/* An AC's power: a toggle switch. Off: a grey track, the knob on the left. On: the whole track
   green, the knob on the right (physical sides, the same in the Hebrew layout). */
.home-power.home-switch {
    position: relative;
    align-self: center;
    width: 13vmin;
    height: 6.4vmin;
    min-height: 40px;
    padding: 0;
    background: rgba(154, 163, 178, 0.45);
    border: 0;
    border-radius: 999px;
    cursor: pointer;
    transition: background 220ms ease;
}

.home-switch .home-switch-knob {
    position: absolute;
    top: 50%;
    left: 0.6vmin;
    width: 5.2vmin;
    height: 5.2vmin;
    border-radius: 50%;
    background: #ffffff;
    box-shadow: 0 0.3vmin 0.8vmin rgba(0, 0, 0, 0.45);
    transform: translateY(-50%);
    transition: left 220ms ease;
}

.home-switch[aria-checked="true"] {
    background: var(--ok);
}

.home-switch[aria-checked="true"] .home-switch-knob {
    left: calc(100% - 5.8vmin);
}

.home-switch.pending:disabled {
    opacity: 1;
}

.home-step:disabled,
.home-power:disabled,
.home-chip:disabled,
.home-big:disabled {
    opacity: 0.35;
    cursor: default;
}

/* Over a tile or a card while its command travels: the step it is at, then the outcome. */
.home-feedback {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2vmin;
    border-radius: inherit;
    background: rgba(5, 7, 10, 0.9);
    font-size: 2.8vmin;
    font-weight: 800;
    text-align: center;
    overflow-wrap: anywhere;
}

.home-feedback.done {
    color: var(--ok);
}

.home-feedback.failed {
    color: var(--error);
}

/* Gimli and the boiler, side by side under the air conditioners. */
.home-bottom {
    flex: 1;
    min-height: 0;
    display: grid;
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    gap: 1.6vmin;
}

.home-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 1.2vmin;
    min-height: 0;
    padding: 1.6vmin 2.2vmin;
    border-radius: 2.4vmin;
    background: rgba(255, 255, 255, 0.05);
    border: 0.25vmin solid rgba(154, 163, 178, 0.18);
}

.home-card-head {
    display: flex;
    align-items: center;
    gap: 1.6vmin;
}

.home-card-title {
    margin: 0;
    font-size: 3.4vmin;
    font-weight: 800;
}

.home-card-hint {
    margin: 0;
    font-size: 1.9vmin;
    color: var(--muted);
}

.home-pill {
    padding: 0.5vmin 1.6vmin;
    font-size: 2vmin;
    font-weight: 700;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.08);
    color: var(--muted);
}

.home-pill[data-tone="ok"] {
    background: rgba(127, 176, 105, 0.18);
    color: var(--ok);
}

.home-pill[data-tone="busy"] {
    background: rgba(91, 157, 217, 0.2);
    color: var(--info);
}

.home-pill[data-tone="warn"] {
    background: rgba(217, 165, 91, 0.2);
    color: var(--warn);
}

.home-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 1vmin;
}

.home-chip {
    min-height: max(4.8vmin, 40px);
    padding: 0 2vmin;
    font: inherit;
    font-size: 2.2vmin;
    font-weight: 700;
    color: var(--text);
    background: rgba(255, 255, 255, 0.07);
    border: 0.25vmin solid rgba(154, 163, 178, 0.3);
    border-radius: 999px;
    cursor: pointer;
}

.home-chip.selected {
    color: #05070a;
    background: var(--info);
    border-color: var(--info);
}

/* The boiler's shower buttons: one row of six, the count over the temperature it heats to. */
.home-showers {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 0.8vmin;
}

.home-shower {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 7.4vmin;
    padding: 0;
    border-radius: 1.6vmin;
}

.home-shower b {
    font-size: 3.2vmin;
    line-height: 1;
}

.home-shower small {
    margin-top: 0.3vmin;
    font-size: 1.7vmin;
    font-weight: 600;
    opacity: 0.8;
    direction: ltr;
    unicode-bidi: isolate;
}

.home-card-actions {
    margin-top: auto;
    display: flex;
    gap: 1.4vmin;
}

.home-big {
    flex: 1;
    min-height: max(6.2vmin, 48px);
    font: inherit;
    font-size: 2.8vmin;
    font-weight: 800;
    color: #05070a;
    background: var(--ok);
    border: 0;
    border-radius: 999px;
    cursor: pointer;
}

.home-big.home-secondary {
    flex: 0 0 auto;
    padding: 0 3vmin;
    color: var(--text);
    background: rgba(255, 255, 255, 0.1);
    border: 0.25vmin solid rgba(242, 244, 247, 0.4);
}

.home-big.home-danger {
    color: var(--text);
    background: rgba(224, 108, 117, 0.85);
}

.home-boiler-now {
    display: flex;
    align-items: baseline;
    gap: 1.4vmin;
}

.home-boiler-water {
    font-size: 6.6vmin;
    font-weight: 800;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    direction: ltr;
    unicode-bidi: isolate;
}

.home-boiler-water-label {
    font-size: 2.2vmin;
    color: var(--muted);
}

@media (orientation: portrait) {
    #stage.with-chores .home { left: 30%; }
    .home-ac-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .home-bottom { grid-template-columns: minmax(0, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
    .home { animation: none; }
}

/* ---------------------------------------------------------------------------------------------
   The family's guide (#help, help/guide.js, FAMILY_DISPLAY_HELP_GUIDE.md): a full-screen page for
   children. A bar with the close and "back to the menu" buttons, then a scrolling page: the
   "מה רוצים לעשות?" menu of colourful tiles and one chapter per tile, each with a moving picture
   (inline SVG, animated here) and a few short steps. Every chapter has its own colour (--c, and
   --c-soft for tints). Stacking: above the photos, the chores panel, the strip, the takeovers (20)
   and the home board (25); below the voice-action card (30), the listening badge (35), pairing
   and the Google Photos setup (40). Its animations run only while it is shown (display: none
   otherwise).
   --------------------------------------------------------------------------------------------- */
.help {
    position: absolute;
    inset: 0;
    z-index: 28;
    display: flex;
    flex-direction: column;
    color: var(--text);
    background:
        radial-gradient(90% 60% at 100% 0%, rgba(91, 124, 255, 0.26), transparent 60%),
        radial-gradient(70% 50% at 0% 100%, rgba(255, 79, 163, 0.16), transparent 60%),
        #0b1020;
    animation: help-in 280ms ease-out;
}

@keyframes help-in {
    from { opacity: 0; transform: translateY(2vmin); }
    to { opacity: 1; transform: none; }
}

/* Holds the shared gradients, clips, pictures and icons; laid out as nothing, but not display:none,
   which would stop its gradients from painting. */
.help-defs {
    position: absolute;
    width: 0;
    height: 0;
    overflow: hidden;
}

.help [data-color="swipe"] { --c: #5b7cff; --c-soft: rgba(91, 124, 255, 0.26); }
.help [data-color="pause"] { --c: #ffc300; --c-soft: rgba(255, 195, 0, 0.22); }
.help [data-color="zoom"] { --c: #06d6a0; --c-soft: rgba(6, 214, 160, 0.22); }
.help [data-color="share"] { --c: #2aa8e6; --c-soft: rgba(42, 168, 230, 0.24); }
.help [data-color="volume"] { --c: #ff8c42; --c-soft: rgba(255, 140, 66, 0.24); }
.help [data-color="hide"] { --c: #b07af5; --c-soft: rgba(176, 122, 245, 0.26); }
.help [data-color="voice"] { --c: #ff4fa3; --c-soft: rgba(255, 79, 163, 0.24); }
.help [data-color="home"] { --c: #ff6b6b; --c-soft: rgba(255, 107, 107, 0.24); }
.help [data-color="chores"] { --c: #9ad13b; --c-soft: rgba(154, 209, 59, 0.22); }
.help [data-color="add"] { --c: #4dd4e8; --c-soft: rgba(77, 212, 232, 0.22); }
.help [data-color="when"] { --c: #b8c0ff; --c-soft: rgba(184, 192, 255, 0.22); }
.help [data-color="shabbat"] { --c: #e0b872; --c-soft: rgba(224, 184, 114, 0.22); }

.help-bar {
    flex: none;
    display: flex;
    align-items: center;
    gap: 2vmin;
    padding: 1.4vmin 3vmin;
    background: rgba(11, 16, 32, 0.88);
    border-bottom: 0.2vmin solid rgba(255, 255, 255, 0.08);
}

.help-bar-title {
    margin-inline-end: auto;
    font-size: 2.8vmin;
    font-weight: 700;
    color: var(--muted);
}

.help-bar-button {
    min-height: max(6.4vmin, 48px);
    padding: 0 3.6vmin;
    font: inherit;
    font-size: 3vmin;
    font-weight: 800;
    color: #ffffff;
    background: rgba(255, 255, 255, 0.1);
    border: 0.3vmin solid rgba(255, 255, 255, 0.4);
    border-radius: 999px;
    cursor: pointer;
}

.help-close {
    background: #ef476f;
    border-color: #ef476f;
}

.help-bar-button:active,
.help-back:active {
    transform: scale(0.96);
}

/* The page that scrolls. Positioned, so a chapter's offsetTop is measured from its top. */
.help-scroll {
    position: relative;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    touch-action: pan-y;
    padding: 3vmin 5vmin 10vmin;
}

.help-menu {
    max-width: 172vmin;
    margin: 0 auto 5vmin;
    text-align: center;
}

.help-title {
    margin: 0;
    font-size: 7.4vmin;
    font-weight: 900;
    line-height: 1.1;
}

.help-subtitle {
    margin: 1vmin 0 3.6vmin;
    font-size: 3vmin;
    color: var(--muted);
}

.help-tiles {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 2.4vmin;
}

.help-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1.4vmin;
    min-height: 19vmin;
    padding: 2.2vmin 1.4vmin;
    font: inherit;
    font-size: 3.3vmin;
    font-weight: 800;
    line-height: 1.15;
    color: #ffffff;
    background: linear-gradient(160deg, var(--c-soft), rgba(18, 24, 41, 0.95) 75%);
    border: 0.45vmin solid var(--c);
    border-radius: 3.2vmin;
    box-shadow: 0 0.9vmin 0 rgba(0, 0, 0, 0.35);
    cursor: pointer;
    transition: transform 120ms ease-out;
}

.help-tile:active {
    transform: translateY(0.5vmin) scale(0.97);
}

.help-icon {
    flex: none;
    color: var(--c);
    stroke: currentColor;
    fill: none;
    stroke-width: 3.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.help-tile .help-icon {
    width: 9vmin;
    height: 9vmin;
}

/* A chapter: a card with its colour across the top. A tile's scroll marks it for a moment. */
.help-topic {
    max-width: 172vmin;
    margin: 0 auto 4.4vmin;
    padding: 3vmin 4vmin;
    background: #131a2c;
    border-top: 1.2vmin solid var(--c);
    border-radius: 3.4vmin;
    box-shadow: 0 1vmin 3vmin rgba(0, 0, 0, 0.35);
}

.help-topic.arrived {
    animation: help-arrived 1.6s ease-out;
}

@keyframes help-arrived {
    0% { box-shadow: 0 0 0 0 var(--c); }
    25% { box-shadow: 0 0 0 1.2vmin var(--c); }
    100% { box-shadow: 0 0 0 0 transparent; }
}

.help-topic-title {
    display: flex;
    align-items: center;
    gap: 2vmin;
    margin: 0 0 2.4vmin;
    font-size: 5.4vmin;
    font-weight: 900;
}

.help-topic-title .help-icon {
    width: 7.4vmin;
    height: 7.4vmin;
    padding: 1vmin;
    background: var(--c-soft);
    border-radius: 2vmin;
}

/* The picture first (on the right of the Hebrew page), the steps beside it. */
.help-topic-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    gap: 4vmin;
    align-items: center;
}

.help-art {
    display: block;
    width: 100%;
    height: auto;
    max-height: 56vh;
    overflow: visible;
}

.help-steps {
    display: flex;
    flex-direction: column;
    gap: 2.2vmin;
    margin: 0;
    padding: 0;
    list-style: none;
}

.help-steps li {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6vmin 1.4vmin;
    font-size: 3.7vmin;
    font-weight: 700;
    line-height: 1.25;
}

.help-steps b {
    color: var(--c);
    font-weight: 900;
}

.help-num {
    flex: none;
    display: inline-grid;
    place-items: center;
    width: 6.2vmin;
    height: 6.2vmin;
    font-size: 3.4vmin;
    font-weight: 900;
    color: #0b1020;
    background: var(--c);
    border-radius: 50%;
}

.help-step-arrow {
    flex: none;
    width: 10vmin;
    height: 5vmin;
    color: var(--c);
    stroke: currentColor;
    fill: none;
    stroke-width: 4.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.help-flip {
    transform: scaleX(-1);
}

.help-steps .help-note,
.help-note {
    font-size: 3vmin;
    font-weight: 600;
    color: var(--muted);
}

/* What to say to the display: speech chips, each with the device it talks to. */
.help-examples {
    margin-top: 3vmin;
}

.help-examples-title {
    margin: 0 0 1.6vmin;
    font-size: 3.6vmin;
    font-weight: 900;
    color: var(--c);
}

.help-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 1.6vmin;
    margin: 0 0 2vmin;
    padding: 0;
    list-style: none;
}

.help-chips li {
    display: flex;
    align-items: center;
    gap: 1.2vmin;
    padding: 1.2vmin 2.4vmin 1.2vmin 1.2vmin;
    font-size: 3.2vmin;
    font-weight: 700;
    color: #13203a;
    background: #ffffff;
    border-radius: 999px;
}

.help-chip-label {
    padding: 0.4vmin 1.6vmin;
    font-size: 2.4vmin;
    font-weight: 800;
    color: #ffffff;
    background: var(--c);
    border-radius: 999px;
}

.help-back {
    display: block;
    min-height: max(6vmin, 48px);
    margin: 3vmin auto 0;
    padding: 0 4vmin;
    font: inherit;
    font-size: 2.8vmin;
    font-weight: 800;
    color: #ffffff;
    background: transparent;
    border: 0.3vmin solid var(--c);
    border-radius: 999px;
    cursor: pointer;
}

@media (orientation: portrait) {
    .help-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .help-topic-body { grid-template-columns: minmax(0, 1fr); }
    .help-art { max-height: 40vh; }
}

/* --- The pictures' parts (user units of the 320 x 236 drawing). --- */
.help-frame { fill: #0d1520; stroke: #33445c; stroke-width: 4; }
.help-touch { fill: rgba(255, 255, 255, 0.92); stroke: rgba(255, 255, 255, 0.4); stroke-width: 8; }
.help-touch-big { stroke-width: 10; }
.help-trail {
    fill: none;
    stroke: rgba(255, 255, 255, 0.9);
    stroke-width: 5;
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-dasharray: 2 10;
    animation: help-trail 1.2s linear infinite;
}
.help-trail-head {
    fill: none;
    stroke: rgba(255, 255, 255, 0.9);
    stroke-width: 5;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.help-ripple {
    fill: none;
    stroke: #ffffff;
    stroke-width: 3;
    opacity: 0;
    transform-box: fill-box;
    transform-origin: center;
    animation: help-ripple var(--d, 3s) ease-out var(--t, 0s) infinite;
}
.help-dark-disc { fill: rgba(0, 0, 0, 0.55); }
.help-chip { fill: rgba(5, 7, 10, 0.72); stroke: rgba(255, 255, 255, 0.85); stroke-width: 2; }
.help-chip-text { fill: #ffffff; font-size: 15px; font-weight: 800; }
.help-bubble { fill: #ffffff; }
.help-bubble-text { fill: #13203a; font-size: 14px; font-weight: 800; }
.help-ring {
    fill: none;
    stroke: #ffffff;
    stroke-width: 3;
    transform-box: fill-box;
    transform-origin: center;
    animation: help-ring 1.6s ease-out infinite;
}
.help-volume-button { fill: rgba(5, 7, 10, 0.72); stroke: #ffffff; stroke-width: 2.5; }
.help-pill { fill: rgba(5, 7, 10, 0.75); stroke: #ffffff; stroke-width: 2; }
.help-pill-text { fill: #ffffff; font-size: 12px; font-weight: 800; }
.help-q-text { fill: #1d1400; font-size: 19px; font-weight: 900; }
.help-listening { fill: rgba(10, 16, 24, 0.72); stroke: rgba(110, 226, 168, 0.85); stroke-width: 2; }
.help-listening-text { fill: #ffffff; font-size: 12px; font-weight: 800; }
.help-bar-a,
.help-bar-b {
    fill: #6ee2a8;
    transform-box: fill-box;
    transform-origin: center;
    animation: help-bars 0.7s ease-in-out infinite alternate;
}
.help-bar-b { animation-delay: 0.35s; }
.help-card { fill: #121a28; stroke: rgba(255, 255, 255, 0.3); stroke-width: 2; }
.help-card-title { fill: #ffffff; font-size: 16px; font-weight: 800; }
.help-card-count { fill: #ffc300; font-size: 34px; font-weight: 900; }
.help-cancel { fill: #ef476f; }
.help-cancel-text { fill: #ffffff; font-size: 12px; font-weight: 800; }
.help-speech { fill: #ffffff; }
.help-speech-text { fill: #13203a; font-size: 14px; font-weight: 800; }
.help-panel { fill: #0f1724; stroke: #26354a; stroke-width: 2; }
.help-duty { fill: rgba(91, 157, 217, 0.16); stroke: #5b9dd9; stroke-width: 2; }
.help-duty-text { fill: #5b9dd9; font-size: 10px; font-weight: 800; }
.help-duty-big { fill: #5b9dd9; font-size: 18px; font-weight: 800; }
.help-avatar { fill: #2b3546; }
.help-avatar-text { fill: #ffffff; font-size: 15px; font-weight: 800; }
.help-row { fill: #172030; }
.help-name { fill: #ffffff; font-size: 16px; font-weight: 800; }
.help-next { fill: #9aa3b2; font-size: 10px; font-weight: 600; }
.help-home-text { fill: #7fb069; font-size: 13px; font-weight: 700; }
.help-clock-text { fill: #ffffff; font-size: 13px; font-weight: 800; }
.help-points { fill: #7fb069; font-size: 16px; font-weight: 900; }
.help-plus {
    fill: #ffc300;
    font-size: 14px;
    font-weight: 900;
    transform-box: fill-box;
    transform-origin: center;
    animation: help-plus 3s ease-out infinite;
}
.help-board-bg { fill: #0c1119; }
.help-board-title { fill: #ffffff; font-size: 12px; font-weight: 800; }
.help-ac-tiles rect { fill: #1a2332; stroke: #2b3a50; stroke-width: 1.5; }
.help-switch-on { fill: #7fb069; }
.help-switch-off { fill: #4a5568; }
.help-board-card { fill: #1a2332; stroke: #2b3a50; stroke-width: 1.5; }
.help-board-card-text { fill: #ffffff; font-size: 13px; font-weight: 800; }
.help-phone { fill: #10151f; stroke: #3a4a5e; stroke-width: 3; }
.help-phone-title { fill: #ffffff; font-size: 10px; font-weight: 800; }
.help-msg { fill: #2b3546; }
.help-add-arrow { stroke: #4dd4e8; stroke-width: 4; stroke-linecap: round; stroke-linejoin: round; }
.help-date-chip { fill: rgba(0, 0, 0, 0.45); }
.help-date-text { fill: #ffffff; font-size: 13px; font-weight: 700; }
.help-place-text { fill: #ffffff; font-size: 12px; font-weight: 800; paint-order: stroke; stroke: rgba(0, 0, 0, 0.55); stroke-width: 3; }
.help-spot {
    fill: none;
    stroke: #ffc300;
    stroke-width: 3.5;
    stroke-dasharray: 8 6;
    animation: help-spot 1.8s ease-in-out infinite;
}
.help-flame {
    transform-box: fill-box;
    transform-origin: 50% 100%;
    animation: help-flicker 1.1s ease-in-out infinite alternate;
}
.help-flame-b { animation-delay: 0.4s; }

/* Groups that grow or appear around their own middle. */
.help-pause-sign,
.help-pause-chip,
.help-zoom-pic,
.help-sent,
.help-voice-card,
.help-board,
.help-add-new {
    transform-box: fill-box;
    transform-origin: center;
}

/* --- The motions. Each chapter's parts share one cycle; a ripple's --t places it in that cycle. --- */
@keyframes help-trail { to { stroke-dashoffset: -24; } }

@keyframes help-ripple {
    0% { opacity: 1; transform: scale(0.6); }
    14% { opacity: 0; transform: scale(1.9); }
    100% { opacity: 0; transform: scale(1.9); }
}

@keyframes help-ring {
    0% { opacity: 0.9; transform: scale(1); }
    100% { opacity: 0; transform: scale(1.9); }
}

@keyframes help-bars {
    from { transform: scaleY(0.4); }
    to { transform: scaleY(1.2); }
}

@keyframes help-spot {
    0%, 100% { opacity: 0.35; }
    50% { opacity: 1; }
}

@keyframes help-flicker {
    from { transform: scale(0.92, 0.88) rotate(-3deg); }
    to { transform: scale(1.04, 1.08) rotate(3deg); }
}

@keyframes help-plus {
    0%, 20% { opacity: 0; transform: translateY(8px); }
    35%, 70% { opacity: 1; transform: none; }
    90%, 100% { opacity: 0; transform: translateY(-6px); }
}

/* A single tap at a quarter of the cycle. */
@keyframes help-single-tap {
    0%, 18% { transform: none; }
    24% { transform: translateY(5px); }
    30%, 100% { transform: none; }
}

/* Swipe: the hand crosses the photo from left to right, and the next photo comes. */
#help-swipe .help-swipe-hand { animation: help-swipe-hand 3.6s ease-in-out infinite; }
#help-swipe .help-swipe-next { animation: help-swipe-next 3.6s ease-in-out infinite; }

@keyframes help-swipe-hand {
    0% { opacity: 0; transform: none; }
    10% { opacity: 1; transform: none; }
    45% { opacity: 1; transform: translateX(140px); }
    58%, 100% { opacity: 0; transform: translateX(140px); }
}

@keyframes help-swipe-next {
    0%, 42% { opacity: 0; }
    55%, 88% { opacity: 1; }
    100% { opacity: 0; }
}

/* Double tap: two quick taps, then the pause sign and "half a minute". */
#help-pause .help-tap-hand { animation: help-double-tap 3.2s ease-in-out infinite; }
#help-pause .help-ripple-a { --d: 3.2s; --t: 0.3s; }
#help-pause .help-ripple-b { --d: 3.2s; --t: 0.55s; }
#help-pause .help-pause-sign,
#help-pause .help-pause-chip { animation: help-after-taps 3.2s ease-out infinite; }

@keyframes help-double-tap {
    0%, 6% { transform: none; }
    9% { transform: translateY(5px); }
    13% { transform: none; }
    17% { transform: translateY(5px); }
    21%, 100% { transform: none; }
}

@keyframes help-after-taps {
    0%, 22% { opacity: 0; transform: scale(0.8); }
    30%, 88% { opacity: 1; transform: none; }
    100% { opacity: 0; transform: none; }
}

/* Pinch: two fingers move apart and the picture grows. */
#help-zoom .help-zoom-pic { animation: help-zoom-pic 3.6s ease-in-out infinite; }
#help-zoom .help-zoom-a { animation: help-zoom-a 3.6s ease-in-out infinite; }
#help-zoom .help-zoom-b { animation: help-zoom-b 3.6s ease-in-out infinite; }

@keyframes help-zoom-pic {
    0%, 15% { transform: none; }
    50%, 76% { transform: scale(1.7); }
    92%, 100% { transform: none; }
}

@keyframes help-zoom-a {
    0% { opacity: 0; transform: none; }
    8%, 15% { opacity: 1; transform: none; }
    50% { opacity: 1; transform: translate(-58px, 38px); }
    62%, 100% { opacity: 0; transform: translate(-58px, 38px); }
}

@keyframes help-zoom-b {
    0% { opacity: 0; transform: none; }
    8%, 15% { opacity: 1; transform: none; }
    50% { opacity: 1; transform: translate(58px, -38px); }
    62%, 100% { opacity: 0; transform: translate(58px, -38px); }
}

/* Telegram: a tap on the blue button, then "sent". */
#help-share .help-tap-hand { animation: help-single-tap 3s ease-in-out infinite; }
#help-share .help-ripple-a { --d: 3s; --t: 0.72s; }
#help-share .help-sent { animation: help-sent 3s ease-out infinite; }

@keyframes help-sent {
    0%, 30% { opacity: 0; transform: translateY(6px) scale(0.9); }
    38%, 86% { opacity: 1; transform: none; }
    100% { opacity: 0; transform: none; }
}

/* Volume: a tap on the speaker turns it orange and the sound comes out. */
#help-volume .help-tap-hand { animation: help-single-tap 3s ease-in-out infinite; }
#help-volume .help-ripple-a { --d: 3s; --t: 0.72s; }
#help-volume .help-volume-button { animation: help-volume-on 3s ease-out infinite; }
#help-volume .help-waves { animation: help-waves 3s ease-out infinite; }

@keyframes help-volume-on {
    0%, 24% { fill: rgba(5, 7, 10, 0.72); }
    27%, 88% { fill: #ff8c42; }
    100% { fill: rgba(5, 7, 10, 0.72); }
}

@keyframes help-waves {
    0%, 26% { opacity: 0; }
    32%, 86% { opacity: 1; }
    100% { opacity: 0; }
}

/* Hide: a double tap, the pill and the "?", a tap on the pill, and the photo is gone. */
#help-hide .help-hide-hand { animation: help-hide-hand 5s ease-in-out infinite; }
#help-hide .help-ripple-a { --d: 5s; --t: 0.35s; }
#help-hide .help-ripple-b { --d: 5s; --t: 0.65s; }
#help-hide .help-ripple-c { --d: 5s; --t: 2.2s; }
#help-hide .help-hide-pill { animation: help-hide-pill 5s ease-out infinite; }
#help-hide .help-hide-pic { animation: help-hide-pic 5s ease-in-out infinite; }

@keyframes help-hide-hand {
    0% { opacity: 0; transform: none; }
    4% { opacity: 1; transform: none; }
    7% { transform: translateY(5px); }
    10% { transform: none; }
    13% { transform: translateY(5px); }
    16%, 28% { transform: none; }
    40% { transform: translate(-34px, 72px); }
    44% { transform: translate(-34px, 77px); }
    48% { opacity: 1; transform: translate(-34px, 72px); }
    58%, 100% { opacity: 0; transform: translate(-34px, 72px); }
}

@keyframes help-hide-pill {
    0%, 16% { opacity: 0; }
    21%, 50% { opacity: 1; }
    56%, 100% { opacity: 0; }
}

@keyframes help-hide-pic {
    0%, 48% { opacity: 1; }
    58%, 92% { opacity: 0; }
    100% { opacity: 1; }
}

/* Voice: "hey Jarvis", "I'm listening", the command, then the card with its countdown. */
#help-voice .help-say-a { animation: help-say-a 8s ease-out infinite; }
#help-voice .help-voice-badge { animation: help-voice-badge 8s ease-out infinite; }
#help-voice .help-say-b { animation: help-say-b 8s ease-out infinite; }
#help-voice .help-voice-card { animation: help-voice-card 8s ease-out infinite; }

@keyframes help-say-a {
    0% { opacity: 0; transform: translateY(6px); }
    4%, 22% { opacity: 1; transform: none; }
    27%, 100% { opacity: 0; transform: none; }
}

@keyframes help-voice-badge {
    0%, 20% { opacity: 0; }
    25%, 52% { opacity: 1; }
    56%, 100% { opacity: 0; }
}

@keyframes help-say-b {
    0%, 32% { opacity: 0; transform: translateY(6px); }
    36%, 56% { opacity: 1; transform: none; }
    60%, 100% { opacity: 0; transform: none; }
}

@keyframes help-voice-card {
    0%, 56% { opacity: 0; transform: scale(0.9); }
    62%, 94% { opacity: 1; transform: none; }
    100% { opacity: 0; transform: none; }
}

/* Home devices: a double tap on the duty row, and the board opens over the photo. */
#help-home .help-home-hand { animation: help-home-hand 5s ease-in-out infinite; }
#help-home .help-ripple-a { --d: 5s; --t: 0.3s; }
#help-home .help-ripple-b { --d: 5s; --t: 0.6s; }
#help-home .help-board { animation: help-board 5s ease-out infinite; }

@keyframes help-home-hand {
    0% { opacity: 0; transform: none; }
    3% { opacity: 1; transform: none; }
    6% { transform: translateY(5px); }
    9% { transform: none; }
    12% { transform: translateY(5px); }
    15% { opacity: 1; transform: none; }
    26%, 100% { opacity: 0; transform: none; }
}

@keyframes help-board {
    0%, 18% { opacity: 0; transform: translateY(8px); }
    26%, 92% { opacity: 1; transform: none; }
    100% { opacity: 0; transform: none; }
}

/* A new photo: it lands in the family's Telegram group, then on the screen. */
#help-add .help-add-sent { animation: help-add-sent 4s ease-out infinite; }
#help-add .help-add-arrow { animation: help-add-arrow 4s ease-in-out infinite; }
#help-add .help-add-new { animation: help-add-new 4s ease-out infinite; }

@keyframes help-add-sent {
    0% { opacity: 0; transform: translateY(10px); }
    10%, 92% { opacity: 1; transform: none; }
    100% { opacity: 0; transform: none; }
}

@keyframes help-add-arrow {
    0%, 20% { opacity: 0; transform: none; }
    30% { opacity: 1; transform: none; }
    45% { opacity: 1; transform: translateX(-6px); }
    55%, 100% { opacity: 0; transform: translateX(-6px); }
}

@keyframes help-add-new {
    0%, 42% { opacity: 0; transform: scale(0.92); }
    52%, 92% { opacity: 1; transform: none; }
    100% { opacity: 0; transform: none; }
}

/* ------------------------------------------------------------------------------- the kid's card */

/* The tiny mark beside a roster name while the member's WhatsApp groups hold unread messages. */
.chores-member-unread {
    display: inline-block;
    width: 1.3vmin;
    height: 1.3vmin;
    margin-inline-start: 0.8vmin;
    vertical-align: super;
    border-radius: 50%;
    background: #ff5d6c;
    box-shadow: 0 0 1vmin rgba(255, 93, 108, 0.8);
}

/* The card covers the photo area beside the roster, like the home board (z-index 25: below the
   voice-action card, pairing and the Google Photos setup). */
.kid-card {
    position: absolute;
    inset: 0;
    z-index: 25;
    display: flex;
    flex-direction: column;
    gap: 1.8vmin;
    padding: 2.6vmin 3.2vmin;
    background:
        radial-gradient(120% 80% at 85% 0%, rgba(91, 157, 217, 0.16), transparent 60%),
        linear-gradient(180deg, #0c1119 0%, #06090e 100%);
    touch-action: manipulation;
    animation: home-in 260ms ease-out;
    overflow: hidden;
}

#stage.with-chores .kid-card {
    left: 25%;
}

/* The way out, plainly: "חזרה לתמונות", white on the dark card. */
.kid-close {
    position: absolute;
    top: 2.2vmin;
    inset-inline-end: 3vmin;
    z-index: 1;
    min-width: 22vmin;
    min-height: max(7vmin, 52px);
    padding: 0 3vmin;
    font: inherit;
    font-size: 2.9vmin;
    font-weight: 800;
    color: #05070a;
    background: #f2f4f7;
    border: 0;
    border-radius: 999px;
    box-shadow: 0 0.4vmin 1.6vmin rgba(0, 0, 0, 0.5);
}

.kid-loading {
    margin: auto;
    font-size: 3.4vmin;
    color: var(--muted);
}

.kid-head {
    display: flex;
    align-items: center;
    gap: 2.4vmin;
}

.kid-avatar {
    width: 12vmin;
    height: 12vmin;
    flex: none;
    display: grid;
    place-items: center;
    overflow: hidden;
    border-radius: 50%;
    border: 0.4vmin solid #6fb6e8;
    background: #232a3a;
}

.kid-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.kid-avatar-initial {
    font-size: 5vmin;
    font-weight: 800;
}

.kid-name {
    margin: 0;
    font-size: 5.4vmin;
    font-weight: 800;
}

.kid-total {
    font-size: 2.8vmin;
    color: var(--muted);
}

.kid-total b {
    font-size: 4vmin;
    color: var(--ok);
}

.kid-give {
    margin-inline-start: 4vmin;
    min-height: max(6.4vmin, 48px);
    padding: 0 3.2vmin;
    font: inherit;
    font-size: 2.7vmin;
    font-weight: 800;
    color: #05070a;
    background: linear-gradient(180deg, #ffd166, #f4a940);
    border: 0;
    border-radius: 999px;
}

.kid-columns {
    flex: 1 1 auto;
    min-height: 0;
    display: grid;
    grid-template-columns: 1.05fr 1fr;
    gap: 2.6vmin;
}

.kid-side {
    display: flex;
    flex-direction: column;
    gap: 2vmin;
    min-height: 0;
}

.kid-box {
    min-height: 0;
    overflow: hidden;
    padding: 1.8vmin 2.2vmin;
    border-radius: 2vmin;
    background: rgba(255, 255, 255, 0.05);
    border: 0.2vmin solid rgba(154, 163, 178, 0.18);
}

.kid-recent {
    flex: 1 1 auto;
}

.kid-box h3 {
    margin: 0 0 1.2vmin;
    font-size: 2.5vmin;
    color: #6fb6e8;
}

.kid-box h3 span {
    font-size: 1.8vmin;
    font-weight: 400;
    color: var(--muted);
}

.kid-empty {
    margin: 1vmin 0;
    font-size: 2.1vmin;
    color: var(--muted);
}

.kid-bar {
    display: flex;
    align-items: center;
    gap: 1.2vmin;
    margin: 1vmin 0;
    font-size: 2.1vmin;
}

.kid-bar-label {
    width: 22vmin;
    flex: none;
}

.kid-track {
    flex: 1 1 auto;
    height: 2vmin;
    overflow: hidden;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.07);
}

.kid-fill {
    height: 100%;
    border-radius: 999px;
    background: linear-gradient(90deg, #7fb069, #b5e48c);
}

.kid-bar-num {
    width: 6vmin;
    flex: none;
    text-align: end;
    font-weight: 700;
    color: #b5e48c;
}

.kid-award {
    display: flex;
    justify-content: space-between;
    gap: 1vmin;
    padding: 0.8vmin 0;
    font-size: 1.95vmin;
    color: #d6dbe4;
    border-bottom: 0.1vmin solid rgba(255, 255, 255, 0.06);
}

.kid-award b {
    color: var(--ok);
}

.kid-likes-title {
    margin-top: 2vmin !important;
}

.kid-messages {
    overflow-y: auto;
}

.kid-message {
    padding: 0.9vmin 0;
    border-bottom: 0.1vmin solid rgba(255, 255, 255, 0.06);
}

.kid-message.new {
    padding-inline-start: 1.2vmin;
    border-inline-start: 0.5vmin solid #ff5d6c;
}

.kid-meta {
    font-size: 1.6vmin;
    color: var(--muted);
}

.kid-text {
    font-size: 2.05vmin;
    line-height: 1.35;
    overflow-wrap: anywhere;
}

/* "הענקת נקודות": a panel over the card. */
.kid-gift {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    background: rgba(5, 7, 10, 0.72);
}

.kid-gift-box {
    width: min(90%, 110vmin);
    padding: 3vmin;
    border-radius: 3vmin;
    background: #121826;
    border: 0.25vmin solid rgba(255, 209, 102, 0.5);
    text-align: center;
}

.kid-gift-box h2 {
    margin: 0 0 2vmin;
    font-size: 3.4vmin;
}

.kid-gift-cost {
    margin: 1vmin 0 2vmin;
    font-size: 3vmin;
    font-weight: 800;
    color: #ffb36b;
}

.kid-chip.kid-confirm {
    background: #3f8f4f;
    border-color: #5fbf6f;
    color: #fff;
}

.kid-award-minus {
    color: #ff8a8a;
}

.kid-chip:disabled {
    opacity: 0.35;
}

.kid-gift-note {
    font-size: 2.3vmin;
    color: var(--muted);
}

.kid-gift-done {
    color: var(--ok);
}

.kid-gift-failed {
    color: var(--error);
    font-size: 2.3vmin;
}

.kid-chips {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 1.4vmin;
    margin: 1.6vmin 0;
}

.kid-chip {
    min-width: 12vmin;
    min-height: max(6.4vmin, 48px);
    padding: 0 2.6vmin;
    font: inherit;
    font-size: 2.8vmin;
    font-weight: 700;
    color: var(--text);
    background: rgba(255, 255, 255, 0.08);
    border: 0.2vmin solid rgba(255, 255, 255, 0.18);
    border-radius: 999px;
}

.kid-points .kid-chip {
    min-width: 9vmin;
    color: #05070a;
    background: linear-gradient(180deg, #ffd166, #f4a940);
    border: 0;
}

.kid-chip:disabled {
    opacity: 0.4;
}

.kid-cancel {
    margin-top: 1.4vmin;
}

@media (orientation: portrait) {
    #stage.with-chores .kid-card { left: 30%; }
    .kid-columns { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------------------------------ "אהבתי" (likes) */

/* The heart: above the share button, or above the volume button on a clip (`above-volume`). */
.like-button {
    position: absolute;
    bottom: calc(3vmin + max(5.5vmin, 40px) + 1.6vmin);
    inset-inline-start: 3vmin;
    z-index: 5;
    width: 5.5vmin;
    height: 5.5vmin;
    min-width: 40px;
    min-height: 40px;
    padding: 0;
    background: rgba(5, 7, 10, 0.62) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23ff5d6c' d='M12 21s-7.5-4.6-10-9.3C.4 8.6 2.2 4.5 6 4.5c2.2 0 3.6 1.2 4.5 2.6.3.5.9.5 1.2 0 .9-1.4 2.3-2.6 4.5-2.6 3.8 0 5.6 4.1 4 7.2C19.5 16.4 12 21 12 21z'/%3E%3C/svg%3E") center / 58% no-repeat;
    border: 0.25vmin solid rgba(242, 244, 247, 0.85);
    border-radius: 50%;
    box-shadow: 0 0.3vmin 1.2vmin rgba(0, 0, 0, 0.45);
    cursor: pointer;
}

.like-button.above-volume {
    bottom: calc(3vmin + 2 * (max(5.5vmin, 40px) + 1.6vmin));
}

.like-button.open {
    border-color: #ff5d6c;
    box-shadow: 0 0 0 0.4vmin rgba(255, 93, 108, 0.35), 0 0.3vmin 1.2vmin rgba(0, 0, 0, 0.45);
}

/* "מי אוהב את התמונה?": the roster's names beside the heart. */
.like-panel {
    position: absolute;
    bottom: 3vmin;
    inset-inline-start: calc(3vmin + max(5.5vmin, 40px) + 2vmin);
    z-index: 6;
    width: min(52vmin, 60%);
    padding: 2vmin 2.2vmin;
    border-radius: 2.4vmin;
    background: rgba(12, 17, 25, 0.88);
    border: 0.2vmin solid rgba(255, 255, 255, 0.18);
    backdrop-filter: blur(14px);
}

.like-title {
    margin: 0 0 1.4vmin;
    font-size: 2.6vmin;
    font-weight: 800;
}

.like-close {
    position: absolute;
    top: 1.2vmin;
    inset-inline-end: 1.2vmin;
    width: 5.6vmin;
    height: 5.6vmin;
    min-width: 44px;
    min-height: 44px;
    padding: 0;
    font: inherit;
    font-size: 3.4vmin;
    font-weight: 700;
    line-height: 1;
    color: var(--text);
    background: rgba(255, 255, 255, 0.14);
    border: 0.25vmin solid rgba(242, 244, 247, 0.6);
    border-radius: 50%;
}

.like-title {
    padding-inline-end: 7vmin;
}

.like-names {
    display: flex;
    flex-wrap: wrap;
    gap: 1.1vmin;
}

.like-name {
    min-height: max(5.6vmin, 44px);
    padding: 0 2.2vmin;
    font: inherit;
    font-size: 2.4vmin;
    font-weight: 700;
    color: var(--text);
    background: rgba(255, 255, 255, 0.08);
    border: 0.2vmin solid rgba(255, 255, 255, 0.15);
    border-radius: 999px;
}

.like-name.on {
    color: #fff;
    background: #ff5d6c;
    border-color: #ff5d6c;
}

.like-failed {
    margin: 1.2vmin 0 0;
    font-size: 2vmin;
    color: var(--error);
}

/* The card's "צפייה בתמונות" and the bar the tour shows over the photos. */
.kid-show-likes {
    min-height: max(5.4vmin, 42px);
    padding: 0 2.6vmin;
    font: inherit;
    font-size: 2.3vmin;
    font-weight: 700;
    color: #fff;
    background: #ff5d6c;
    border: 0;
    border-radius: 999px;
}

.likes-tour {
    position: absolute;
    bottom: 3vmin;
    left: 50%;
    z-index: 6;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    gap: 2vmin;
    padding: 1.2vmin 1.4vmin 1.2vmin 2.4vmin;
    border-radius: 999px;
    background: rgba(12, 17, 25, 0.82);
    border: 0.2vmin solid rgba(255, 93, 108, 0.6);
    font-size: 2.5vmin;
    font-weight: 700;
}

#stage.with-chores .likes-tour {
    left: 62.5%;
}

.likes-tour-stop {
    min-height: max(5vmin, 40px);
    padding: 0 2.2vmin;
    font: inherit;
    font-size: 2.2vmin;
    font-weight: 700;
    color: var(--text);
    background: rgba(255, 255, 255, 0.1);
    border: 0.2vmin solid rgba(255, 255, 255, 0.3);
    border-radius: 999px;
}

/* --------------------------------------------------------------------- the Shabbat screen */

/* Over the photo area beside the roster through the quiet window, four minutes of every five
   (shabbat/screen.js). Below the shopping / HTML takeovers (20), the home board and the kid's
   card (25); above the photos and their buttons. */
.shabbat-screen {
    position: absolute;
    inset: 0;
    z-index: 15;
    display: flex;
    flex-direction: column;
    gap: 2.4vmin;
    padding: 3vmin 4vmin;
    color: #f4ead6;
    background:
        radial-gradient(90% 70% at 50% 0%, rgba(255, 196, 92, 0.18), transparent 65%),
        linear-gradient(180deg, #14100a 0%, #07060a 100%);
    animation: home-in 400ms ease-out;
}

#stage.with-chores .shabbat-screen {
    left: 25%;
}

.shabbat-candles {
    display: flex;
    justify-content: center;
    gap: 6vmin;
    flex: 0 0 auto;
    height: 13vmin;
    padding-top: 1vmin;
    align-items: flex-end;
}

.shabbat-candle {
    position: relative;
    width: 2.6vmin;
    height: 7.5vmin;
    border-radius: 0.5vmin;
    background: linear-gradient(90deg, #e9e1d2, #fffaf0 45%, #d2c9b8);
    box-shadow: 0 0 3vmin rgba(255, 190, 80, 0.18);
}

/* The wick, under the flame. */
.shabbat-candle::before {
    content: '';
    position: absolute;
    left: 50%;
    bottom: 100%;
    width: 0.3vmin;
    height: 0.9vmin;
    transform: translateX(-50%);
    border-radius: 0.2vmin;
    background: #3b2a1a;
}

/* Warm light around the flame: grows and fades, never in step with the flame itself. */
.shabbat-candle::after {
    content: '';
    position: absolute;
    left: 50%;
    bottom: 100%;
    width: 11vmin;
    height: 11vmin;
    margin-left: -5.5vmin;
    margin-bottom: -2.5vmin;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(255, 196, 92, 0.45) 0%, rgba(255, 160, 60, 0.12) 45%, rgba(255, 140, 40, 0) 70%);
    pointer-events: none;
    animation: shabbat-glow 2.6s ease-in-out infinite;
}

.shabbat-flame {
    position: absolute;
    left: 50%;
    bottom: 100%;
    width: 2vmin;
    height: 3.6vmin;
    margin-left: -1vmin;
    margin-bottom: 0.5vmin;
    transform-origin: 50% 100%;
    border-radius: 50% 50% 45% 45% / 65% 65% 35% 35%;
    background: radial-gradient(circle at 50% 75%, #ffffff 0%, #fff3b0 22%, #ffc94a 50%, #ff8a1f 85%, rgba(255, 110, 20, 0.6) 100%);
    box-shadow: 0 0 2.6vmin rgba(255, 190, 80, 0.85), 0 -0.6vmin 3.4vmin rgba(255, 150, 50, 0.45);
    animation: shabbat-flicker 1.7s ease-in-out infinite;
}

/* The blue root of a real flame, at its base. */
.shabbat-flame::after {
    content: '';
    position: absolute;
    left: 50%;
    bottom: 0.1vmin;
    width: 0.9vmin;
    height: 0.9vmin;
    margin-left: -0.45vmin;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(120, 170, 255, 0.85), rgba(120, 170, 255, 0));
}

/* The second candle is never in step with the first. */
.shabbat-candle:nth-child(2) .shabbat-flame {
    animation-duration: 2.1s;
    animation-delay: -0.8s;
}

.shabbat-candle:nth-child(2)::after {
    animation-duration: 3.1s;
    animation-delay: -1.3s;
}

/* Sway from the wick, stretch and shrink, lean back: uneven steps so it reads as a live flame. */
@keyframes shabbat-flicker {
    0% { transform: rotate(-2deg) scale(1, 1); }
    15% { transform: rotate(3deg) scale(0.94, 1.1); }
    30% { transform: rotate(-1deg) scale(1.04, 0.95); }
    45% { transform: rotate(4deg) scale(0.92, 1.14); }
    60% { transform: rotate(-3deg) scale(1.02, 0.98); }
    75% { transform: rotate(1deg) scale(0.96, 1.08); }
    90% { transform: rotate(-4deg) scale(1.03, 0.96); }
    100% { transform: rotate(-2deg) scale(1, 1); }
}

@keyframes shabbat-glow {
    0%, 100% { opacity: 0.75; transform: scale(1); }
    35% { opacity: 1; transform: scale(1.12); }
    65% { opacity: 0.6; transform: scale(0.94); }
}

.shabbat-title {
    margin: 0;
    text-align: center;
    font-size: 7vmin;
    font-weight: 800;
    color: #ffe2a8;
}

.shabbat-menus {
    flex: 1 1 auto;
    min-height: 0;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2.6vmin;
}

.shabbat-menu {
    min-height: 0;
    overflow: hidden;
    padding: 2.2vmin 3vmin;
    border-radius: 2.6vmin;
    background: rgba(255, 226, 168, 0.06);
    border: 0.2vmin solid rgba(255, 226, 168, 0.25);
}

.shabbat-menu h3 {
    margin: 0 0 1.2vmin;
    font-size: 3.4vmin;
    color: #ffcf70;
}

.shabbat-menu ul {
    margin: 0;
    padding-inline-start: 3vmin;
    font-size: 2.9vmin;
}

/* A long menu: two columns, filled down the first, then the second. */
.shabbat-menu ul.two-columns {
    column-count: 2;
    column-gap: 3vmin;
}

.shabbat-menu li {
    margin: 0.6vmin 0;
    font-size: inherit;
    break-inside: avoid;
}

.shabbat-unknown {
    font-size: 2.6vmin;
    color: #8d7f66;
}

.shabbat-facts {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 2vmin;
}

.shabbat-fact {
    padding: 2vmin 1.8vmin;
    text-align: center;
    border-radius: 2.2vmin;
    background: rgba(255, 255, 255, 0.05);
    border: 0.2vmin solid rgba(255, 255, 255, 0.12);
}

.shabbat-q {
    font-size: 2.3vmin;
    color: #c9b48f;
}

.shabbat-a {
    margin-top: 0.6vmin;
    font-size: 3.6vmin;
    font-weight: 800;
}

.shabbat-a.yes { color: #9fe07a; }
.shabbat-a.no { color: #ff8a8a; }
.shabbat-a.info { color: #ffe2a8; }
.shabbat-a.unknown { color: #8d7f66; }

.shabbat-times {
    align-self: center;
    text-align: center;
    margin-top: -1vmin;
    padding: 0.8vmin 2.6vmin;
    border-radius: 999px;
    font-size: 3.4vmin;
    font-weight: 700;
    color: #ffe2a8;
    background: rgba(224, 184, 114, 0.12);
    border: 0.2vmin solid rgba(224, 184, 114, 0.35);
}

.shabbat-times:empty {
    display: none;
}

.shabbat-credit {
    margin-inline-start: 2vmin;
    opacity: 0.8;
}

.shabbat-activity {
    padding: 1.6vmin 2vmin;
    text-align: center;
    border-radius: 2.2vmin;
    background: rgba(224, 184, 114, 0.1);
    border: 0.2vmin solid rgba(224, 184, 114, 0.35);
}

.shabbat-activity .shabbat-a {
    font-size: 3.4vmin;
    overflow-wrap: anywhere;
}

.shabbat-next {
    font-size: 2vmin;
    color: #8d7f66;
}

@media (orientation: portrait) {
    #stage.with-chores .shabbat-screen { left: 30%; }
    .shabbat-menus { grid-template-columns: 1fr; }
    .shabbat-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (prefers-reduced-motion: reduce) {
    .shabbat-screen { animation: none; }
    .shabbat-flame, .shabbat-candle::after { animation: none; }
}

/* The countdown bar (countdown/bar.js): a thin, quiet bar on the right edge, the side away from the
   chore roster; it shrinks toward the bottom until the screen changes. Above the Shabbat screen and
   the takeovers (15, 20), below the boards, the card and the guide (25+). */
.countdown-bar {
    position: fixed;
    top: 0;
    bottom: 0;
    right: 0;
    width: 0.5vmin;
    z-index: 24;
    pointer-events: none;
    border-radius: 0.3vmin 0 0 0.3vmin;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0.28));
    box-shadow: 0 0 0.8vmin rgba(255, 255, 255, 0.18);
    transform-origin: 50% 100%;
    will-change: transform;
}
