@import 'Tripcity.Client.rsdfxsc9v4.bundle.scp.css';

/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
.components-reconnect-first-attempt-visible[b-sr3w13r5fo],
.components-reconnect-repeated-attempt-visible[b-sr3w13r5fo],
.components-reconnect-failed-visible[b-sr3w13r5fo],
.components-pause-visible[b-sr3w13r5fo],
.components-resume-failed-visible[b-sr3w13r5fo],
.components-rejoining-animation[b-sr3w13r5fo] {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible[b-sr3w13r5fo],
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation[b-sr3w13r5fo],
#components-reconnect-modal.components-reconnect-paused .components-pause-visible[b-sr3w13r5fo],
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible[b-sr3w13r5fo],
#components-reconnect-modal.components-reconnect-retrying[b-sr3w13r5fo],
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible[b-sr3w13r5fo],
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation[b-sr3w13r5fo],
#components-reconnect-modal.components-reconnect-failed[b-sr3w13r5fo],
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible[b-sr3w13r5fo] {
    display: block;
}


#components-reconnect-modal[b-sr3w13r5fo] {
    background-color: white;
    width: 20rem;
    margin: 20vh auto;
    padding: 2rem;
    border: 0;
    border-radius: 0.5rem;
    box-shadow: 0 3px 6px 2px rgba(0, 0, 0, 0.3);
    opacity: 0;
    transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity-b-sr3w13r5fo 0.5s both;
    &[open]

{
    animation: components-reconnect-modal-slideUp-b-sr3w13r5fo 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity-b-sr3w13r5fo 0.5s ease-in-out 0.3s;
    animation-fill-mode: both;
}

}

#components-reconnect-modal[b-sr3w13r5fo]::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
    animation: components-reconnect-modal-fadeInOpacity-b-sr3w13r5fo 0.5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp-b-sr3w13r5fo {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity-b-sr3w13r5fo {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity-b-sr3w13r5fo {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.components-reconnect-container[b-sr3w13r5fo] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p[b-sr3w13r5fo] {
    margin: 0;
    text-align: center;
}

#components-reconnect-modal button[b-sr3w13r5fo] {
    border: 0;
    background-color: #6b9ed2;
    color: white;
    padding: 4px 24px;
    border-radius: 4px;
}

    #components-reconnect-modal button:hover[b-sr3w13r5fo] {
        background-color: #3b6ea2;
    }

    #components-reconnect-modal button:active[b-sr3w13r5fo] {
        background-color: #6b9ed2;
    }

.components-rejoining-animation[b-sr3w13r5fo] {
    position: relative;
    width: 80px;
    height: 80px;
}

    .components-rejoining-animation div[b-sr3w13r5fo] {
        position: absolute;
        border: 3px solid #0087ff;
        opacity: 1;
        border-radius: 50%;
        animation: components-rejoining-animation-b-sr3w13r5fo 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
    }

        .components-rejoining-animation div:nth-child(2)[b-sr3w13r5fo] {
            animation-delay: -0.5s;
        }

@keyframes components-rejoining-animation-b-sr3w13r5fo {
    0% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    4.9% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    5% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 1;
    }

    100% {
        top: 0px;
        left: 0px;
        width: 80px;
        height: 80px;
        opacity: 0;
    }
}
/* /Components/Pages/Blog.razor.rz.scp.css */
/* Blog.razor.css — Rob (2026-09-03). The blog placeholder, in the tutorial's visual language.

   Scoped (Blazor CSS isolation); host project, so these rules bundle into `Tripcity.styles.css`.
   The tokens are stated rather than imported, the WP128 J7 note: glass panels over night navy,
   cyan accent, uppercase 11px labels, no Bootstrap. The same four values as `Tutorial.razor.css`. */

.deck[b-2l7ujgogtv] {
    width: min(880px, 100%);
    margin: 0 auto;
    padding: 1.4rem 1.2rem 3rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
    flex: 1;
}

.panel[b-2l7ujgogtv] {
    background: rgba(var(--tc-glass), 0.72);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border: 1px solid rgba(var(--tc-tint), 0.12);
    border-radius: 10px;
    padding: 1.1rem 1.25rem;
}

/* ---- top line ---------------------------------------------------------------------------------- */

.topline[b-2l7ujgogtv] { display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }

.back[b-2l7ujgogtv] {
    color: var(--tc-accent-hi);
    text-decoration: none;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
.back:hover[b-2l7ujgogtv] { text-decoration: underline; }

/* ---- the under-construction panel ---------------------------------------------------------------
   The panel gives up its own padding so the two tape strips can run edge to edge: `padding: 0` here
   and the inset moves onto `.site-body`, which is what makes the stripes read as barriers across
   the card rather than as two rules floating inside it. */

.site[b-2l7ujgogtv] {
    padding: 0;
    overflow: hidden;
    text-align: center;
}

.tape[b-2l7ujgogtv] {
    height: 14px;
    background: repeating-linear-gradient(-45deg, var(--tc-amber) 0 14px, #14181f 14px 28px);
    opacity: 0.85;
}

.site-body[b-2l7ujgogtv] { padding: 2.4rem 1.5rem 2.6rem; }

.cone[b-2l7ujgogtv] {
    display: inline-flex;
    color: var(--tc-amber);
    filter: drop-shadow(0 6px 18px rgba(var(--tc-amber-rgb), 0.30));
}

.kicker[b-2l7ujgogtv] {
    margin: 0.6rem 0 0;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--tc-accent);
}

.site h1[b-2l7ujgogtv] {
    margin: 0.3rem 0 0.7rem;
    font-size: clamp(2rem, 6vw, 3.2rem);
    font-weight: 800;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--tc-ink);
    text-shadow: 0 4px 24px rgba(var(--tc-shade), 0.55);
}

.lede[b-2l7ujgogtv] {
    margin: 0 auto;
    max-width: 52ch;
    font-size: 1.02rem;
    line-height: 1.6;
    color: var(--tc-text);
}

/* ---- prose and the row of doors ------------------------------------------------------------------ */

