/* /Components/Layout/MainLayout.razor.rz.scp.css */
.page[b-ong4o2freg] {
    position: relative;
    display: flex;
    flex-direction: column;
}

main[b-ong4o2freg] {
    flex: 1;
}

.sidebar[b-ong4o2freg] {
    background-image: var(--brand-sidebar-gradient, linear-gradient(180deg, #0e1620 0%, #0b1119 100%));
}

.top-row[b-ong4o2freg] {
    /* T-083d: token-aligned with the Desk palette (tokens.css) instead of one-off hex —
       kit dojo look refinement only, no layout/behavior change. */
    background-color: var(--surface-topbar, #f7f7f7);
    border-bottom: 1px solid var(--border-default, #d6d5d5);
    justify-content: flex-end;
    height: 3.5rem;
    display: flex;
    align-items: center;
}

    .top-row[b-ong4o2freg]  a, .top-row[b-ong4o2freg]  .btn-link {
        white-space: nowrap;
        margin-left: 1.5rem;
        text-decoration: none;
    }

    .top-row[b-ong4o2freg]  a:hover, .top-row[b-ong4o2freg]  .btn-link:hover {
        text-decoration: underline;
    }

    .top-row[b-ong4o2freg]  a:first-child {
        overflow: hidden;
        text-overflow: ellipsis;
    }

/* T-080f (D-039): top-right account menu — a CSS-only <details>/<summary> disclosure
   (no new JS) replacing the old About link. Right-aligned in .top-row. Declared AFTER the
   generic .top-row ::deep a/.btn-link rules above (same 2-class specificity) so these
   overrides win the cascade by source order for margin/hover on the panel's own items. */
.top-row[b-ong4o2freg]  .account-menu {
    position: relative;
    margin-left: auto;
}

.top-row[b-ong4o2freg]  .account-menu-trigger {
    cursor: pointer;
    list-style: none;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--ink, #0e1620);
    font-weight: 500;
    padding: 0.35rem 0.6rem;
    margin-left: 0;
    border-radius: var(--radius-pill, 50rem);
}

    .top-row[b-ong4o2freg]  .account-menu-trigger::-webkit-details-marker {
        display: none;
    }

    .top-row[b-ong4o2freg]  .account-menu-trigger:hover {
        background-color: rgba(0, 0, 0, 0.05);
        text-decoration: none;
    }

.top-row[b-ong4o2freg]  .account-menu[open] .account-menu-trigger {
    background-color: rgba(0, 0, 0, 0.05);
}

.top-row[b-ong4o2freg]  .account-menu-panel {
    position: absolute;
    right: 0;
    top: calc(100% + 0.35rem);
    min-width: 10rem;
    background: var(--white, #fff);
    color: var(--ink, #0e1620);
    border: 1px solid var(--border-strong, #c2c9d2);
    border-radius: var(--radius-lg, 0.5rem);
    box-shadow: var(--shadow-panel, 0 4px 12px rgba(0, 0, 0, 0.15));
    padding: 0.35rem;
    display: flex;
    flex-direction: column;
    z-index: 10;
}

.top-row[b-ong4o2freg]  .account-menu-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--ink, #0e1620);
    text-decoration: none;
    padding: 0.45rem 0.6rem;
    margin-left: 0;
    border-radius: var(--radius-sm, 0.25rem);
    font-size: 0.9rem;
    white-space: nowrap;
}

    .top-row[b-ong4o2freg]  .account-menu-item:hover {
        background-color: rgba(0, 0, 0, 0.06);
        text-decoration: none;
    }

.top-row[b-ong4o2freg]  .account-menu-anon-link {
    margin-left: 1.5rem;
}

@media (max-width: 640.98px) {
    .top-row[b-ong4o2freg] {
        justify-content: space-between;
    }

    .top-row[b-ong4o2freg]  a, .top-row[b-ong4o2freg]  .btn-link {
        margin-left: 0;
    }
}

@media (min-width: 641px) {
    .page[b-ong4o2freg] {
        flex-direction: row;
    }

    .sidebar[b-ong4o2freg] {
        width: 250px;
        height: 100vh;
        position: sticky;
        top: 0;
    }

    .top-row[b-ong4o2freg] {
        position: sticky;
        top: 0;
        z-index: 1;
    }

    .top-row.auth[b-ong4o2freg]  a:first-child {
        flex: 1;
        text-align: right;
        width: 0;
    }

    .top-row[b-ong4o2freg], article[b-ong4o2freg] {
        padding-left: 2rem !important; /* Beats Bootstrap's .px-4 padding-left (bootstrap.min.css, also marked important there); applied via .top-row px-4 (MainLayout.razor:19) and .content px-4 (:47). */
        padding-right: 1.5rem !important; /* Beats Bootstrap's .px-4 padding-right (bootstrap.min.css, also marked important there); applied via .top-row px-4 (MainLayout.razor:19) and .content px-4 (:47). */
    }
}

#blazor-error-ui[b-ong4o2freg] {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss[b-ong4o2freg] {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }
/* /Components/Layout/NavMenu.razor.rz.scp.css */
.navbar-toggler[b-iyzgqpp1ad] {
    appearance: none;
    cursor: pointer;
    width: 3.5rem;
    height: 2.5rem;
    color: white;
    position: absolute;
    top: 0.5rem;
    right: 1rem;
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(255, 255, 255, 0.1);
}

.navbar-toggler:checked[b-iyzgqpp1ad] {
    background-color: rgba(255, 255, 255, 0.5);
}

.top-row[b-iyzgqpp1ad] {
    min-height: 3.5rem;
    background-color: rgba(0,0,0,0.4);
}

.navbar-brand[b-iyzgqpp1ad] {
    font-size: 1.1rem;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

.navbar-brand-mark[b-iyzgqpp1ad] {
    display: inline-block;
    width: 1.5rem;
    height: 1.5rem;
    flex-shrink: 0;
}

/* T-080b: nav-item icons are real Bootstrap Icons font glyphs (<i class="bi bi-*">)
   bundled locally (wwwroot/lib/bootstrap-icons) — no more partial hand-inlined SVG
   background-image rules (several nav icons rendered blank because most bi-*-nav-menu
   classes had no matching rule). Just spacing/sizing to match the prior layout. */
.nav-item[b-iyzgqpp1ad]  .nav-link .bi {
    display: inline-block;
    width: 1.25rem;
    margin-right: 0.75rem;
    font-size: 1.1rem;
    text-align: center;
}

.nav-item[b-iyzgqpp1ad] {
    font-size: 0.9rem;
    padding-bottom: 0.5rem;
}

    .nav-item:first-of-type[b-iyzgqpp1ad] {
        padding-top: 1rem;
    }

    .nav-item:last-of-type[b-iyzgqpp1ad] {
        padding-bottom: 1rem;
    }

    .nav-item[b-iyzgqpp1ad]  .nav-link {
        color: var(--gray-400, #c2c9d2);
        background: none;
        border: none;
        border-radius: var(--radius-pill, 50rem);
        min-height: 3rem;
        display: flex;
        align-items: center;
        width: 100%;
    }

/* T-080b: active nav = signal-blue pill (readme.md "active nav" spec), not the old
   translucent-white highlight. */
.nav-item[b-iyzgqpp1ad]  a.active {
    background-color: var(--blue-600, var(--bs-primary, #2d6ff0));
    color: var(--white, #fff);
}

.nav-item[b-iyzgqpp1ad]  .nav-link:hover {
    background-color: rgba(255, 255, 255, 0.1);
    color: var(--white, #fff);
}

/* T-080f (D-039): section-header dividers (LEARN / TRAIN / PROGRESS / AUTHORING) — small,
   muted, uppercase, non-interactive (not links). Token-driven for the ink sidebar.
   T-083d: font-mono added — matches the kit's mono muted-uppercase-label idiom used
   throughout the dojo system (the "THE DOJO" eyebrow, belt-spine/-card rank labels). */
.nav-section-header[b-iyzgqpp1ad] {
    color: var(--gray-500, #8a93a0);
    font-family: var(--font-mono);
    font-size: var(--text-xs, 0.75rem);
    font-weight: 600;
    letter-spacing: var(--tracking-wide, 0.06em);
    text-transform: uppercase;
    margin-top: 1.25rem;
    margin-bottom: 0.25rem;
}

.nav-scrollable[b-iyzgqpp1ad] {
    display: none;
}

.navbar-toggler:checked ~ .nav-scrollable[b-iyzgqpp1ad] {
    display: block;
}

@media (min-width: 641px) {
    .navbar-toggler[b-iyzgqpp1ad] {
        display: none;
    }

    .nav-scrollable[b-iyzgqpp1ad] {
        /* Never collapse the sidebar for wide screens */
        display: block;

        /* Allow sidebar to scroll for tall menus */
        height: calc(100vh - 3.5rem);
        overflow-y: auto;
    }
}
/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
.components-reconnect-first-attempt-visible[b-hs0ct84d7b],
.components-reconnect-repeated-attempt-visible[b-hs0ct84d7b],
.components-reconnect-failed-visible[b-hs0ct84d7b],
.components-pause-visible[b-hs0ct84d7b],
.components-resume-failed-visible[b-hs0ct84d7b],
.components-rejoining-animation[b-hs0ct84d7b] {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible[b-hs0ct84d7b],
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation[b-hs0ct84d7b],
#components-reconnect-modal.components-reconnect-paused .components-pause-visible[b-hs0ct84d7b],
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible[b-hs0ct84d7b],
#components-reconnect-modal.components-reconnect-retrying[b-hs0ct84d7b],
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible[b-hs0ct84d7b],
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation[b-hs0ct84d7b],
#components-reconnect-modal.components-reconnect-failed[b-hs0ct84d7b],
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible[b-hs0ct84d7b] {
    display: block;
}


#components-reconnect-modal[b-hs0ct84d7b] {
    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-hs0ct84d7b 0.5s both;
    &[open]

{
    animation: components-reconnect-modal-slideUp-b-hs0ct84d7b 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity-b-hs0ct84d7b 0.5s ease-in-out 0.3s;
    animation-fill-mode: both;
}

}

#components-reconnect-modal[b-hs0ct84d7b]::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
    animation: components-reconnect-modal-fadeInOpacity-b-hs0ct84d7b 0.5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp-b-hs0ct84d7b {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity-b-hs0ct84d7b {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity-b-hs0ct84d7b {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.components-reconnect-container[b-hs0ct84d7b] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p[b-hs0ct84d7b] {
    margin: 0;
    text-align: center;
}

#components-reconnect-modal button[b-hs0ct84d7b] {
    border: 0;
    background-color: #6b9ed2;
    color: white;
    padding: 4px 24px;
    border-radius: 4px;
}

    #components-reconnect-modal button:hover[b-hs0ct84d7b] {
        background-color: #3b6ea2;
    }

    #components-reconnect-modal button:active[b-hs0ct84d7b] {
        background-color: #6b9ed2;
    }

.components-rejoining-animation[b-hs0ct84d7b] {
    position: relative;
    width: 80px;
    height: 80px;
}

    .components-rejoining-animation div[b-hs0ct84d7b] {
        position: absolute;
        border: 3px solid #0087ff;
        opacity: 1;
        border-radius: 50%;
        animation: components-rejoining-animation-b-hs0ct84d7b 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
    }

        .components-rejoining-animation div:nth-child(2)[b-hs0ct84d7b] {
            animation-delay: -0.5s;
        }

@keyframes components-rejoining-animation-b-hs0ct84d7b {
    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/Home.razor.rz.scp.css */
/* Home page — scoped component CSS (T-080e, D-038 AC1).
   Hero polish + module color-by-role accent. Copy/routes/gating untouched —
   this file adds token-driven presentation only. Base card look (.desk-card)
   lives in app.css so it's shared identically with the mode-select and
   /learn belt-ladder cards (T-080e AC2/AC3); the top accent bar here is
   Home-specific (PRD §7 U2 — a working choice, not a Brooks rule). */

.hero-title[b-byif9t9nlk] {
    font-family: var(--font-display, var(--font-sans));
    font-weight: var(--weight-bold, 700);
    letter-spacing: var(--tracking-tight, -0.02em);
    font-size: var(--text-display, 3rem);
}

.hero-lead[b-byif9t9nlk] {
    font-size: var(--text-lead, 1.25rem);
    line-height: var(--leading-relaxed, 1.65);
    max-width: 640px;
    margin-left: auto;
    margin-right: auto;
}

/* Color-by-role accent: a 4px top bar, not a full-card recolor (I-016-style
   legibility guard — text stays on the default white card surface). Scoped
   to Home's own .desk-card instances only (does not leak to Landing/Learn). */
.desk-card[b-byif9t9nlk]::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 4px;
    background: var(--card-accent, var(--border-default));
}

.card-role-sr[b-byif9t9nlk]            { --card-accent: var(--blue-600); }
.card-role-trendrange[b-byif9t9nlk]    { --card-accent: var(--ink-900); }
.card-role-transitions[b-byif9t9nlk]   { --card-accent: var(--amber-500); }
.card-role-live[b-byif9t9nlk]          { --card-accent: var(--green-600); }
.card-role-followthrough[b-byif9t9nlk] { --card-accent: var(--blue-700); }
.card-role-breakout[b-byif9t9nlk]      { --card-accent: var(--gray-700); }
.card-role-learn[b-byif9t9nlk]         { --card-accent: var(--blue-600); }
.card-role-progress[b-byif9t9nlk]      { --card-accent: var(--green-600); }
.card-role-history[b-byif9t9nlk]       { --card-accent: var(--gray-500); }
/* /Components/Pages/Learn.razor.rz.scp.css */
/* Learn page (/learn) — dojo belt-ladder scoped CSS (T-083c, PRD-T083-DOJO-RESKIN.md §2/§2.4).
   Token-driven only (no invented hex) — mirrors Home.razor.css's use of tokens.css vars alongside
   the shared global .desk-card look. Responsive rules (§2.4, AC5):
     - belt-card-grid: repeat(3,1fr) on wide, collapses to 1 column under 768px.
     - the belt spine lives in an overflow-x:auto track — it must never force the page body to
       scroll horizontally.
     - every belt action button is a >=44px tap target. */

.dojo-eyebrow[b-9blsdei5hd] {
    font-family: var(--font-mono);
    font-size: 0.72rem;
    letter-spacing: var(--tracking-wide, 0.1em);
    color: var(--text-muted);
    margin-bottom: var(--space-2);
}

.learn-title[b-9blsdei5hd] {
    margin: 0 0 var(--space-2);
    font-size: var(--text-h1);
    font-weight: var(--weight-bold);
    letter-spacing: var(--tracking-tight);
    color: var(--text-heading);
}

.learn-lead[b-9blsdei5hd] {
    margin: 0 0 var(--space-6);
    font-size: var(--text-lead);
    color: var(--text-muted);
    line-height: var(--leading-snug);
    max-width: 720px;
}

.min-width-0[b-9blsdei5hd] {
    min-width: 0;
}

/* -------------------------------------------------------------------------
   Belt spine — horizontal ladder track. overflow-x:auto on the OUTER track
   only, so a long ladder scrolls within itself and never widens the page
   body (§2.4). The inner row is allowed to grow past 100% via min-content.
   ------------------------------------------------------------------------- */
.belt-spine-track[b-9blsdei5hd] {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    margin-bottom: var(--space-6);
}

.belt-spine-inner[b-9blsdei5hd] {
    position: relative;
    min-width: 100%;
    width: max-content;
    padding: var(--space-4) var(--space-2) var(--space-6);
}

.belt-spine-line[b-9blsdei5hd],
.belt-spine-fill[b-9blsdei5hd] {
    position: absolute;
    top: 60px;
    left: 56px;
    right: 56px;
    height: 3px;
    border-radius: 2px;
}

.belt-spine-line[b-9blsdei5hd] {
    background: var(--gray-300);
}

.belt-spine-fill[b-9blsdei5hd] {
    right: auto;
    background: var(--green-600);
    transition: width var(--duration, 180ms) var(--ease-standard, ease);
}

.belt-spine-nodes[b-9blsdei5hd] {
    position: relative;
    z-index: 1;
    display: flex;
    gap: var(--space-4);
}

.belt-spine-node[b-9blsdei5hd] {
    flex: 0 0 auto;
    width: 112px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: var(--space-3) var(--space-2);
    border-radius: var(--radius-lg);
    border: 2px solid transparent;
}

.belt-spine-node.is-current[b-9blsdei5hd] {
    background: var(--white);
    border-color: var(--blue-600);
    box-shadow: var(--shadow-panel);
}

.belt-spine-label[b-9blsdei5hd] {
    text-align: center;
}

.belt-spine-rank[b-9blsdei5hd] {
    font-family: var(--font-mono);
    font-size: 0.7rem;
    color: var(--text-muted);
    letter-spacing: var(--tracking-wide, 0.06em);
}

.belt-spine-name[b-9blsdei5hd] {
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    color: var(--text-heading);
    line-height: 1.2;
    margin-top: 2px;
}

.belt-spine-status[b-9blsdei5hd] {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
}

.tone-earned[b-9blsdei5hd] { color: var(--green-700); }
.tone-current[b-9blsdei5hd] { color: var(--blue-700); }
/* T-086: Unlocked ("Available") reads quieter than InProgress ("You are here") — reuses the muted
   text token rather than the blue "current" hue, so an accessible-but-not-started belt is visually
   distinct from the ONE belt actually in progress. */
.tone-available[b-9blsdei5hd] { color: var(--text-muted); }
.tone-locked[b-9blsdei5hd] { color: var(--gray-500); }

/* -------------------------------------------------------------------------
   Belt cards
   ------------------------------------------------------------------------- */
.belt-card-grid[b-9blsdei5hd] {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-5);
}

.belt-card[b-9blsdei5hd] {
    display: flex;
    flex-direction: column;
}

.belt-card-locked[b-9blsdei5hd] {
    opacity: 0.78;
}

.belt-card-strip[b-9blsdei5hd] {
    height: 8px;
}

.belt-card-eyebrow[b-9blsdei5hd] {
    font-family: var(--font-mono);
    font-size: 0.7rem;
    color: var(--text-muted);
    letter-spacing: var(--tracking-wide, 0.06em);
}

.belt-card-actions .btn[b-9blsdei5hd] {
    min-height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
}

@media (max-width: 768px) {
    .belt-card-grid[b-9blsdei5hd] {
        grid-template-columns: 1fr;
    }

    .belt-spine-node[b-9blsdei5hd] {
        width: 92px;
    }
}
/* /Components/Pages/Train/BreakoutReversalDrill.razor.rz.scp.css */
/* BreakoutReversalDrill page — scoped component CSS.
   Relies on Bootstrap for layout/colours; only page-specific rules here.
   Mirrors TrendRangeDrill.razor.css. */

.br-drill-page[b-s6mimwetbn] {
    max-width: 960px;
}

/* Chart canvas: fixed height giving a reasonable 16:9-ish ratio.
   Matches the TrendRangeDrill/SrDrill chart-wrapper proportions. */
.br-chart-wrapper[b-s6mimwetbn] {
    height: clamp(300px, 45vw, 480px);
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: var(--radius-lg, 8px);
    box-shadow: var(--shadow-panel, 0 1px 3px rgba(16, 24, 40, 0.08), 0 4px 12px rgba(16, 24, 40, 0.06));
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

/* The caption (~20px) sits above .chart-canvas-wrapper inside this fixed-height
   wrapper; without this the canvas overruns the wrapper's bottom edge and the
   x-axis time labels get clipped by overflow:hidden above (T-063).
   !important beats ChartCanvas.razor's inline min-height:300px on the wrapper. */
[b-s6mimwetbn] .chart-canvas-wrapper {
    flex: 1 1 auto;
    min-height: 0 !important;
}

/* Outcome choice buttons: large enough for >=44px tap targets on touch devices (PRD-T043c AC4). */
.br-outcome-btn[b-s6mimwetbn] {
    min-height: 44px;
    padding: 0.5rem 1rem;
    font-size: 0.9rem;
    line-height: 1.3;
    text-align: center;
    flex: 1 1 auto;
    min-width: 200px;
}

/* T-083f: border reads the shared Desk border token, matching the sibling drills' .feedback-line
   rule (SrDrill/TrendRangeDrill/TransitionsDrill) instead of a magic-number rgba. */
.br-cue[b-s6mimwetbn] {
    border: 1px solid var(--border-default, #e2e6ec);
    font-size: 0.875rem;
}

/* Landscape-phone / narrow viewport: stack buttons vertically for readability */
@media (max-width: 600px) {
    .br-outcome-buttons[b-s6mimwetbn] {
        flex-direction: column;
    }

    .br-outcome-btn[b-s6mimwetbn] {
        width: 100%;
    }

    .br-chart-wrapper[b-s6mimwetbn] {
        height: clamp(240px, 60vw, 360px);
    }
}
/* /Components/Pages/Train/DailyRegimeDrill.razor.rz.scp.css */
/* DailyRegimeDrill page — scoped component CSS.
   T-186: this page had no .razor.css of its own, so Blazor stamped its elements with no scope
   attribute at all and the rules below (declared only in sibling pages' scoped sheets, e.g.
   TrendRangeDrill.razor.css, qualified with THEIR OWN scope id) could never match. This sheet
   carries those rule bodies verbatim (PRD-T186-DRILL-CSS.md §4) to give this page its own scope id.
   Relies on Bootstrap for layout/colours; only page-specific rules here. */

.tr-drill-page[b-w41wfmclq3] {
    max-width: 960px;
}

/* Chart canvas: fixed height giving a reasonable 16:9-ish ratio.
   Matches the SrDrill chart-wrapper proportions. */
.tr-chart-wrapper[b-w41wfmclq3] {
    height: clamp(300px, 45vw, 480px);
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: var(--radius-lg, 8px);
    box-shadow: var(--shadow-panel, 0 1px 3px rgba(16, 24, 40, 0.08), 0 4px 12px rgba(16, 24, 40, 0.06));
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

/* The caption (~20px) sits above .chart-canvas-wrapper inside this fixed-height
   wrapper; without this the canvas overruns the wrapper's bottom edge and the
   x-axis time labels get clipped by overflow:hidden above (T-063).
   !important beats ChartCanvas.razor's inline min-height:300px on the wrapper. */
[b-w41wfmclq3] .chart-canvas-wrapper {
    flex: 1 1 auto;
    min-height: 0 !important;
}

/* Regime choice buttons: large enough for ≥44px tap targets on touch devices (T-023 AC4). */
.tr-regime-btn[b-w41wfmclq3] {
    min-height: 44px;
    padding: 0.5rem 1rem;
    font-size: 0.9rem;
    line-height: 1.3;
    text-align: center;
    flex: 1 1 auto;
    min-width: 160px;
}

/* .feedback-line moved to wwwroot/app.css (T-187, docs/PRD-T187-CSS-PLACEMENT-DEBT.md §2 FORK 1):
   the same rule was declared identically in four scoped sheets while two other components
   (LiveSim, ReactionDrill) wrote the class with no sheet of their own to reach — promoted to one
   global rule so all six writers reach it. */

/* Landscape-phone / narrow viewport: stack buttons vertically for readability */
@media (max-width: 600px) {
    .tr-regime-buttons[b-w41wfmclq3] {
        flex-direction: column;
    }

    .tr-regime-btn[b-w41wfmclq3] {
        width: 100%;
    }

    .tr-chart-wrapper[b-w41wfmclq3] {
        height: clamp(240px, 60vw, 360px);
    }
}
/* /Components/Pages/Train/DailyRegimeIdentifyNotesList.razor.rz.scp.css */
/* DailyRegimeIdentifyNotesList — scoped component CSS.

   Moved UNCHANGED from DailyRegimeExplain.razor.css at T-089d1-FE (PRD-T089-EXPLAINER-VISUAL.md
   §10.8, the shared-render refactor): the clarity notes markup now lives in this shared fragment
   component rather than directly in DailyRegimeExplain's own template, so the scoped rule that
   targets it moves here too (Blazor CSS isolation only auto-scopes elements a component's OWN
   .razor file renders).

   Clarity notes (PRD §9.2): plain prose blocks, no chart, sit between the triptych and the
   pullback-contrast pair. */
.tr-clarity-note h6[b-h7hjxry5l2] {
    font-weight: 600;
}
/* /Components/Pages/Train/ExplainPanelRow.razor.rz.scp.css */
/* ExplainPanelRow — scoped component CSS.

   Moved UNCHANGED from DailyRegimeExplain.razor.css at T-089d1-FE (PRD-T089-EXPLAINER-VISUAL.md
   §10.8, the shared-render refactor): this markup (the chart wrapper + marker overlay) now lives in
   this shared fragment component rather than directly in DailyRegimeExplain's own template, so the
   scoped rules that target it move here too (Blazor CSS isolation only auto-scopes elements a
   component's OWN .razor file renders).

   T-089h (PRD-T089-EXPLAINER-VISUAL.md §9.4): the parity-safe CSS-overlay bar-index markers.
   `.tr-chart-wrapper` is the wrapper this component owns around <ChartCanvas> (a plain div in the
   .razor markup, NOT ChartCanvas's own internal `.chart-canvas-wrapper`, which is JS-owned and
   overflow:hidden). Making it position:relative here turns the marker <div> below into a
   position:absolute SIBLING of <ChartCanvas> — zero JS, zero canvas edit; chart-canvas.js stays
   parity-locked (T-080/T-083). `left` is computed per-marker in
   ExplainPanelRow.razor.cs (MarkerLeftStyle) from the SAME fixed CSS-pixel constants
   chart-canvas.js's computeGeo uses (padL=10, padR=56), so it lands on the exact bar centre without
   ever reading JS geometry. */
/* T-090a (PRD-T090-S1-GOLDEN-FIX.md, Defect 1): the wrapper had NO definite height, so
   ChartCanvas's internal <canvas height:100%> collapsed to the 150px replaced-element intrinsic
   default (fit() reads clientHeight) — candlesticks rendered in the top ~half, blank below. Give
   the wrapper a definite height (named constant, shorter aspect than the drill pages' since these
   are narrow triptych/contrast columns) plus the drill-style flex + ::deep collapse so the
   internal .chart-canvas-wrapper's flex-basis resolves to a definite computed height and
   height:100% on the canvas works. overflow stays visible (default, NOT set to hidden like the
   drills) so the T-089h marker label pills (top:-1.4rem) are not clipped. CSS/sizing only — no
   chart-canvas.js or ChartCanvas.razor edit (parity-locked, T-035o/T-080/T-083). */
.tr-chart-wrapper[b-lunsa5cwf9] {
    position: relative;
    --tr-explain-chart-h: clamp(180px, 24vw, 260px);
    height: var(--tr-explain-chart-h);
    display: flex;
    flex-direction: column;
}

[b-lunsa5cwf9] .chart-canvas-wrapper {
    flex: 1 1 auto;
    min-height: 0 !important; /* Beats ChartCanvas.razor's inline min-height:300px on the wrapper. */
}

/* Vertical marker line. top/bottom = 16px matches chart-canvas.js's padTop/padBot, so the line
   spans exactly the plot area. Lives in .tr-chart-wrapper (overflow:visible by default) — one
   level ABOVE ChartCanvas's own overflow:hidden inner wrapper, so it is never clipped. */
.tr-marker[b-lunsa5cwf9] {
    position: absolute;
    top: 16px;
    bottom: 16px;
    width: 0;
    border-left: 2px dashed #f5a623;
    pointer-events: none;
    z-index: 5;
}

/* Label pill anchored to the marker line, centred on it. T-118c (F2, PRD-T118-IMAGE-EVALUATOR.md §6
   G2/§10 AC4): same defect T-117 fixed on the horizontal sibling `.tr-hmarker-label` — this vertical
   mechanism was still `white-space:nowrap` with no width limit, so a long marker label grows outside
   its own panel exactly the way the horizontal pill did before T-117.

   T-118g (QA fix 1, LIVE PROD, 2026-07-26): T-118c's own GREEN carried a false premise here, worth
   recording so it isn't repeated. It read: "clamped to the containing block (`.tr-marker`, already
   positioned within the chart wrapper) via max-width:100%". `.tr-marker` is `width: 0` (load-bearing —
   see its own comment above: the dashed line IS that zero-width box's `border-left`), so a PERCENTAGE
   max-width against it resolves to 0px, not "the chart wrapper" — every vertical label wrapped one
   character per line on prod. The horizontal sibling's identical-looking fix ported cleanly because its
   containing block, `.tr-hmarker`, declares NO `width` at all — only `left`/`right` insets — giving it a
   real inline size; `.tr-marker` only has `top`/`bottom` (block-axis, irrelevant to an inline-axis
   max-width). Percentage max-width and a zero-width positioned ancestor is the failure mode; check what
   the containing block's INLINE size actually resolves to before reusing this pattern elsewhere.

   Fix: an absolute length instead of a percentage, so there is no containing block to resolve against.
   13rem (208px) is chosen from `docs/eval/t118-label-metrics-2026-07-26.md` (measured live off
   trainer.solopilot.pro, commit f09f9be, macOS darwin 25.5.0 / Chrome / devicePixelRatio 2 / 1512×862
   viewport) — that file's narrowest recorded plot-box width is 217px (3-up triptych layout); 208px sits
   conservatively under that 217px PLOT BOX. The pill's own container, `.tr-chart-wrapper`, is not the
   plot box — it is roughly 66px wider still (the plot box is `.tr-chart-wrapper` minus `padL: 10` /
   `padR: 56`), so 208px has margin against the box that actually contains it, not just against the
   narrower box measured. THAT FILE'S OWN FONT STACK IS THE BASIS FOR THIS NUMBER (`"Helvetica Neue", Helvetica, Arial, sans-serif`
   at the resolved pill size) — a font-stack change invalidates this value and mandates a re-measure, not
   an adjustment by feel.

   This cap is a WRAP BOUND, not a containment guarantee: the pill is still centred on the marker line
   (`transform:translateX(-50%)` unchanged), so a marker sitting near a panel's edge can still place a
   capped, non-wrapping pill partly outside that panel — capping the width stops runaway text, it does
   not reposition the pill. Keeping it fully inside its panel regardless of marker position is T-119's
   scope, not this item's.

   The Domain-side length cap (SrPanelConstants.SrPanelMarkerLabelMaxChars) remains the enforceable,
   by-construction guard on how much text can ever reach this pill in the first place. Unlike
   `.tr-hmarker-label`'s comment above, THIS CSS IS NOW TEST-ASSERTED —
   PanelLabelContainingBlockT118gTests.cs (T-118g AC1/AC3) pins both the max-width shape and its sanity
   band. Line geometry (`.tr-marker`'s own `top`/`bottom`/`border-left`) is untouched — parity-matched to
   the renderer. */
/* T-120 AC1 (2026-08-02, live-prod): T-118g's fix above capped the WRAP BOUND but never gave this
   box a real INLINE SIZE to grow into, so the used width still shrink-to-fit against .tr-marker's
   zero inline size (that rule's own comment) all the way down to min-content -- every label rendered
   one word per line regardless of the 13rem cap (measured live: "not a bull day" 31px/4 lines).
   Fix: width: max-content -- chosen over the other two sound shapes (an equivalent fit-content
   keyword; or instead giving .tr-marker itself a real inline size via left+right insets, mirroring
   the sound sibling .tr-hmarker below) because max-content is the one CSS Sizing keyword whose
   definition does NOT reference the containing block's available space at all -- it is unambiguously
   the box's own preferred (single-line) width, independent of .tr-marker's zero width, then capped by
   max-width exactly as before. fit-content's spec definition explicitly clamps by the containing
   block's available space, which is itself 0 here -- a real risk of silently collapsing back to
   min-content depending on how a given engine resolves "available space" for an absolutely-positioned
   box with only left set; max-content carries no such ambiguity. Centring
   (left:50%; transform:translateX(-50%)) is unchanged and still correct: 50% of .tr-marker's
   zero-width box IS that box's own position (the marker LINE's exact X, MarkerLeftStyle), and the
   transform now shifts by half the label's REAL resolved width instead of half its min-content width.
   TradingTrainer.Domain.VerticalMarkerLabelAnchor (T-120 AC2, 3rd arbitration, wired via
   ExplainPanelRow.razor.cs's MarkerLabelAnchorStyle) layers an edge-aware ANCHOR on top of
   this ONLY for a marker whose bar-centre fraction f is genuinely near an edge (f >= 0.8125 or
   f <= 0.1875, VerticalMarkerLabelAnchor.AnchorZoneFThreshold) -- this width fix alone does not
   reposition anything, only stops the wrap. Mirrors the sound horizontal sibling .tr-hmarker-label
   below (right:0, growing leftward via its own real containing block): a right-anchored marker sets
   --tr-marker-label-right:0 (no left, no transform) so the label's RIGHT edge sits at the marker line
   (0 from either edge of .tr-marker's zero-width box is the same point) and grows LEFTWARD using its
   own max-content-resolved width; a left-anchored marker mirrors it (--tr-marker-label-left:0),
   growing RIGHTWARD. A marker in the middle zone (the majority) gets NO custom properties at all --
   MarkerLabelAnchorStyle emits an empty string for it, so the var() fallbacks below (centred) are what
   actually render, byte-identical to pre-T-120. The anchor is threaded in as CSS custom properties set
   on the PARENT .tr-marker div rather than a style attribute on this span directly --
   PanelLabelContainingBlockT118gTests' AC1 precondition (closed, cannot be edited) pins this span's
   opening tag to the exact literal <span class="tr-marker-label"> with no other attribute. Custom
   properties inherit parent-to-child. */
.tr-marker-label[b-lunsa5cwf9] {
    position: absolute;
    top: -1.4rem;
    left: var(--tr-marker-label-left, 50%);
    right: var(--tr-marker-label-right, auto);
    transform: var(--tr-marker-label-transform, translateX(-50%));
    width: max-content;
    max-width: 13rem;
    white-space: normal;
    overflow-wrap: break-word;
    text-align: center;
    font-size: 0.7rem;
    font-weight: 600;
    line-height: 1.4;
    padding: 1px 6px;
    border-radius: 4px;
    background: #f5a623;
    color: #1a1a1a; /* I-016: this element sets its own background, so it must set its own text color */
    pointer-events: none;
}

/* Distinct colour for the "pullback" pointer so the two marker kinds read differently at a glance. */
.tr-marker--pullback[b-lunsa5cwf9] {
    border-left-color: #e5484d;
}

.tr-marker--pullback .tr-marker-label[b-lunsa5cwf9] {
    background: #e5484d;
    color: #ffffff; /* I-016 */
}

/* D-049 §T-090d.B.3: GREEN "still holds" pointer for the 3rd (held counter-colour) contrast panel —
   a positive colour, visually distinct from the red --pullback disqualifier above (green = "this is
   fine / still holds" vs red = "this ends the channel"). Reuses the same .tr-marker geometry
   (line + centred label pill, MarkerLeftStyle calc) — no new geometry mechanism. */
.tr-marker--held[b-lunsa5cwf9] {
    border-left-color: #30a46c;
}

.tr-marker--held .tr-marker-label[b-lunsa5cwf9] {
    background: #30a46c;
    color: #ffffff; /* I-016: this element sets its own background, so it must set its own text color */
}

/* Horizontal (y-axis) price-level edge marker (PRD-T089 §10.6, T-089n) — the y-axis sibling of
   .tr-marker above, used by the DailyTradingRange "range" panel's top/bottom edge lines. `top` is
   computed per-marker in ExplainPanelRow.razor.cs (MarkerTopStyle) from the SAME
   parity-locked priceRange() ±10% pad + Y() map chart-canvas.js uses (padTop=padBot=16,
   PriceRangePadFraction=0.10), so it lands on the exact price level without ever reading JS
   geometry. left:10px/right:56px matches the plot box's padL/padR (chart-canvas.js:146) — the line
   never overflows the plot horizontally. */
.tr-hmarker[b-lunsa5cwf9] {
    position: absolute;
    left: 10px;
    right: 56px;
    height: 0;
    border-top: 2px dashed #f5a623;
    pointer-events: none;
    z-index: 5;
}

/* Label pill anchored to the marker line's right end BY DEFAULT. T-117 (2026-07-26 live-prod
   overflow): a 70-char zone label grew LEFTWARD out of its own panel and over the neighbouring
   column/price axis, since this was `right:0; white-space:nowrap` with no width limit. Clamped to
   the containing block (.tr-hmarker, already inset to the plot box per its own comment above) via
   max-width:100%, wrapping instead of overflowing; text-align:right keeps a wrapped pill still
   reading right-anchored. The Domain-side length cap (SrPanelConstants.SrPanelMarkerLabelMaxChars)
   is the enforceable, by-construction guard on how LONG a label can ever be. This CSS's own
   containment shape IS test-asserted: SrGraphicsMagnitudeT098pTests (T-117 F1) pins that the rule
   declares max-width, no longer declares white-space:nowrap, and that its containing block
   (.tr-hmarker) stays position:absolute; PanelLabelAnchorT119aTests (T-119a AC6) additionally pins
   width:max-content, the retained max-width:100%, and that left/right/top/transform/text-align each
   read through a var() whose fallback is today's shipped value. The remaining decorative
   declarations below (background/color/padding/border-radius/font sizing) carry no such guard.

   T-119a (PRD-T119-LABEL-PLACEMENT.md §2/§3 AC6): left/right/top/transform/text-align now read
   through var() custom properties set on the PARENT .tr-hmarker div by
   ExplainPanelRow.razor.cs's HMarkerLabelAnchorStyle (mirrors the vertical sibling's
   T-120 --tr-marker-label-* scheme) -- every var()'s FALLBACK is today's shipped value, so a marker
   with no baked SrPanelLabelAnchors override (HMarkerLabelAnchorStyle emits nothing for it) resolves
   to the exact SAME computed style as before this item, byte-for-byte. width:max-content is ADDED
   (engineering decision 1, PRD §2): under a centre anchor (left:50%; right:auto) the shrink-to-fit
   available width would otherwise be only 50% of .tr-hmarker, wrapping a pill wider than half the
   plot box -- max-content makes the used width the box's own preferred (single-line) width instead,
   still clamped by the UNCHANGED max-width:100% below. No-op for every right-anchored pill (today's
   22 unmoved + the 5 newly right-below ones): none of them wrap either way. */
.tr-hmarker-label[b-lunsa5cwf9] {
    position: absolute;
    left: var(--tr-hmarker-label-left, auto);
    right: var(--tr-hmarker-label-right, 0);
    top: var(--tr-hmarker-label-top, -1.1rem);
    transform: var(--tr-hmarker-label-transform, none);
    width: max-content;
    max-width: 100%;
    white-space: normal;
    overflow-wrap: break-word;
    text-align: var(--tr-hmarker-label-text-align, right);
    font-size: 0.7rem;
    font-weight: 600;
    line-height: 1.4;
    padding: 1px 6px;
    border-radius: 4px;
    background: #f5a623;
    color: #1a1a1a; /* I-016: this element sets its own background, so it must set its own text color */
    pointer-events: none;
}

/* T-098p (F2b, eval finding 2): ToViews now leaves exactly one of a zone's two edge markers'
   Label empty (so a band's name prints once, not twice) rather than omitting the second marker
   entirely (both edges still draw their line, per G2 "draw the band"). An empty label renders as a
   pill with no text -- hide it outright instead. Additive only: does not affect any marker that
   still carries a Label (::empty never matches a populated <span>). */
.tr-hmarker-label:empty[b-lunsa5cwf9] {
    display: none;
}

/* "sell" variant — top edge (fade the top / sell here). Reuses the --pullback red: a caution colour. */
.tr-hmarker--sell[b-lunsa5cwf9] {
    border-top-color: #e5484d;
}

.tr-hmarker--sell .tr-hmarker-label[b-lunsa5cwf9] {
    background: #e5484d;
    color: #ffffff; /* I-016 */
}

/* "buy" variant — bottom edge (fade the bottom / buy here). Reuses the --held green: a positive colour. */
.tr-hmarker--buy[b-lunsa5cwf9] {
    border-top-color: #30a46c;
}

.tr-hmarker--buy .tr-hmarker-label[b-lunsa5cwf9] {
    background: #30a46c;
    color: #ffffff; /* I-016 */
}

/* T-098p (F2a, eval finding 2, code-verified by judge A): "resistance"/"support" variants for the
   S/R explainer's Sr* illustration catalogs (TradingTrainer.Domain/Scoring.cs) — today's only two
   Variant values those catalogs emit. Before this pair, BOTH fell through to the base .tr-hmarker
   rule above (identical fixed orange dashed line), so support and resistance — and S5's whole
   polarity-flip swap — rendered identically. Reuses the SAME --zone-resistance-line/
   --zone-support-line tokens (tokens.css) the chart canvas itself already uses for this exact
   semantic — not an invented hex, and visually consistent with the chart's own S/R colour language. */
.tr-hmarker--resistance[b-lunsa5cwf9] {
    border-top-color: var(--zone-resistance-line);
}

.tr-hmarker--resistance .tr-hmarker-label[b-lunsa5cwf9] {
    background: var(--zone-resistance-line);
    color: var(--text-on-accent); /* I-016 */
}

.tr-hmarker--support[b-lunsa5cwf9] {
    border-top-color: var(--zone-support-line);
}

.tr-hmarker--support .tr-hmarker-label[b-lunsa5cwf9] {
    background: var(--zone-support-line);
    color: var(--text-on-accent); /* I-016 */
}

/* T-098p (F2a): SrExplain.razor.cs's ToViews marks ONLY the S7 "over_marked" panel's two
   untested-price noise zones (SrLayeredContrast, PRD §3.8) with this variant instead of their
   catalog "resistance" Variant — a structural over_marked-minus-every_level diff, never a
   bar-touch guess (see ToViews' own doc for why a generic guess is unsafe). The panel's 3 REAL
   levels stay solid resistance-red; the 2 noise lines read as visibly less certain (dotted, muted).
   The distinction the eval asked for is carried entirely by styling, never by the label text (F10
   already stripped the answer-revealing "noise" wording from those zones' Labels). */
.tr-hmarker--untested[b-lunsa5cwf9] {
    border-top-style: dotted;
    border-top-color: var(--muted);
}

.tr-hmarker--untested .tr-hmarker-label[b-lunsa5cwf9] {
    background: var(--gray-200);
    color: var(--text-body); /* I-016 */
    font-weight: var(--weight-regular);
}
/* /Components/Pages/Train/SrDrill.razor.rz.scp.css */
/* SrDrill page — scoped component CSS.
   Relies on Bootstrap for layout/colours; only page-specific rules here.

   T-073c: the chevron shell (.sr-chart-shell/.sr-chevron*) and the chart-canvas wrapper
   (.sr-chart-wrapper/::deep .chart-canvas-wrapper, incl. its narrow-viewport height override)
   moved to SrChartShell.razor.css and SrZoneSelector.razor.css respectively — scoped CSS does
   not cross the child-component boundary, so SrDrill no longer carries them itself.
   .sr-zone-badge/.sr-zone-remove moved to SrZoneList.razor.css (T-073b). */

.sr-drill-page[b-44yrkuqwbp] {
    max-width: 960px;
}

/* T-071: every remaining toolbar button (the TF buttons, Check, and Next) shares one height so
   the TF group doesn't stand taller than the rest. TF buttons additionally keep a wider touch
   target via min-width — see the .sr-tf-toolbar .btn rule below. (Support/Resistance/Erase/Clear
   all now live inside SrDrawToolbar, which carries its own copy of this rule — T-073a.) */
.sr-toolbar .btn[b-44yrkuqwbp] {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.sr-tf-toolbar .btn[b-44yrkuqwbp] {
    min-width: 44px;
}

/* T-080d — elevated score panel (D-038 AC3). readme.md: "the scored feedback panel gets a soft
   elevation and slightly larger (12px) radius." Content/logic untouched; the panel keeps
   Bootstrap's .card (bg/border) and only gains the Desk radius + shadow tokens (T-080a). */
.sr-feedback-panel[b-44yrkuqwbp] {
    border-radius: var(--radius-xl, 0.75rem);
    box-shadow: var(--shadow-panel, 0 1px 3px rgba(16, 24, 40, 0.08), 0 4px 12px rgba(16, 24, 40, 0.06));
}

/* .feedback-line moved to wwwroot/app.css (T-187, docs/PRD-T187-CSS-PLACEMENT-DEBT.md §2 FORK 1):
   the same rule was declared identically in four scoped sheets while two other components
   (LiveSim, ReactionDrill) wrote the class with no sheet of their own to reach — promoted to one
   global rule so all six writers reach it. */

.citation-chip[b-44yrkuqwbp] {
    font-family: ui-monospace, Menlo, monospace;
    font-size: 0.75rem;
    letter-spacing: 0.02em;
    flex-shrink: 0;
}

/* Halo detail panel */
.sr-halo-panel .halo-zone[b-44yrkuqwbp] {
    background: var(--bs-body-bg);
}

/* Landscape-phone / narrow viewport: stack toolbar vertically */
@media (max-width: 480px) {
    .sr-toolbar[b-44yrkuqwbp] {
        flex-direction: column;
        align-items: flex-start;
    }
}
/* /Components/Pages/Train/SrExplain.razor.rz.scp.css */
/* SrExplain — scoped component CSS.

   Added at T-110 (docs/"TradingTrainer Design System.zip" -> design_handoff_sr_explainer/, board
   T-110): the S0 "how it works" restyle — page shell, numbered section headings (mono index +
   uppercase title, index generated via CSS counter()), card chrome, typography scale. Styling
   only; no learner-visible prose added here (CSS has none to add). Tokens come from
   wwwroot/css/tokens.css only — no new custom properties are declared, no hex is hard-coded.

   T-132: the rules shared with DailyRegimeExplain/TrendRangeExplain (.tr-explain-page and its
   descendants, .tr-explain-card/.desk-card) moved to the global wwwroot/app.css — a
   component-scoped sheet only applies to ITS OWN component's Blazor scope id, so those rules
   never styled the other two pages, which have no .razor.css of their own. What remains here is
   genuinely SrExplain-only: the S0 numbered framing section below. */

/* S0 numbered framing sections -- the design's signature element. */

.sr-s0-framing[b-szheioejw6] {
    counter-reset: sr-s0;
    margin-top: 40px;
}

.sr-s0-point[b-szheioejw6] {
    counter-increment: sr-s0;
    position: relative;
    padding-left: 56px;
    margin-top: 44px;
}

.sr-s0-point:first-child[b-szheioejw6] {
    margin-top: 0;
}

.sr-s0-point-heading[b-szheioejw6] {
    font-size: 15px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--gray-900);
}

.sr-s0-point-heading[b-szheioejw6]::before {
    content: counter(sr-s0, decimal-leading-zero);
    position: absolute;
    left: 0;
    top: 2px;
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: normal;
    text-transform: none;
    color: var(--blue-600);
}

.sr-s0-point-body[b-szheioejw6] {
    font-size: 15px;
    line-height: 1.6;
    color: var(--gray-700);
}

/* S0 rule lists (T-111) -- F2/F3/F4 render as an ordered, always-visible sequence of rules
   instead of one paragraph. Reading order is load-bearing (D-071): no chips, no reordering, no
   collapsing. The rule index is generated content only, mirroring .sr-s0-point-heading::before
   above -- never a literal digit in the markup. */

.sr-s0-rules[b-szheioejw6] {
    counter-reset: sr-s0-rule;
    list-style: none;
    margin: 12px 0 0;
    padding: 0;
}

.sr-s0-rule[b-szheioejw6] {
    counter-increment: sr-s0-rule;
    position: relative;
    padding-left: 32px;
    margin-top: 12px;
}

.sr-s0-rule:first-child[b-szheioejw6] {
    margin-top: 0;
}

.sr-s0-rule[b-szheioejw6]::before {
    content: counter(sr-s0-rule, decimal-leading-zero);
    position: absolute;
    left: 0;
    top: 2px;
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 600;
    color: var(--blue-600);
}

.sr-s0-rule-label[b-szheioejw6] {
    display: block;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--gray-900);
}

.sr-s0-rule-text[b-szheioejw6] {
    display: block;
    font-size: 15px;
    line-height: 1.6;
    color: var(--gray-700);
}

@media (max-width: 820px) {
    .sr-s0-point[b-szheioejw6] {
        padding-left: 0;
        padding-top: 28px;
    }

    .sr-s0-point-heading[b-szheioejw6]::before {
        left: 0;
        top: 0;
    }

    .sr-s0-rule[b-szheioejw6] {
        padding-left: 0;
        padding-top: 20px;
    }

    .sr-s0-rule[b-szheioejw6]::before {
        left: 0;
        top: 0;
    }
}

/* /Components/Pages/Train/TransitionsDrill.razor.rz.scp.css */
/* TransitionsDrill page — scoped component CSS.
   Relies on Bootstrap for layout/colours; only page-specific rules here. */

.td-drill-page[b-bad8e3hsic] {
    max-width: 960px;
}

/* Chart canvas: fixed height giving a reasonable 16:9-ish ratio.
   Matches the TrendRangeDrill chart-wrapper proportions. */
.td-chart-wrapper[b-bad8e3hsic] {
    height: clamp(300px, 45vw, 480px);
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: var(--radius-lg, 8px);
    box-shadow: var(--shadow-panel, 0 1px 3px rgba(16, 24, 40, 0.08), 0 4px 12px rgba(16, 24, 40, 0.06));
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

/* The caption (~20px) sits above .chart-canvas-wrapper inside this fixed-height
   wrapper; without this the canvas overruns the wrapper's bottom edge and the
   x-axis time labels get clipped by overflow:hidden above (T-063).
   !important beats ChartCanvas.razor's inline min-height:300px on the wrapper. */
[b-bad8e3hsic] .chart-canvas-wrapper {
    flex: 1 1 auto;
    min-height: 0 !important;
}

/* Check button: large enough for ≥44px tap targets on touch devices (I-008 / T-023 AC4 precedent). */
.td-check-btn[b-bad8e3hsic] {
    min-height: 44px;
    padding: 0.5rem 1.5rem;
    font-size: 0.9rem;
}

/* .feedback-line moved to wwwroot/app.css (T-187, docs/PRD-T187-CSS-PLACEMENT-DEBT.md §2 FORK 1):
   the same rule was declared identically in four scoped sheets while two other components
   (LiveSim, ReactionDrill) wrote the class with no sheet of their own to reach — promoted to one
   global rule so all six writers reach it. */

/* Landscape-phone / narrow viewport: compact chart for readability */
@media (max-width: 600px) {
    .td-chart-wrapper[b-bad8e3hsic] {
        height: clamp(240px, 60vw, 360px);
    }
}
/* /Components/Pages/Train/TrendRangeDrill.razor.rz.scp.css */
/* TrendRangeDrill page — scoped component CSS.
   Relies on Bootstrap for layout/colours; only page-specific rules here. */

.tr-drill-page[b-gx55g7yxj1] {
    max-width: 960px;
}

/* Chart canvas: fixed height giving a reasonable 16:9-ish ratio.
   Matches the SrDrill chart-wrapper proportions. */
.tr-chart-wrapper[b-gx55g7yxj1] {
    height: clamp(300px, 45vw, 480px);
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: var(--radius-lg, 8px);
    box-shadow: var(--shadow-panel, 0 1px 3px rgba(16, 24, 40, 0.08), 0 4px 12px rgba(16, 24, 40, 0.06));
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

/* The caption (~20px) sits above .chart-canvas-wrapper inside this fixed-height
   wrapper; without this the canvas overruns the wrapper's bottom edge and the
   x-axis time labels get clipped by overflow:hidden above (T-063).
   !important beats ChartCanvas.razor's inline min-height:300px on the wrapper. */
[b-gx55g7yxj1] .chart-canvas-wrapper {
    flex: 1 1 auto;
    min-height: 0 !important;
}

/* Regime choice buttons: large enough for ≥44px tap targets on touch devices (T-023 AC4). */
.tr-regime-btn[b-gx55g7yxj1] {
    min-height: 44px;
    padding: 0.5rem 1rem;
    font-size: 0.9rem;
    line-height: 1.3;
    text-align: center;
    flex: 1 1 auto;
    min-width: 160px;
}

/* .feedback-line moved to wwwroot/app.css (T-187, docs/PRD-T187-CSS-PLACEMENT-DEBT.md §2 FORK 1):
   the same rule was declared identically in four scoped sheets while two other components
   (LiveSim, ReactionDrill) wrote the class with no sheet of their own to reach — promoted to one
   global rule so all six writers reach it. */

/* Landscape-phone / narrow viewport: stack buttons vertically for readability */
@media (max-width: 600px) {
    .tr-regime-buttons[b-gx55g7yxj1] {
        flex-direction: column;
    }

    .tr-regime-btn[b-gx55g7yxj1] {
        width: 100%;
    }

    .tr-chart-wrapper[b-gx55g7yxj1] {
        height: clamp(240px, 60vw, 360px);
    }
}
/* /Components/Shared/ScenarioFeedbackWidget.razor.rz.scp.css */
/* ScenarioFeedbackWidget — T-072b: bottom-right content-QA control.
   Positioned absolute within its host container (SrDrill.razor's .sr-chart-wrapper, which declares
   position:relative for this — SrDrill.razor.css). Deliberately NOT position:fixed to the viewport:
   that would risk colliding with the global Glossary FAB (.glx-fab, position:fixed;
   bottom:18px; right:18px; z-index:9998 — I-030), which this widget sits well above since it is
   scoped to the chart area, not the page bottom. */

.sr-feedback-widget[b-ro74drs3z0] {
    position: absolute;
    right: 8px;
    bottom: 8px;
    z-index: 5;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    max-width: min(260px, 80%);
}

.sr-feedback-buttons[b-ro74drs3z0] {
    display: flex;
    gap: 4px;
}

.sr-feedback-btn[b-ro74drs3z0] {
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid var(--bs-border-color);
    border-radius: 50%;
    background: var(--bs-body-bg);
    color: var(--bs-body-color);
    opacity: 0.75;
    font-size: 1rem;
    line-height: 1;
    cursor: pointer;
    transition: opacity 0.15s ease-in-out;
}

.sr-feedback-btn:hover:not(:disabled)[b-ro74drs3z0],
.sr-feedback-btn:focus-visible[b-ro74drs3z0] {
    opacity: 1;
}

.sr-feedback-btn:disabled[b-ro74drs3z0] {
    opacity: 0.35;
    cursor: default;
}

.sr-feedback-comment[b-ro74drs3z0] {
    background: var(--bs-body-bg);
    color: var(--bs-body-color);
    border: 1px solid var(--bs-border-color);
    border-radius: 6px;
    padding: 6px;
    width: 220px;
    /* T-083f: shared Desk elevation token (matches SrDrill.razor.css's .sr-feedback-panel) instead
       of a magic-number box-shadow. */
    box-shadow: var(--shadow-raised, 0 1px 2px rgba(16, 24, 40, 0.06), 0 1px 3px rgba(16, 24, 40, 0.10));
}

.sr-feedback-textarea[b-ro74drs3z0] {
    resize: vertical;
    font-size: 0.8rem;
}

.sr-feedback-comment-actions[b-ro74drs3z0] {
    display: flex;
    justify-content: flex-end;
    gap: 4px;
    margin-top: 4px;
}

.sr-feedback-status[b-ro74drs3z0] {
    font-size: 0.75rem;
    padding: 2px 6px;
    border-radius: 4px;
    background: var(--bs-body-bg);
    color: var(--bs-body-color);
    border: 1px solid var(--bs-border-color);
}

.sr-feedback-thanks[b-ro74drs3z0] {
    color: var(--bs-success, #198754);
}

.sr-feedback-error[b-ro74drs3z0] {
    color: var(--bs-danger, #dc3545);
}
/* /Components/Shared/SrChartShell.razor.rz.scp.css */
/* SrChartShell — scoped component CSS.
   T-073c: carried verbatim from SrDrill.razor.css (the T-068d edge-pan chevron flex row + button
   styling). The old ".sr-chart-shell .sr-chart-wrapper" sizing rule does not carry — scoped CSS
   does not cross the child-component boundary, so it is replaced by ".sr-chart-shell-body" below,
   which sizes the div THIS component wraps around ChildContent. */

.sr-chart-shell[b-df1zt1vkx4] {
    display: flex;
    align-items: center;
    gap: 6px;
}

.sr-chart-shell-body[b-df1zt1vkx4] {
    flex: 1 1 auto;
    min-width: 0;
}

.sr-chevron[b-df1zt1vkx4] {
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid var(--bs-border-color);
    border-radius: 50%;
    background: var(--bs-body-bg);
    color: var(--bs-body-color);
    opacity: 0.55;
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
    transition: opacity 0.15s ease-in-out;
}

.sr-chevron:hover:not(:disabled)[b-df1zt1vkx4],
.sr-chevron:focus-visible[b-df1zt1vkx4] {
    opacity: 0.9;
}

.sr-chevron:disabled[b-df1zt1vkx4] {
    opacity: 0.2;
    cursor: default;
}
/* /Components/Shared/SrDrawToolbar.razor.rz.scp.css */
/* SrDrawToolbar — scoped component CSS.
   T-071's 44px touch-target rule, scoped to THIS component's own class: scoped CSS does not
   cross the child-component boundary, so the atom must carry its own copy (it no longer inherits
   SrDrill.razor.css's .sr-toolbar .btn rule once mounted as a child component elsewhere). */
.sr-draw-toolbar .btn[b-0jtwwtidhg] {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* T-080d — segmented blue tool-toggle (D-038 AC1). Visual only: no class is added/removed and
   ToolSelected/Cleared wiring is untouched (SrDrawToolbar.razor.cs's ToolClass() already emits
   "btn-primary" for the active tool / "btn-outline-secondary" for inactive ones — see that file).
   The active segment already resolves blue for free: btn-primary reads --bs-primary, which
   tokens.css (T-080a) remaps to --blue-600. The inactive segment resolves Bootstrap's OWN
   --bs-secondary, which T-080a intentionally remaps to the dark --ink-900 brand tone for
   STANDALONE secondary buttons app-wide — too strong for this group's "off" state, which should
   read neutral so the active blue segment stays the only signal. Scope a lighter neutral to just
   this toolbar's group; nothing here touches the --bs-* tokens themselves. Bootstrap's own
   .btn-group rules already merge the borders and round only the group's outer corners, using
   --bs-border-radius = var(--radius) (T-080a) — no extra radius rule needed. */
.sr-draw-toolbar .btn-group > .btn-outline-secondary[b-0jtwwtidhg] {
    color: var(--gray-700, #44505e);
    border-color: var(--border-default, #e2e6ec);
    background-color: var(--white, #fff);
}

.sr-draw-toolbar .btn-group > .btn-outline-secondary:hover:not(:disabled)[b-0jtwwtidhg] {
    background-color: var(--surface-subtle, #f4f6f9);
}
/* /Components/Shared/SrZoneList.razor.rz.scp.css */
/* SrZoneList — scoped component CSS.
   T-073b: carried verbatim from SrDrill.razor.css (the hover-highlight + per-badge remove (x)
   button rules). The root <ul> carries no dedicated wrapper class of its own — only Bootstrap
   utility classes (list-unstyled etc.) on the host markup — so no layout rule to carry. */
.sr-zone-badge[b-532d62fk7d] {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.sr-zone-badge:hover[b-532d62fk7d] {
    filter: brightness(1.3);
}

.sr-zone-remove[b-532d62fk7d] {
    background: transparent;
    border: none;
    padding: 0 2px;
    color: inherit;
    font-size: 0.9rem;
    line-height: 1;
    cursor: pointer;
}

.sr-zone-remove:hover[b-532d62fk7d] {
    color: var(--bs-danger);
}
/* /Components/Shared/SrZoneSelector.razor.rz.scp.css */
/* SrZoneSelector — scoped component CSS.
   T-073c: carried verbatim from SrDrill.razor.css (the chart-canvas wrapper sizing/frame rules).
   .sr-chart-shell/.sr-chevron* moved to SrChartShell.razor.css instead — not duplicated here.
   .sr-zone-badge/.sr-zone-remove already live in SrZoneList.razor.css (T-073b) — not duplicated. */

/* Chart canvas: fixed height that gives a reasonable 16:9-ish ratio.
   100vw is limited by the host page's own max-width; height is explicit so the canvas knows its
   CSS dimensions before JS measure (avoids 0-height on first draw).
   T-068b AC1: theme-aware card-frame border (radius already present) — does not touch
   overflow:hidden, so the T-063 axis-label-clipping fix is unchanged. */
.sr-chart-wrapper[b-u0aqu6y4m0] {
    height: clamp(300px, 45vw, 480px);
    border: 1px solid var(--bs-border-color);
    border-radius: var(--radius-lg, 8px);
    box-shadow: var(--shadow-panel, 0 1px 3px rgba(16, 24, 40, 0.08), 0 4px 12px rgba(16, 24, 40, 0.06));
    overflow: hidden;
    display: flex;
    flex-direction: column;
    /* T-072b / I-030: anchors an absolutely-positioned ChartOverlay (e.g. ScenarioFeedbackWidget)
       to the chart area itself (not the viewport — avoids the Glossary FAB). */
    position: relative;
}

/* The caption (~20px) sits above .chart-canvas-wrapper inside this fixed-height wrapper; without
   this the canvas overruns the wrapper's bottom edge and the x-axis time labels get clipped by
   overflow:hidden above (T-063).
   !important beats ChartCanvas.razor's inline min-height:300px on the wrapper. */
[b-u0aqu6y4m0] .chart-canvas-wrapper {
    flex: 1 1 auto;
    min-height: 0 !important;
}

/* Landscape-phone / narrow viewport: shrink the chart height. */
@media (max-width: 480px) {
    .sr-chart-wrapper[b-u0aqu6y4m0] {
        height: clamp(240px, 60vw, 360px);
    }
}
