/* ===========================================
   The Reality — pinned lockscreen, scrolling copy

   One phone stays pinned while the four explanations move past it, and each
   one adds to the notification stack. The visual is a single object being
   buried rather than four separate cards crossfading, so scroll progress and
   accumulating load are the same movement.
   Loaded after styles.css; nothing here is shared with the other pages.
   =========================================== */
.scrolly {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4rem;
    /* Both columns stretch to the row height. A sticky element can only
       travel as far as its parent is tall, so the media column has to be
       as tall as the copy column — `align-items: start` would collapse it
       to the canvas height and the pin would last zero pixels. */
    align-items: stretch;
}

.scrolly-media { position: relative; height: 100%; }

.scrolly-canvas {
    position: sticky;
    top: calc(50vh - 17rem);   /* centres a 34rem phone in the viewport */
    height: 34rem;
    display: flex;
    justify-content: center;
}

/* --- the phone ------------------------------------------------------------ */
/* The shell, screen, island, status bar and home indicator are shared with the
   chat phone in the capabilities section — the two are meant to read as the
   same device, once buried and once answering. Only the height and what's on
   the screen belong to a particular section. */
.phone {
    --phone-bezel: #1c1c22;
    --phone-screen-top: #12141a;
    --phone-screen-bottom: #07080b;
    --phone-ink: #f5f5f5;
    --phone-ink-dim: rgba(245, 245, 245, 0.55);
    --phone-card: rgba(255, 255, 255, 0.09);
    --phone-card-border: rgba(255, 255, 255, 0.12);

    position: relative;
    width: 17.5rem;
}

.scrolly-canvas .phone { height: 34rem; }

/* A lit screen at night is the whole point of the third step, so the wallpaper
   stays dark there rather than following the page into light mode. */
body.light-mode .phone:not(.is-night) {
    --phone-bezel: #d8dcE0;
    --phone-screen-top: #eef1f4;
    --phone-screen-bottom: #dde3e8;
    --phone-ink: #171717;
    --phone-ink-dim: rgba(23, 23, 23, 0.5);
    --phone-card: rgba(255, 255, 255, 0.75);
    --phone-card-border: rgba(0, 0, 0, 0.07);
}

/* 3:47 AM: colder, dimmer, and still the brightest thing in the room. */
.phone.is-night {
    --phone-screen-top: #0b1119;
    --phone-screen-bottom: #05070b;
}

/* The sprite is a definitions block, not a drawing. */
.phone-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.phone-glow {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 150%;
    height: 85%;
    transform: translate(-50%, -50%);
    background: radial-gradient(ellipse at center,
        rgba(92, 236, 211, 0.16) 0%,
        rgba(173, 251, 246, 0.07) 38%,
        transparent 70%);
    pointer-events: none;
    transition: opacity 600ms var(--ease-out);
}

body.light-mode .phone-glow { opacity: 0.45; }

.phone-shell {
    position: absolute;
    inset: 0;
    border: 6px solid var(--phone-bezel);
    border-radius: 40px;
    background: var(--phone-bezel);
    box-shadow:
        0 30px 70px rgba(0, 0, 0, 0.55),
        0 0 0 1px rgba(120, 120, 135, 0.25),
        inset 0 1px 0 rgba(255, 255, 255, 0.07);
    transition: border-color 600ms var(--ease-out);
}

body.light-mode .phone-shell { box-shadow: var(--shadow-lg), 0 0 0 1px rgba(0, 0, 0, 0.06); }

.phone-screen {
    position: absolute;
    inset: 0;
    border-radius: 34px;
    overflow: hidden;
    background: linear-gradient(180deg, var(--phone-screen-top) 0%, var(--phone-screen-bottom) 100%);
    transition: background 600ms var(--ease-out);
}

.phone-island {
    position: absolute;
    left: 50%;
    top: 9px;
    width: 84px;
    height: 20px;
    transform: translateX(-50%);
    background: #000;
    border-radius: 12px;
    z-index: 3;
}

/* --- status bar ----------------------------------------------------------- */
.phone-status {
    position: absolute;
    top: 14px;
    left: 0;
    right: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 20px;
    color: var(--phone-ink);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    z-index: 2;
}