h2[b-2l7ujgogtv] { margin: 0 0 0.5rem; font-size: 1.28rem; color: var(--tc-accent); font-weight: 700; }
p[b-2l7ujgogtv] { margin: 0 0 0.7rem; color: var(--tc-text); line-height: 1.62; max-width: 74ch; }
p:last-child[b-2l7ujgogtv] { margin-bottom: 0; }
b[b-2l7ujgogtv] { color: var(--tc-ink-2); }
.muted[b-2l7ujgogtv] { color: var(--tc-label); margin: 0.8rem 0 0; line-height: 1.55; font-size: 0.94rem; }
.muted a[b-2l7ujgogtv], p a[b-2l7ujgogtv] { color: var(--tc-accent-hi); }

.row[b-2l7ujgogtv] { display: flex; flex-wrap: wrap; gap: 8px; margin: 0.9rem 0 0; }

.btn[b-2l7ujgogtv] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 9px 16px;
    border-radius: 8px;
    border: 1px solid transparent;
    background: var(--tc-accent);
    color: var(--tc-on-accent);
    font-weight: 700;
    font-size: 13px;
    text-decoration: none;
    cursor: pointer;
}

.btn:hover[b-2l7ujgogtv] { filter: brightness(1.1); }

.btn.ghost[b-2l7ujgogtv] {
    background: rgba(var(--tc-tint), 0.06);
    border-color: rgba(var(--tc-tint), 0.16);
    color: var(--tc-text-hi);
    font-weight: 600;
}

.btn.ghost:hover[b-2l7ujgogtv] { border-color: rgba(var(--tc-accent-rgb), 0.5); color: var(--tc-accent); }

/* The only motion on this page is a drop shadow, so there is nothing for `prefers-reduced-motion`
   to switch off — deliberately, not by omission. */
/* /Components/Pages/DevKit.razor.rz.scp.css */
/* DevKit.razor.css — WP128 §3.4 / J7. The developer-kit page in Home's and /api's visual language.

   Scoped (Blazor CSS isolation), so nothing here reaches Home, /api or the game. This page lives in
   the HOST project, so these rules are bundled into `Tripcity.styles.css`, which `App.razor` already
   links — /api's file is in the CLIENT project and the two never meet.

   The tokens are stated rather than imported because Api.razor.css states them the same way — glass
   panels over night navy, cyan accent, uppercase 11px labels, no Bootstrap. If those ever become
   shared variables, all three pages move together. */

.deck[b-v2ipreub5g] {
    width: min(1040px, 100%);
    margin: 0 auto;
    padding: 1.4rem 1.2rem 3rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
    flex: 1;
}

.panel[b-v2ipreub5g] {
    background: rgba(var(--tc-glass), 0.72);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border: 1px solid rgba(var(--tc-tint), 0.12);
    border-radius: 10px;
    padding: 1.1rem 1.25rem;
}

/* ---- top line and header --------------------------------------------------------------------- */

.topline[b-v2ipreub5g] { display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }

.back[b-v2ipreub5g] {
    color: var(--tc-accent-hi);
    text-decoration: none;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
.back:hover[b-v2ipreub5g] { text-decoration: underline; }

.kicker[b-v2ipreub5g] {
    margin: 0;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--tc-accent);
}

.head h1[b-v2ipreub5g] { margin: 0.35rem 0 0.6rem; font-size: 2rem; font-weight: 800; color: var(--tc-ink); }

.lede[b-v2ipreub5g] { margin: 0; font-size: 1.05rem; line-height: 1.6; color: var(--tc-text-hi); max-width: 62ch; }

.muted[b-v2ipreub5g] { color: var(--tc-label); margin: 0.6rem 0 0; line-height: 1.55; }
.muted a[b-v2ipreub5g], .callout a[b-v2ipreub5g], li a[b-v2ipreub5g], p a[b-v2ipreub5g] { color: var(--tc-accent-hi); }

/* ---- prose ------------------------------------------------------------------------------------ */

h2[b-v2ipreub5g] { margin: 0 0 0.5rem; font-size: 1.28rem; color: var(--tc-accent); font-weight: 700; }
h3[b-v2ipreub5g] { margin: 1.2rem 0 0.35rem; font-size: 1rem; color: var(--tc-ink-2); font-weight: 700; }
p[b-v2ipreub5g] { margin: 0 0 0.7rem; color: var(--tc-text); line-height: 1.62; max-width: 74ch; }
p:last-child[b-v2ipreub5g] { margin-bottom: 0; }

b[b-v2ipreub5g] { color: var(--tc-ink-2); }

code[b-v2ipreub5g] {
    background: rgba(var(--tc-accent-rgb), 0.10);
    border: 1px solid rgba(var(--tc-accent-rgb), 0.22);
    color: var(--tc-accent-hi);
    border-radius: 4px;
    padding: 0 4px;
    font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
    font-size: 0.88em;
}

.callout[b-v2ipreub5g] {
    border-left: 3px solid var(--tc-amber);
    background: rgba(var(--tc-amber-rgb), 0.08);
    padding: 0.6rem 0.85rem;
    border-radius: 0 6px 6px 0;
    color: var(--tc-amber-hi);
    margin-top: 0.9rem;
}

.foot[b-v2ipreub5g] {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--tc-dimmer);
    margin: 0.7rem 0 0;
}
.foot a[b-v2ipreub5g] { color: var(--tc-accent-hi); text-decoration: none; }
.foot a:hover[b-v2ipreub5g] { text-decoration: underline; }
.foot em[b-v2ipreub5g] { color: var(--tc-accent-hi); font-style: normal; }

/* ---- the manifest tallies ---------------------------------------------------------------------
   The point of this row is that the numbers are the archive, not a description of it, so they are
   the loudest thing on the page after the download button. */

.tallies[b-v2ipreub5g] {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 0.9rem;
}

.tally[b-v2ipreub5g] {
    flex: 1 1 auto;
    min-width: 7.5rem;
    background: var(--tc-well);
    border: 1px solid rgba(var(--tc-tint), 0.10);
    border-radius: 8px;
    padding: 0.6rem 0.8rem;
}
.tally b[b-v2ipreub5g] {
    display: block;
    font-size: 1.35rem;
    font-weight: 800;
    color: var(--tc-accent);
    line-height: 1.15;
    font-variant-numeric: tabular-nums;
}
.tally span[b-v2ipreub5g] {
    display: block;
    margin-top: 2px;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--tc-dimmer);
    font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
    text-transform: none;
}

.gamelist[b-v2ipreub5g] { display: flex; flex-wrap: wrap; gap: 6px; line-height: 2; }

/* ---- lists, buttons, code ---------------------------------------------------------------------- */

.steps[b-v2ipreub5g] { margin: 0; padding-left: 1.15rem; color: var(--tc-text); line-height: 1.65; }
.steps li[b-v2ipreub5g] { margin-bottom: 0.5rem; }

.actions[b-v2ipreub5g] { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 0.5rem; }

.btn[b-v2ipreub5g] {
    cursor: pointer;
    font: inherit;
    font-size: 14px;
    font-weight: 700;
    padding: 11px 20px;
    border-radius: 8px;
    border: 1px solid transparent;
    background: var(--tc-accent);
    color: var(--tc-on-accent);
    text-decoration: none;
    transition: filter .12s ease, transform .12s ease;
}
.btn:hover[b-v2ipreub5g] { filter: brightness(1.1); transform: translateY(-1px); }

pre.snip[b-v2ipreub5g] {
    margin: 0.5rem 0 0.2rem;
    padding: 0.75rem 0.9rem;
    background: var(--tc-well);
    border: 1px solid rgba(var(--tc-tint), 0.10);
    border-radius: 8px;
    overflow-x: auto;
}
pre.snip code[b-v2ipreub5g] {
    background: none; border: none; padding: 0;
    color: var(--tc-text-hi);
    font-size: 12.5px;
    line-height: 1.55;
    white-space: pre;
}

/* ---- narrow -------------------------------------------------------------------------------------- */

@media (max-width: 560px) {
    .deck[b-v2ipreub5g] { padding: 1rem 0.9rem 2.4rem; }
    .head h1[b-v2ipreub5g] { font-size: 1.6rem; }
    .actions .btn[b-v2ipreub5g] { flex: 1 1 100%; text-align: center; }
}
/* /Components/TutorialParts/LegacyTutorial.razor.rz.scp.css */
/* LegacyTutorial.razor.css — WP163's sheet, moved beside its markup by WP219 and otherwise
   untouched. It styles the ROLLBACK page only; the live nine wear TutorialShell.razor.css.

   Was: Tutorial.razor.css — WP163. The tutorial page in Home's, /api's and /devkit's visual language.

   Scoped (Blazor CSS isolation); host project, so these rules bundle into `Tripcity.styles.css`.
   The tokens are stated rather than imported, the WP128 J7 note: glass panels over night navy,
   cyan accent, uppercase 11px labels, no Bootstrap. If they ever become shared variables, all four
   pages move together. */

.deck[b-ztcyanlr23] {
    width: min(880px, 100%);
    margin: 0 auto;
    padding: 1.4rem 1.2rem 3rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
    flex: 1;
}

.panel[b-ztcyanlr23] {
    background: rgba(var(--tc-glass), 0.72);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border: 1px solid rgba(var(--tc-tint), 0.12);
    border-radius: 10px;
    padding: 1.1rem 1.25rem;
}

/* ---- top line and header --------------------------------------------------------------------- */

.topline[b-ztcyanlr23] { display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }

.back[b-ztcyanlr23] {
    color: var(--tc-accent-hi);
    text-decoration: none;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
.back:hover[b-ztcyanlr23] { text-decoration: underline; }

.kicker[b-ztcyanlr23] {
    margin: 0;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--tc-accent);
}

.head h1[b-ztcyanlr23] { margin: 0.35rem 0 0.6rem; font-size: 2rem; font-weight: 800; color: var(--tc-ink); }

.lede[b-ztcyanlr23] { margin: 0; font-size: 1.05rem; line-height: 1.6; color: var(--tc-text-hi); max-width: 62ch; }

.muted[b-ztcyanlr23] { color: var(--tc-label); margin: 0.6rem 0 0; line-height: 1.55; }
.muted a[b-ztcyanlr23], li a[b-ztcyanlr23], p a[b-ztcyanlr23] { color: var(--tc-accent-hi); }

/* ---- prose ------------------------------------------------------------------------------------ */

h2[b-ztcyanlr23] { margin: 0 0 0.5rem; font-size: 1.28rem; color: var(--tc-accent); font-weight: 700; }
h3[b-ztcyanlr23] { margin: 1.2rem 0 0.35rem; font-size: 1rem; color: var(--tc-ink-2); font-weight: 700; }
p[b-ztcyanlr23] { margin: 0 0 0.7rem; color: var(--tc-text); line-height: 1.62; max-width: 74ch; }
p:last-child[b-ztcyanlr23] { margin-bottom: 0; }

b[b-ztcyanlr23] { color: var(--tc-ink-2); }

ul[b-ztcyanlr23] { margin: 0 0 0.7rem; padding-left: 1.2rem; color: var(--tc-text); line-height: 1.62; }
li[b-ztcyanlr23] { margin-bottom: 0.35rem; }
li:last-child[b-ztcyanlr23] { margin-bottom: 0; }

code[b-ztcyanlr23] {
    background: rgba(var(--tc-accent-rgb), 0.10);
    border: 1px solid rgba(var(--tc-accent-rgb), 0.22);
    color: var(--tc-accent-hi);
    border-radius: 4px;
    padding: 0 4px;
    font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
    font-size: 0.88em;
}

.callout[b-ztcyanlr23] {
    border-left: 3px solid var(--tc-amber);
    background: rgba(var(--tc-amber-rgb), 0.08);
    padding: 0.6rem 0.85rem;
    border-radius: 0 6px 6px 0;
    color: var(--tc-amber-hi);
    margin-top: 0.9rem;
    max-width: none;
}

/* ---- the key table ---------------------------------------------------------------------------- */

.keys[b-ztcyanlr23] { border-collapse: collapse; width: 100%; margin-top: 0.4rem; }

.keys td[b-ztcyanlr23] {
    padding: 0.42rem 0.6rem;
    border-top: 1px solid rgba(var(--tc-tint), 0.08);
    color: var(--tc-text);
    line-height: 1.5;
    vertical-align: top;
}

.keys td:first-child[b-ztcyanlr23] { white-space: nowrap; width: 9.5rem; }