.phone-status-icons { display: flex; align-items: center; gap: 5px; }
.phone-cell { display: flex; align-items: flex-end; gap: 1.5px; }
.phone-cell span { width: 2px; background: currentColor; border-radius: 1px; }
.phone-cell span:nth-child(1) { height: 3px; }
.phone-cell span:nth-child(2) { height: 5px; }
.phone-cell span:nth-child(3) { height: 7px; }
.phone-cell span:nth-child(4) { height: 9px; }

.phone-battery {
    position: relative;
    width: 17px;
    height: 9px;
    border: 1px solid currentColor;
    border-radius: 2.5px;
    opacity: 0.7;
}

.phone-battery::after {
    content: '';
    position: absolute;
    inset: 1.5px;
    right: 60%;   /* the battery is not the story, but it isn't full either */
    background: currentColor;
    border-radius: 1px;
}

/* --- clock block ---------------------------------------------------------- */
.phone-lock {
    position: absolute;
    top: 3.4rem;
    left: 0;
    right: 0;
    text-align: center;
    color: var(--phone-ink);
    z-index: 2;
}

.phone-date {
    font-size: 0.72rem;
    letter-spacing: 0.02em;
    color: var(--phone-ink-dim);
}

.phone-clock {
    font-family: var(--font-serif);
    font-size: 3.5rem;
    line-height: 1.05;
    letter-spacing: -0.02em;
}

.phone-clock em {
    font-family: var(--font-sans);
    font-style: normal;
    font-size: 0.95rem;
    margin-left: 0.35rem;
    color: var(--phone-ink-dim);
}

/* The count is the number the reader is meant to feel, so it gets the one
   piece of chrome on the screen. */
.phone-count {
    display: inline-block;
    margin-top: 0.5rem;
    padding: 0.2rem 0.7rem;
    border-radius: 999px;
    background: var(--phone-card);
    border: 1px solid var(--phone-card-border);
    font-size: 0.68rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--phone-ink-dim);
    transition: color 500ms var(--ease-out), border-color 500ms var(--ease-out);
}

.phone-count [data-phone-count] {
    font-variant-numeric: tabular-nums;   /* no width jitter while it counts */
    font-weight: 600;
    color: var(--phone-ink);
}

/* Past the point where a person could plausibly catch up. */
.phone.is-buried .phone-count {
    color: var(--gold-light);
    border-color: rgba(212, 168, 87, 0.35);
}

.phone.is-buried .phone-count [data-phone-count] { color: var(--gold-light); }

/* Swapped text leaves before it arrives, rather than cutting. */
.phone-date,
.phone-clock span,
.phone-status-time {
    display: inline-block;
    transition: opacity 180ms var(--ease-out), transform 180ms var(--ease-out);
}

.is-swapping { opacity: 0; transform: translateY(-4px); }

/* --- the stack ------------------------------------------------------------ */
.phone-stack {
    position: absolute;
    left: 0;
    right: 0;
    top: 12.5rem;
    bottom: 1.9rem;
    padding: 0 0.7rem;
    margin: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    /* Bottom-anchored: a new notification takes its place at the bottom and
       pushes the older ones up under the fade, exactly as a real lockscreen
       does. No FLIP needed — the layout does it. */
    justify-content: flex-end;
    overflow: hidden;
    mask-image: linear-gradient(to bottom, transparent 0, #000 3.5rem);
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 3.5rem);
    z-index: 2;
}

/* 0fr -> 1fr makes room for the card without measuring it, and reverses
   cleanly when the reader scrolls back up. The gap lives inside the inner
   element so a collapsed row leaves no space behind. */
.phone-notif {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 520ms var(--ease-drawer);
}

.phone-notif.is-in { grid-template-rows: 1fr; }

.phone-notif-inner { overflow: hidden; padding-top: 0.45rem; }

.phone-notif-card {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.5rem 0.6rem;
    border-radius: 13px;
    background: var(--phone-card);
    border: 1px solid var(--phone-card-border);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    opacity: 0;
    transform: translateY(8px) scale(0.97);
    transform-origin: 50% 100%;
    transition: opacity 300ms var(--ease-out),
                transform 460ms var(--ease-out);
}

.phone-notif.is-in .phone-notif-card {
    opacity: 1;
    transform: none;
    /* The card arrives after the room has been made for it. */
    transition-delay: 90ms;
}