footer.panel p[b-ztcyanlr23] { color: var(--tc-label); }
/* /Components/TutorialParts/TutorialLightbox.razor.rz.scp.css */
/* ================================================================================================
   TutorialLightbox.razor.css — WP224, rebuilt on the Popover API by WP225.

   Click an image, see it at full size; step through every image on that page; leave by Esc, by the
   close button, by clicking the picture, or by clicking anywhere outside it.

   NO SCRIPT. `popover` is declarative HTML: the browser owns Esc, light dismiss and the top layer,
   and CSS only has to say what the thing looks like. That keeps the promise the rest of this page
   family makes — these pages ship no JS interop at all — while adding the two behaviours CSS alone
   could never have done, because CSS cannot hear a key.

   Why it earns its place at all: the stored images are 1600x900 and the tutorial column renders them
   at ~800, so half the captured detail was unreachable. 1600 is also the CEILING — the captures come
   off a 1568px-wide viewport — so this shows everything there is and nothing is gained by storing
   them larger.
   ================================================================================================ */

.lb[b-sco140d7ag] {
    /* the popover's own box: no chrome of its own, the picture is the content */
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    max-width: 100%;
    max-height: 100%;
    margin: 0;
    padding: 3vmin;
    border: 0;
    background: transparent;
    overflow: visible;
}

/* `popover` is display:none until open — say what open looks like, and only then. */
.lb:popover-open[b-sco140d7ag] {
    display: flex;
    align-items: center;
    justify-content: center;
}

/* The browser paints this behind the top layer, and a click on it light-dismisses for free —
   which is why there is no backdrop element of our own any more. */
.lb[b-sco140d7ag]::backdrop {
    background: rgba(var(--tc-ground), 0.94);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
}

/* ---- the picture, which is also the close button ----------------------------------------------
   A <button> so the keyboard reaches it and the browser handles the dismiss; stripped of every
   button default so it reads as a picture, and given `zoom-out` so the pointer says what a click
   will do (Rob). */

.lb .lb-fig[b-sco140d7ag] {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
    max-width: min(1600px, 94vw);
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: zoom-out;
}

.lb .lb-fig img[b-sco140d7ag] {
    display: block;
    width: 100%;
    height: auto;
    max-height: 84vh;
    object-fit: contain;
    border-radius: 8px;
    border: 1px solid rgba(var(--tc-tint), 0.16);
    background: var(--tc-media);
}

.lb .lb-cap[b-sco140d7ag] {
    display: flex;
    gap: 0.9rem;
    align-items: baseline;
    color: var(--tc-text);
    font-size: 0.95rem;
    line-height: 1.5;
}
.lb .lb-cap .n[b-sco140d7ag] {
    flex: 0 0 auto;
    color: var(--tc-accent);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* ---- the controls ------------------------------------------------------------------------------
   They sit OVER the picture, and the picture closes on click — so each one stops the pointer being
   a zoom-out and says what it actually does instead. */

.lb .lb-step[b-sco140d7ag],
.lb .lb-x[b-sco140d7ag] {
    position: absolute;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font: inherit;
    color: var(--tc-text-hi);
    background: rgba(var(--tc-glass), 0.72);
    border: 1px solid rgba(var(--tc-tint), 0.16);
    border-radius: 10px;
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}
.lb .lb-step:hover[b-sco140d7ag],
.lb .lb-x:hover[b-sco140d7ag] { border-color: rgba(var(--tc-accent-rgb), 0.6); color: var(--tc-ink); }
.lb .lb-step:focus-visible[b-sco140d7ag],
.lb .lb-x:focus-visible[b-sco140d7ag] { outline: 2px solid var(--tc-accent); outline-offset: 2px; }

.lb .lb-step[b-sco140d7ag] {
    top: 50%;
    transform: translateY(-50%);
    width: 3rem;
    height: 4.4rem;
    font-size: 2rem;
    line-height: 1;
}
.lb .lb-step.prev[b-sco140d7ag] { left: 2vmin; }
.lb .lb-step.next[b-sco140d7ag] { right: 2vmin; }

.lb .lb-x[b-sco140d7ag] {
    top: 2vmin;
    right: 2vmin;
    width: 2.6rem;
    height: 2.6rem;
    font-size: 1.1rem;
}

/* Narrow screens: the steps would sit over the picture, so drop them to the bottom corners. */
@media (max-width: 700px) {
    .lb .lb-step[b-sco140d7ag] { top: auto; bottom: 2vmin; transform: none; height: 3rem; width: 3.6rem; }
}
/* /Components/TutorialParts/TutorialShell.razor.rz.scp.css */
/* TutorialShell.razor.css — WP219. WP163's `Tutorial.razor.css` carried forward VERBATIM in its
   token values (S3: glass panels over night navy, cyan accent var(--tc-accent), uppercase 11px labels, no
   Bootstrap), plus the four new blocks WP219 needs (contents list, media slots, prev/next, cards).

   EVERY rule below the `.deck` box is written `.deck ::deep …` rather than bare, and that is
   structural, not stylistic: Blazor scopes a selector to the markup of the component the sheet
   belongs to, and nine-tenths of the markup on any tutorial page arrives through this component's
   `@ChildContent` slot from a page that has no stylesheet at all. `::deep` compiles to
   `.deck[b-xxx] …`, which reaches the slot. Take the `::deep` off a rule and it silently stops
   applying to the nine section pages while still applying to the header — the worst failure shape
   there is, so: if it is not `.deck` itself, it is `::deep`.

   Scoped (Blazor CSS isolation); host project, so these rules bundle into `Tripcity.styles.css`. */

.deck[b-l6ptzii8k0] {
    width: min(880px, 100%);
    margin: 0 auto;
    padding: 1.4rem 1.2rem 3rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
    flex: 1;
}

.deck[b-l6ptzii8k0]  .panel {
    background: rgba(var(--tc-glass), 0.72);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border: 1px solid rgba(var(--tc-tint), 0.12);
    border-radius: 10px;
    padding: 1.1rem 1.25rem;
}

/* ---- top line and header --------------------------------------------------------------------- */

.deck[b-l6ptzii8k0]  .topline { display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }

.deck[b-l6ptzii8k0]  .back {
    color: var(--tc-accent-hi);
    text-decoration: none;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
.deck[b-l6ptzii8k0]  .back:hover { text-decoration: underline; }

.deck[b-l6ptzii8k0]  .kicker {
    margin: 0;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--tc-accent);
}

.deck[b-l6ptzii8k0]  .head h1 { margin: 0.35rem 0 0.6rem; font-size: 2rem; font-weight: 800; color: var(--tc-ink); }

.deck[b-l6ptzii8k0]  .lede { margin: 0; font-size: 1.05rem; line-height: 1.6; color: var(--tc-text-hi); max-width: 62ch; }

.deck[b-l6ptzii8k0]  .muted { color: var(--tc-label); margin: 0.6rem 0 0; line-height: 1.55; }
.deck[b-l6ptzii8k0]  .muted a,
.deck[b-l6ptzii8k0]  li a,
.deck[b-l6ptzii8k0]  p a { color: var(--tc-accent-hi); }

/* ---- prose ------------------------------------------------------------------------------------ */

.deck[b-l6ptzii8k0]  h2 { margin: 0 0 0.5rem; font-size: 1.28rem; color: var(--tc-accent); font-weight: 700; }
.deck[b-l6ptzii8k0]  h3 { margin: 1.2rem 0 0.35rem; font-size: 1rem; color: var(--tc-ink-2); font-weight: 700; }
.deck[b-l6ptzii8k0]  p { margin: 0 0 0.7rem; color: var(--tc-text); line-height: 1.62; max-width: 74ch; }
.deck[b-l6ptzii8k0]  p:last-child { margin-bottom: 0; }

.deck[b-l6ptzii8k0]  b { color: var(--tc-ink-2); }

.deck[b-l6ptzii8k0]  ul, .deck[b-l6ptzii8k0]  ol { margin: 0 0 0.7rem; padding-left: 1.2rem; color: var(--tc-text); line-height: 1.62; }
.deck[b-l6ptzii8k0]  li { margin-bottom: 0.35rem; }
.deck[b-l6ptzii8k0]  li:last-child { margin-bottom: 0; }

.deck[b-l6ptzii8k0]  code {
    background: rgba(var(--tc-accent-rgb), 0.10);
    border: 1px solid rgba(var(--tc-accent-rgb), 0.22);
    color: var(--tc-accent-hi);
    border-radius: 4px;
    padding: 0 4px;
    font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
    font-size: 0.88em;
}

.deck[b-l6ptzii8k0]  .callout {
    border-left: 3px solid var(--tc-amber);
    background: rgba(var(--tc-amber-rgb), 0.08);
    padding: 0.6rem 0.85rem;
    border-radius: 0 6px 6px 0;
    color: var(--tc-amber-hi);
    margin-top: 0.9rem;
    max-width: none;
}

/* ---- the key table ---------------------------------------------------------------------------- */

.deck[b-l6ptzii8k0]  .keys { border-collapse: collapse; width: 100%; margin-top: 0.4rem; }

.deck[b-l6ptzii8k0]  .keys td {
    padding: 0.42rem 0.6rem;
    border-top: 1px solid rgba(var(--tc-tint), 0.08);
    color: var(--tc-text);
    line-height: 1.5;
    vertical-align: top;
}

.deck[b-l6ptzii8k0]  .keys td:first-child { white-space: nowrap; width: 9.5rem; }

.deck[b-l6ptzii8k0]  footer.panel p { color: var(--tc-label); }

/* ---- WP219: the contents list on the landing page --------------------------------------------- */

.deck[b-l6ptzii8k0]  .toc { display: grid; gap: 0.55rem; margin-top: 0.2rem; }

.deck[b-l6ptzii8k0]  .toc a {
    display: grid;
    grid-template-columns: 2.1rem 1fr;
    gap: 0 0.75rem;
    align-items: baseline;
    text-decoration: none;
    padding: 0.7rem 0.85rem;
    border: 1px solid rgba(var(--tc-tint), 0.10);
    border-radius: 8px;
    background: rgba(var(--tc-tint), 0.025);
}
.deck[b-l6ptzii8k0]  .toc a:hover { border-color: rgba(var(--tc-accent-rgb), 0.55); background: rgba(var(--tc-accent-rgb), 0.07); }

.deck[b-l6ptzii8k0]  .toc .n {
    font-size: 11px;
    letter-spacing: 0.1em;
    color: var(--tc-accent);
    font-weight: 700;
    grid-row: span 2;
    align-self: center;
}
.deck[b-l6ptzii8k0]  .toc .t { color: var(--tc-ink-2); font-weight: 700; font-size: 1.02rem; }
.deck[b-l6ptzii8k0]  .toc .d { color: var(--tc-label); font-size: 0.9rem; line-height: 1.5; grid-column: 2; }

/* ---- WP221: the tour film's two affordances ---------------------------------------------------

   `.tourlink` is the shell's OWN element, so it needs no ::deep. `.chapters` arrives through the
   slot from Index.razor, so it does. (The rule at the top of this file, applied.) */

.tourlink[b-l6ptzii8k0] { margin: -0.4rem 0 0; }

.tourlink a[b-l6ptzii8k0] {
    color: var(--tc-accent-hi);
    text-decoration: none;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}
.tourlink a:hover[b-l6ptzii8k0] { text-decoration: underline; }

.deck[b-l6ptzii8k0]  .chapters {
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem;
    margin-top: 0.8rem;
}

.deck[b-l6ptzii8k0]  .chapters a {
    display: inline-flex;
    align-items: baseline;
    gap: 0.5rem;
    text-decoration: none;
    padding: 0.42rem 0.7rem;
    border: 1px solid rgba(var(--tc-tint), 0.10);
    border-radius: 999px;
    background: rgba(var(--tc-tint), 0.025);
}
.deck[b-l6ptzii8k0]  .chapters a:hover { border-color: rgba(var(--tc-accent-rgb), 0.55); background: rgba(var(--tc-accent-rgb), 0.07); }

/* The chapter you arrived on. It is a server-rendered class, not a :target — the timecode is a
   query, so there is no fragment for :target to match (TutorialContent.TourHref). */
.deck[b-l6ptzii8k0]  .chapters a.on { border-color: rgba(var(--tc-accent-rgb), 0.75); background: rgba(var(--tc-accent-rgb), 0.12); }

.deck[b-l6ptzii8k0]  .chapters .c {
    color: var(--tc-accent);
    font-weight: 700;
    font-size: 11px;
    letter-spacing: 0.06em;
    font-variant-numeric: tabular-nums;
}
.deck[b-l6ptzii8k0]  .chapters .t { color: var(--tc-ink-2); font-size: 0.9rem; }

/* ---- the section index -------------------------------------------------------------------------

   Nine circles. The filled one is selected by `[aria-current="page"]` rather than by a class of its
   own, so the thing a screen reader announces and the thing an eye sees are driven by the SAME
   attribute and cannot drift apart. `.secnav` is the shell's own element, so it needs no ::deep. */

.secnav[b-l6ptzii8k0] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0.1rem 0 0.2rem;
}