.phone-notif-icon {
    flex: none;
    width: 18px;
    height: 18px;
    display: grid;
    place-items: center;
    border-radius: 5px;
    background: rgba(173, 251, 246, 0.16);
    color: var(--cyan-glow);
}

.phone-notif-icon svg {
    width: 11px;
    height: 11px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

body.light-mode .phone:not(.is-night) .phone-notif-icon {
    background: rgba(13, 115, 119, 0.12);
    color: var(--cyan-deep);
}

.phone-notif-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.05rem; }

.phone-notif-from {
    font-size: 0.66rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--phone-ink);
}

.phone-notif-body {
    font-size: 0.68rem;
    line-height: 1.35;
    color: var(--phone-ink-dim);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.phone-notif-time {
    flex: none;
    font-size: 0.6rem;
    color: var(--phone-ink-dim);
    padding-top: 0.1rem;
}

/* The one that actually matters, sized exactly like the newsletter above it. */
.phone-notif.is-urgent .phone-notif-card {
    background: rgba(173, 251, 246, 0.13);
    border-color: rgba(173, 251, 246, 0.3);
}

body.light-mode .phone:not(.is-night) .phone-notif.is-urgent .phone-notif-card {
    background: rgba(13, 115, 119, 0.09);
    border-color: rgba(13, 115, 119, 0.24);
}

.phone-notif.is-warn .phone-notif-icon { background: rgba(212, 168, 87, 0.2); color: var(--gold-light); }
.phone-notif.is-warn .phone-notif-body { color: var(--gold-light); }

body.light-mode .phone:not(.is-night) .phone-notif.is-warn .phone-notif-body { color: #8a6a20; }
body.light-mode .phone:not(.is-night) .phone-notif.is-warn .phone-notif-icon {
    background: rgba(212, 168, 87, 0.28);
    color: #8a6a20;
}

.phone-home {
    position: absolute;
    left: 50%;
    bottom: 0.5rem;
    transform: translateX(-50%);
    width: 6.5rem;
    height: 3px;
    border-radius: 999px;
    background: var(--phone-ink);
    opacity: 0.35;
    z-index: 2;
}

/* --- the copy column ------------------------------------------------------ */
.scrolly-copy { display: flex; flex-direction: column; }

.scrolly-step {
    min-height: 80vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    opacity: 0.25;
    transition: opacity 400ms var(--ease-out);
}

.scrolly-step.is-active { opacity: 1; }

.scrolly-step h3 {
    font-family: var(--font-serif);
    font-size: 1.75rem;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 1rem;
}

.scrolly-step p {
    color: var(--text-secondary);
    font-size: 1.05rem;
    line-height: 1.8;
}

/* Steps were single-paragraph until one of them needed to turn from the
   problem to the answer. A gap wider than the 1.8 line-height, or the two
   read as one block with an odd break in it. */
.scrolly-step p + p { margin-top: 1.15em; }

/* A phone taller than the viewport can't be pinned to the middle of it. */
@media (max-height: 780px) {
    .scrolly-canvas { top: calc(50vh - 14rem); height: 28rem; }
    .scrolly-canvas .phone { transform: scale(0.82); transform-origin: top center; }
}

@media (max-width: 900px) {
    .scrolly { grid-template-columns: 1fr; gap: 0; }

    /* One column, one cell: the media and the copy are stacked on top of each
       other rather than given a row each. A grid item can only stick inside
       its own grid area, so a row of its own would leave the phone nothing to
       travel through — it would scroll away before the first step and do all
       of its accumulating off screen. */
    .scrolly-media,
    .scrolly-copy { grid-area: 1 / 1; }

    .scrolly-media { pointer-events: none; z-index: 2; }

    .scrolly-canvas {
        /* Clears the fixed nav pill and theme toggle, which float above
           everything and were landing on the phone's status bar. */
        top: 3.75rem;
        height: 34rem;
        /* The copy scrolls up behind the pinned lockscreen. This is where it
           goes quiet — the fade has to sit in the padding *below* the last
           card, not across it. */
        padding-bottom: 2.5rem;
        background: linear-gradient(180deg,
            var(--bg-secondary) 0, var(--bg-secondary) calc(100% - 2.5rem), transparent 100%);
    }

    /* Sticky travels with the canvas, so the scrim above it does too. */
    .scrolly-canvas::before {
        content: '';
        position: absolute;
        left: 0;
        right: 0;
        bottom: 100%;
        height: 4rem;
        background: var(--bg-secondary);
    }

    body.light-mode .scrolly-canvas {
        background: linear-gradient(180deg,
            var(--white) 0, var(--white) calc(100% - 2.5rem), transparent 100%);
    }

    body.light-mode .scrolly-canvas::before { background: var(--white); }

    /* Between 640 and 900 the phone keeps its desktop size — a tablet in
       portrait has the height for a properly proportioned device. Below 640
       it drops the frame entirely (see the block at the end of this file). */
    .scrolly-canvas .phone { transform: none; }

    /* Clears the pinned phone so the first step isn't hidden under it. */
    .scrolly-copy { padding-top: 35rem; }

    /* At 150% the halo reached past the edge of a phone screen. */
    .phone-glow { width: 120%; }

    /* Bottom-aligned, not centred: a step goes active as it crosses the middle
       of the viewport, and the phone owns the top of it. Anchoring the text low
       in its own block puts it below the phone at exactly that moment. */
    .scrolly-step {
        min-height: 68vh;
        justify-content: flex-end;
        padding-bottom: 7vh;
    }

    .scrolly-step h3 { font-size: 1.45rem; }
}

@media (prefers-reduced-motion: reduce) {
    /* Dimming still marks the active step, just less harshly. */
    .scrolly-step { opacity: 0.55; }
    /* Notifications appear in place: the count still climbs, nothing slides. */
    .phone-notif-card { transform: none; }
}

/* ===========================================
   The lockscreen without the phone

   On a phone, a picture of a phone is a device inside a device — and the only
   way to fit one was to keep the width and cut the height, which walked the
   silhouette from phone (0.51) to square (1.00) to watch (1.22). So below 640
   the frame comes off: the section *is* the lockscreen, the reader's own
   status bar completes it, and the type goes back up to page scale because it
   is no longer pretending to be 280px wide.
   =========================================== */
@media (max-width: 640px) {
    .scrolly-canvas { height: auto; }

    .scrolly-canvas .phone {
        width: 100%;
        height: auto;
    }

    /* Nothing left to draw a device with. */
    .phone-glow,
    .phone-island,
    .phone-status,
    .phone-home { display: none; }

    .phone-shell {
        position: static;
        border: 0;
        border-radius: 0;
        background: none;
        box-shadow: none;
    }

    .phone-screen {
        position: static;
        border-radius: 0;
        overflow: visible;
        background: none;
    }

    /* --- the lockscreen, as page content ---------------------------------- */
    .phone-lock {
        position: static;
        margin-bottom: 1.25rem;
    }

    /* Smaller than the device it is imitating. A real lockscreen sets its clock
       to fill a phone held at arm's length; this one is a picture of a phone
       inside a page, and at full scale it read as a hero rather than as the
       thing the copy underneath is describing. */
    .phone-date { font-size: 0.8rem; }

    .phone-clock { font-size: 2.75rem; }
    .phone-clock em { font-size: 0.9rem; }

    .phone-count {
        margin-top: 0.5rem;
        padding: 0.28rem 0.75rem;
        font-size: 0.6875rem;
    }

    /* --- the stack, at page scale ----------------------------------------- */
    .phone-stack {
        position: static;
        padding: 0;
        /* Still bounded, just not by a screen: without a cap all nine cards
           render and the pinned block swallows the viewport. The fade stays,
           because it is what says the pile continues above. */
        max-height: 17rem;
        mask-image: linear-gradient(to bottom, transparent 0, #000 3rem);
        -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 3rem);
    }

    .phone-notif-inner { padding-top: 0.5rem; }

    .phone-notif-card {
        gap: 0.625rem;
        padding: 0.625rem 0.75rem;
        border-radius: 14px;
    }

    .phone-notif-icon { width: 22px; height: 22px; border-radius: 6px; }
    .phone-notif-icon svg { width: 13px; height: 13px; }

    .phone-notif-from { font-size: 0.75rem; }
    .phone-notif-body { font-size: 0.8125rem; line-height: 1.35; }
    .phone-notif-time { font-size: 0.6875rem; padding-top: 0.05rem; }

    /* The copy is the section; the phone is the illustration. At 1.05rem over
       1.8 a four-line paragraph ran to seven lines on a 390px screen and the
       reader lost the thread between the top of it and the bottom. */
    .scrolly-step h3 { font-size: 1.3rem; margin-bottom: 0.75rem; }
    .scrolly-step p { font-size: 0.9375rem; line-height: 1.7; }

    /* The copy has to clear the pinned lockscreen, and without a screen to
       clip against the only lever is how much of the pile shows. */
    .scrolly-copy { padding-top: 25rem; }
}

/* Shorter screens see less of the pile, not a smaller phone. */
@media (max-width: 640px) and (max-height: 720px) {
    .scrolly-canvas { top: 3.25rem; padding-bottom: 2rem; }
    .phone-lock { margin-bottom: 0.875rem; }
    .phone-date { font-size: 0.75rem; }
    .phone-clock { font-size: 2.2rem; }
    .phone-clock em { font-size: 0.8rem; }
    .phone-count { margin-top: 0.4rem; font-size: 0.65rem; }
    .phone-stack {
        max-height: 10rem;
        mask-image: linear-gradient(to bottom, transparent 0, #000 2rem);
        -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 2rem);
    }
    .scrolly-copy { padding-top: 17.25rem; }
}

@media (max-width: 640px) and (max-height: 600px) {
    .scrolly-canvas { top: 3rem; padding-bottom: 1.5rem; }
    .phone-lock { margin-bottom: 0.625rem; }
    .phone-clock { font-size: 1.85rem; }
    .phone-count { margin-top: 0.3rem; }
    .phone-stack {
        max-height: 6rem;
        mask-image: linear-gradient(to bottom, transparent 0, #000 1.5rem);
        -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 1.5rem);
    }
    .phone-notif-card { padding: 0.5rem 0.65rem; }
    .phone-notif-body { font-size: 0.75rem; }
    .scrolly-step p { font-size: 0.875rem; }
    .scrolly-copy { padding-top: 13rem; }
}

/* ===========================================
   The lockscreen wallpaper

   The Reality phone is somebody's actual phone, and nobody's actual phone has
   a gradient behind the lockscreen — it has a picture of the people the
   notifications are about. Which is the point of the section: the pile-up is
   not abstract, it is happening on top of these five faces.

   Only this phone. `[data-phone]` is the Reality lockscreen; the one in Meet
   Your AI Executive is `.chat-phone` and keeps its plain screen, because a
   thread reads against a flat ground and not against a photograph.

   Desktop only, per the ask — and because the rule not matching is also the
   reason a narrow screen never fetches the image at all.

   Served from Cloudinary rather than from assets/, through the same
   f_auto,q_auto transform the benefits rack uses: w_620 is twice the 280px
   the screen is ever drawn at, and comes back as ~75KB of WebP or AVIF
   instead of the 3.1MB original.
   =========================================== */
@media (min-width: 901px) {
    /* The photo turns over with the step — scrolly.js writes --lock-photo from
       its own STATES list, so the scrim stays one rule here and the four
       wallpapers stay one list there. This is the first step's, and the
       fallback for a browser that never runs the script.

       It has to be declared on the phone, not on .phone-screen below: the
       script sets the property on [data-phone], and a declaration on the child
       would beat the value inherited from the parent every time — which is
       exactly the bug that pinned all four steps to this one photo. */
    [data-phone] {
        --lock-photo: url('https://res.cloudinary.com/dayr3egl3/image/upload/f_auto,q_auto,w_620/v1787864618/Gemini_Generated_Image_dk2c2gdk2c2gdk2c_x27pqs.jpg');
    }

    [data-phone] .phone-screen {
        /* Two layers, photo underneath. The scrim is heavier at the top and
           bottom than through the middle: the clock sits in one end and the
           notification stack fills the other, and the faces are in between.
           It is the same reason iOS dims a wallpaper behind the time.

           One set of stops for every step of the story. The 3:47 AM state used
           to carry its own, much heavier scrim, which meant the wallpaper was
           conspicuously brighter in the four steps either side of it — the same
           photograph changing exposure as you scrolled. Both are at the darker
           setting now, and the night beat is a shift in tint plus a couple of
           points of alpha rather than a change of brightness. */
        --lock-tint: 6, 7, 10;
        --lock-dim: 0;
        background-image:
            linear-gradient(180deg,
                rgba(var(--lock-tint), calc(0.90 + var(--lock-dim))) 0%,
                rgba(var(--lock-tint), calc(0.76 + var(--lock-dim))) 26%,
                rgba(var(--lock-tint), calc(0.68 + var(--lock-dim))) 46%,
                rgba(var(--lock-tint), calc(0.85 + var(--lock-dim))) 72%,
                rgba(var(--lock-tint), calc(0.94 + var(--lock-dim))) 100%),
            var(--lock-photo);
        background-size: cover;
        background-position: center 42%;
        background-repeat: no-repeat;
    }

    /* The count pill was a 9%-white chip, which is plenty over a gradient and
       nothing at all over a lit window: measured 4.1:1 in dark mode and 3.3:1
       in light against a 4.5 requirement for text this size. Over a photograph
       it has to be an actual material — a dark, blurred chip the way a real
       lockscreen widget is — and the label goes up from 55% to 88% white. The
       notification cards below need none of this; they sit in the heavy end of
       the scrim and measured 7.7:1 and better. */
    [data-phone] .phone-count {
        background: rgba(8, 10, 14, 0.62);
        -webkit-backdrop-filter: blur(10px) saturate(140%);
        backdrop-filter: blur(10px) saturate(140%);
        border-color: rgba(255, 255, 255, 0.22);
        color: rgba(245, 245, 245, 0.88);
    }

    /* Still glass, with more substance behind it. The 9%-white veil these
       cards use is the right weight over a flat screen and far too thin over a
       photograph — the room reads straight through the words. What replaces it
       is not an opaque card: it is the same frosted material with the tint
       switched from white to dark and taken up to 46%, so the picture still
       moves under it and the text sits clearly on top. Dark rather than white
       because the ink is white; a heavier white veil over a lit photograph
       just turns pale and takes the text with it.

       Only the two tokens change: the count pill sets its own material just
       above, and the chat phone in Meet Your AI Executive is never
       `[data-phone]`, so its cards keep the lighter tint they were tuned for. */
    [data-phone].phone {
        --phone-card: rgba(18, 20, 26, 0.46);
        --phone-card-border: rgba(255, 255, 255, 0.16);
    }

    [data-phone] .phone-notif-card {
        -webkit-backdrop-filter: blur(18px) saturate(140%);
        backdrop-filter: blur(18px) saturate(140%);
    }

    /* A photo lockscreen is white-on-image whatever the system theme is doing
       — a real phone does not switch its lockscreen type to match light mode,
       and the dark ink this phone uses in light mode would be unreadable over
       the scrim. Specificity has to clear `body.light-mode .phone:not(.is-night)`
       above, hence the doubled-up selector. */
    body.light-mode [data-phone].phone:not(.is-night) {
        --phone-ink: #f5f5f5;
        --phone-ink-dim: rgba(245, 245, 245, 0.62);
        --phone-card: rgba(18, 20, 26, 0.46);
        --phone-card-border: rgba(255, 255, 255, 0.16);
    }

    /* The urgent card carries its own cyan wash, at an alpha chosen for the
       same 9%-white veil — so it needs bringing up with the rest or it would
       be the one transparent card in the stack. The signal stays in the border
       and the icon; the body just gets a colder ground than its neighbours.
       The light-mode rule it has to outrank is six classes deep, hence this. */
    [data-phone] .phone-notif.is-urgent .phone-notif-card,
    body.light-mode [data-phone].phone:not(.is-night) .phone-notif.is-urgent .phone-notif-card {
        background: rgba(16, 34, 38, 0.5);
        border-color: rgba(173, 251, 246, 0.34);
    }

    /* 3:47 AM. The screen-colour variables the night state used to work through
       are no longer painting anything here, so the beat lives in the scrim —
       but as a colder tint and three points of alpha, not as a step change in
       exposure. The room is the same room; only the hour is different. */
    [data-phone].phone.is-night .phone-screen {
        --lock-tint: 4, 6, 11;
        --lock-dim: 0.03;
    }
}