.secnav a[b-l6ptzii8k0] {
    /* A circle, sized in `ch` + padding so it stays round whether the number is one digit or two —
       a fixed width would break the day a tenth section is added. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.85rem;
    height: 1.85rem;
    padding: 0 0.35rem;
    border-radius: 999px;
    border: 1px solid rgba(var(--tc-accent-rgb), 0.45);
    color: var(--tc-accent-hi);
    background: rgba(var(--tc-accent-rgb), 0.06);
    font-size: 0.82rem;
    font-weight: 700;
    line-height: 1;
    text-decoration: none;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.secnav a:hover[b-l6ptzii8k0] {
    border-color: rgba(var(--tc-accent-rgb), 0.9);
    background: rgba(var(--tc-accent-rgb), 0.18);
    color: var(--tc-accent-hi);
}

.secnav a:focus-visible[b-l6ptzii8k0] {
    outline: 2px solid var(--tc-accent);
    outline-offset: 2px;
}

/* The page you are on. Filled, and NOT a link you can usefully follow — but it stays an anchor
   rather than becoming a span, because turning it into a non-link would make the row jump by a
   pixel as you move between sections and would take it out of the tab order halfway along. */
.secnav a[aria-current="page"][b-l6ptzii8k0] {
    background: var(--tc-accent);
    border-color: var(--tc-accent);
    color: var(--tc-on-accent);
    cursor: default;
}

@media (max-width: 620px) {
    .secnav a[b-l6ptzii8k0] { min-width: 1.6rem; height: 1.6rem; font-size: 0.76rem; }
}

/* ---- the tour film, dressed as film ------------------------------------------------------------

   Rob: make it look clearly like a video. Two devices, both CSS, neither needing script:

   1. A SPROCKET COLUMN down each side — one radial-gradient tiled vertically, so the perforations
      cost no image and no element. They are on `.film`'s own padding, not on the video, so they
      never overlap the picture or the native controls.
   2. The PLAY BADGE is NOT here. It is composited into the poster image itself, which is the only
      way to have it appear exactly while the poster is showing and vanish the moment playback
      starts — CSS cannot know a video is playing, and this page family ships no script to ask. */

.deck[b-l6ptzii8k0]  .media.film {
    margin: 0.95rem 0 0;
    background: #06090d;
    border: 1px solid rgba(var(--tc-tint), 0.10);
    border-radius: 10px;
    /* the side padding IS the sprocket track */
    padding: 12px 22px;
}

/* One cell, 22 wide by 26 tall, with a rounded hole punched at its centre; repeated down both
   edges. `background-repeat: repeat-y` and a fixed cell size means the holes stay the same size at
   every video height rather than stretching with it. */
.deck[b-l6ptzii8k0]  .media.film .reel {
    position: relative;
    background-image:
        radial-gradient(circle at 11px 13px, rgba(232, 240, 246, 0.62) 0 4.5px, rgba(var(--tc-shade), 0) 5px),
        radial-gradient(circle at 11px 13px, rgba(232, 240, 246, 0.62) 0 4.5px, rgba(var(--tc-shade), 0) 5px);
    background-size: 22px 26px, 22px 26px;
    background-position: left top, right top;
    background-repeat: repeat-y, repeat-y;
    padding: 0 22px;
    margin: 0 -22px;   /* the track sits in the figure's padding, beside the picture */
}

.deck[b-l6ptzii8k0]  .media.film video {
    display: block;
    width: 100%;
    border-radius: 4px;
    background: #000;
    /* The whole frame starts it (`tutorial.js`), and the poster carries a play badge, so the pointer
       should say so. Only while it is paused would be better, but that is a state CSS cannot see —
       and once it is playing the cursor sits over the control bar most of the time anyway. */
    cursor: pointer;
}

.deck[b-l6ptzii8k0]  .media.film figcaption {
    margin-top: 0.6rem;
}

/* A phone has no room for a 22 px track on each side; the holes shrink with it rather than eating
   the picture. */
@media (max-width: 620px) {
    .deck[b-l6ptzii8k0]  .media.film { padding: 8px 13px; }
    .deck[b-l6ptzii8k0]  .media.film .reel {
        background-size: 13px 18px, 13px 18px;
        background-image:
            radial-gradient(circle at 6.5px 9px, rgba(232, 240, 246, 0.62) 0 2.6px, rgba(var(--tc-shade), 0) 3px),
            radial-gradient(circle at 6.5px 9px, rgba(232, 240, 246, 0.62) 0 2.6px, rgba(var(--tc-shade), 0) 3px);
        padding: 0 13px;
        margin: 0 -13px;
    }
}

/* ---- WP219: media slots ------------------------------------------------------------------------ */

.deck[b-l6ptzii8k0]  .media { margin: 0.95rem 0 0; }

.deck[b-l6ptzii8k0]  .media img,
.deck[b-l6ptzii8k0]  .media video {
    display: block;
    width: 100%;
    height: auto;
    border-radius: 8px;
    border: 1px solid rgba(var(--tc-tint), 0.12);
    background: var(--tc-media);
}

.deck[b-l6ptzii8k0]  .media figcaption {
    margin-top: 0.45rem;
    font-size: 0.86rem;
    color: var(--tc-dim);
    line-height: 1.5;
}

/* the placeholder card (J2). Dashed, deliberately: it must read as a gap that will be filled, not
   as a broken image and not as a designed element. It also prints the brief, so the page doubles as
   the production to-do list it already is in the WP. */
.deck[b-l6ptzii8k0]  .media-ph {
    margin: 0.95rem 0 0;
    border: 1px dashed rgba(var(--tc-accent-rgb), 0.34);
    border-radius: 8px;
    background: rgba(var(--tc-accent-rgb), 0.035);
    padding: 0.75rem 0.9rem;
}

.deck[b-l6ptzii8k0]  .media-ph .k {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.11em;
    color: var(--tc-accent);
    font-weight: 700;
}
.deck[b-l6ptzii8k0]  .media-ph .c { color: var(--tc-text-hi); font-weight: 700; margin-top: 0.2rem; }
.deck[b-l6ptzii8k0]  .media-ph .b { color: var(--tc-dim); font-size: 0.88rem; line-height: 1.55; margin-top: 0.25rem; }
.deck[b-l6ptzii8k0]  .media-ph .s { color: var(--tc-dimmer); font-size: 0.78rem; margin-top: 0.4rem; font-family: ui-monospace, SFMono-Regular, Consolas, monospace; }

/* ---- WP219: prev / next ------------------------------------------------------------------------ */

.deck[b-l6ptzii8k0]  .tnav { display: flex; gap: 0.6rem; align-items: stretch; flex-wrap: wrap; }

.deck[b-l6ptzii8k0]  .tnav a {
    flex: 1 1 14rem;
    min-width: 0;
    text-decoration: none;
    border: 1px solid rgba(var(--tc-tint), 0.12);
    border-radius: 8px;
    padding: 0.65rem 0.85rem;
    background: rgba(var(--tc-tint), 0.025);
}
.deck[b-l6ptzii8k0]  .tnav a:hover { border-color: rgba(var(--tc-accent-rgb), 0.55); background: rgba(var(--tc-accent-rgb), 0.07); }
.deck[b-l6ptzii8k0]  .tnav a.next { text-align: right; }

.deck[b-l6ptzii8k0]  .tnav .k {
    display: block;
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.11em;
    color: var(--tc-accent);
}
.deck[b-l6ptzii8k0]  .tnav .t { display: block; color: var(--tc-ink-2); font-weight: 700; margin-top: 0.15rem; }

.deck[b-l6ptzii8k0]  .tnav .all {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    color: var(--tc-accent-hi);
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
}

/* ================================================================================================
   WP220 — the hero (F2) and the image sequence (F4).
   ================================================================================================ */

/* ---- F2: the hero ------------------------------------------------------------------------------
   Full column width, no glass chrome. A picture inside a panel reads as an illustration OF the
   text; a picture above the panels reads as the subject itself, which is what an establishing shot
   is for. `.hero` is the shell's own element, so it needs no ::deep — its CONTENTS do. */

.hero[b-l6ptzii8k0] { margin: -0.2rem 0 0; }

.deck[b-l6ptzii8k0]  .hero .media,
.deck[b-l6ptzii8k0]  .hero .media-ph { margin: 0; }

.deck[b-l6ptzii8k0]  .hero .media img,
.deck[b-l6ptzii8k0]  .hero .media video,
.deck[b-l6ptzii8k0]  .hero .seq .frames {
    border-radius: 12px;
    border-color: rgba(var(--tc-tint), 0.16);
}

.deck[b-l6ptzii8k0]  .hero .media figcaption { text-align: center; }

/* ---- F4: the image sequence --------------------------------------------------------------------

   Every moving part below is CSS. WP212's landing page made the same choice on the same surface and
   said so; these pages ship no JS interop at all, and an auto-advancing slideshow is exactly the
   kind of thing that does not need any.

   The frames stack absolutely inside a fixed 16:9 box and crossfade. CSS keyframes cannot be
   parameterised by frame count, so there is one block per count — `tc-seq-2` … `tc-seq-6`, matching
   `TutorialContent.MaxFrames`. The component picks the class and emits each frame's
   `animation-delay` inline (negative, so the cycle is already under way on load rather than every
   frame fading up together). */

.deck[b-l6ptzii8k0]  .seq .frames {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    border-radius: 8px;
    border: 1px solid rgba(var(--tc-tint), 0.12);
    background: var(--tc-media);
    overflow: hidden;
}

.deck[b-l6ptzii8k0]  .seq .frames img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border: 0;
    border-radius: 0;
    opacity: 0;
    animation-duration: var(--d, 16s);
    animation-iteration-count: infinite;
    animation-timing-function: linear;
}

/* Frame 1 is opaque with no animation running (a still, or the reduced-motion state), so the box is
   never blank; the keyframe rules below override it once a `tc-seq-n` class is on the figure. */
.deck[b-l6ptzii8k0]  .seq .frames img:first-child { opacity: 1; }
.deck[b-l6ptzii8k0]  .seq.still .frames img:not(:first-child) { display: none; }

/* ---- the caption strip: one line per frame, on the same stagger ------------------------------ */

.deck[b-l6ptzii8k0]  .seq .steps {
    position: relative;
    margin-top: 0.5rem;
    min-height: 1.5em;
}

.deck[b-l6ptzii8k0]  .seq .steps .st {
    position: absolute;
    inset: 0 0 auto;
    opacity: 0;
    color: var(--tc-text);
    font-size: 0.92rem;
    line-height: 1.5;
    animation-duration: var(--d, 16s);
    animation-iteration-count: infinite;
    animation-timing-function: linear;
}

.deck[b-l6ptzii8k0]  .seq .steps .st:first-child { opacity: 1; }
.deck[b-l6ptzii8k0]  .seq.still .steps .st:not(:first-child) { display: none; }

.deck[b-l6ptzii8k0]  .seq .steps .st b {
    display: inline-block;
    min-width: 1.35em;
    color: var(--tc-accent);
    font-variant-numeric: tabular-nums;
}

/* The strip is a stack of absolutely-positioned lines, which would collapse to nothing; this
   invisible copy of the longest one holds the height so the panel below never jumps mid-cycle. */
.deck[b-l6ptzii8k0]  .seq .steps .sizer {
    display: block;
    visibility: hidden;
    font-size: 0.92rem;
    line-height: 1.5;
    padding-left: 1.35em;
}

/* ---- the five keyframe blocks -----------------------------------------------------------------
   Each frame holds for 100/n% of the cycle, fades out over ~3%, stays down, and fades back in over
   the last ~3% so the loop closes on itself with no flash. */

.deck[b-l6ptzii8k0]  .tc-seq-2 .frames img { animation-name: tcSeq2-b-l6ptzii8k0; }
.deck[b-l6ptzii8k0]  .tc-seq-3 .frames img { animation-name: tcSeq3-b-l6ptzii8k0; }
.deck[b-l6ptzii8k0]  .tc-seq-4 .frames img { animation-name: tcSeq4-b-l6ptzii8k0; }
.deck[b-l6ptzii8k0]  .tc-seq-5 .frames img { animation-name: tcSeq5-b-l6ptzii8k0; }
.deck[b-l6ptzii8k0]  .tc-seq-6 .frames img { animation-name: tcSeq6-b-l6ptzii8k0; }

@keyframes tcSeq2-b-l6ptzii8k0 { 0%, 45%    { opacity: 1 } 50%,    95%   { opacity: 0 } 100% { opacity: 1 } }
@keyframes tcSeq3-b-l6ptzii8k0 { 0%, 29%    { opacity: 1 } 33.33%, 96%   { opacity: 0 } 100% { opacity: 1 } }
@keyframes tcSeq4-b-l6ptzii8k0 { 0%, 22%    { opacity: 1 } 25%,    97%   { opacity: 0 } 100% { opacity: 1 } }
@keyframes tcSeq5-b-l6ptzii8k0 { 0%, 17%    { opacity: 1 } 20%,    97%   { opacity: 0 } 100% { opacity: 1 } }
@keyframes tcSeq6-b-l6ptzii8k0 { 0%, 14%    { opacity: 1 } 16.67%, 97.5% { opacity: 0 } 100% { opacity: 1 } }

/* THE CAPTIONS CUT; THE PICTURES DISSOLVE. Two photographs at half opacity read as a dissolve, which
   is what a dissolve is for. Two SENTENCES at half opacity read as neither sentence — the words
   interleave and the strip becomes mush for the length of the fade. Measured in the browser: at a
   3% ramp on a 12.8 s cycle that is nearly 0.4 s of unreadable caption on every step, which on a
   loop is most of what a reader who glances at the wrong moment ever sees.

   So the captions get their own keyframes with a 0.5% ramp — 0.06 s, a cut rather than a fade — and
   the two are separated permanently rather than sharing one animation name. Same slot boundaries, so
   the caption still changes with its picture; only the transition differs. */

.deck[b-l6ptzii8k0]  .tc-seq-2 .steps .st { animation-name: tcCap2-b-l6ptzii8k0; }
.deck[b-l6ptzii8k0]  .tc-seq-3 .steps .st { animation-name: tcCap3-b-l6ptzii8k0; }
.deck[b-l6ptzii8k0]  .tc-seq-4 .steps .st { animation-name: tcCap4-b-l6ptzii8k0; }
.deck[b-l6ptzii8k0]  .tc-seq-5 .steps .st { animation-name: tcCap5-b-l6ptzii8k0; }
.deck[b-l6ptzii8k0]  .tc-seq-6 .steps .st { animation-name: tcCap6-b-l6ptzii8k0; }

@keyframes tcCap2-b-l6ptzii8k0 { 0%, 49.5%  { opacity: 1 } 50%,    99.5% { opacity: 0 } 100% { opacity: 1 } }
@keyframes tcCap3-b-l6ptzii8k0 { 0%, 32.8%  { opacity: 1 } 33.33%, 99.5% { opacity: 0 } 100% { opacity: 1 } }
@keyframes tcCap4-b-l6ptzii8k0 { 0%, 24.5%  { opacity: 1 } 25%,    99.5% { opacity: 0 } 100% { opacity: 1 } }
@keyframes tcCap5-b-l6ptzii8k0 { 0%, 19.5%  { opacity: 1 } 20%,    99.5% { opacity: 0 } 100% { opacity: 1 } }
@keyframes tcCap6-b-l6ptzii8k0 { 0%, 16.1%  { opacity: 1 } 16.67%, 99.5% { opacity: 0 } 100% { opacity: 1 } }

/* An auto-looping animation with no pause control is precisely what this setting exists for, and a
   tutorial is the worst place to ignore it. Freeze on frame 1 with frame 1's caption. */
@media (prefers-reduced-motion: reduce) {
    .deck[b-l6ptzii8k0]  .seq .frames img,
    .deck[b-l6ptzii8k0]  .seq .steps .st { animation: none !important; }
    .deck[b-l6ptzii8k0]  .seq .frames img:not(:first-child),
    .deck[b-l6ptzii8k0]  .seq .steps .st:not(:first-child) { display: none; }
    .deck[b-l6ptzii8k0]  .seq .frames img:first-child,
    .deck[b-l6ptzii8k0]  .seq .steps .st:first-child { opacity: 1; }
}

/* ---- the placeholder's shot list (an empty sequence slot IS its shot list) --------------------- */

.deck[b-l6ptzii8k0]  .media-ph .shots {
    margin: 0.5rem 0 0;
    padding-left: 1.4rem;
    color: var(--tc-dim);
    font-size: 0.88rem;
    line-height: 1.55;
}
.deck[b-l6ptzii8k0]  .media-ph .shots li { margin-bottom: 0.2rem; }

/* ---- WP224: the click target on an image ------------------------------------------------------
   The OVERLAYS themselves are not styled here — they belong to `TutorialLightbox`, a separate
   component, so its scope attribute is not this sheet's. They live in `TutorialLightbox.razor.css`.
   Only the in-page click affordance is this sheet's business. */

/* WP225 — the trigger is a <button> (popover triggers name an element, and only a button can),
   so every button default has to come off before it reads as a picture again. */
.deck[b-l6ptzii8k0]  .zoom {
    display: block;
    width: 100%;
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    color: inherit;
    cursor: zoom-in;
}
.deck[b-l6ptzii8k0]  .zoom:focus-visible { outline: 2px solid var(--tc-accent); outline-offset: 3px; }

/* the sequence's trigger covers the whole crossfading stack */
.deck[b-l6ptzii8k0]  .seqzoom { position: absolute; inset: 0; z-index: 3; width: auto; }
