/* ============================================================================
   "My day" — the staff self-view (#181).

   THE RULE THIS STYLESHEET ENFORCES:

     MEASURED things are drawn in INK.       (the class: wearables in a room, majority section)
     ASSUMED things are drawn as QUESTIONS.  (the subject: just their primary — nothing sensed it)

   A subject that looks as solid as the class it sits on is a lie told with typography. So an
   assumed subject is dotted and italic, and it goes SOLID the moment the teacher confirms it.
   The day arrives as a guess and the teacher inks it in.

   Tokens only (--yb-*); light + dark via the existing [data-theme="dark"] overrides.
   ============================================================================ */

/* Left-aligned, explicitly. The app shell centres its content, and centred prose in a reading pane
   is a wall — the eye loses the left edge it needs to come back to on every line. This screen is
   read, not admired. */
.yb-sd {
    max-width: 1180px;
    margin: 0 auto;
    padding: 1.5rem 1rem 4rem;
    text-align: left;
}

/* ── Header ───────────────────────────────────────────────────────────────── */
.yb-sd-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--yb-border);
    margin-bottom: 1.5rem;
}

.yb-sd-title {
    margin: 0;
    font-family: "Fraunces", Georgia, serif;
    font-size: 1.6rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--yb-text);
}

.yb-sd-who {
    margin: 0.2rem 0 0;
    font-size: 0.85rem;
    color: var(--yb-text-muted);
}

.yb-sd-who b { color: var(--yb-text); font-weight: 600; }

.yb-sd-daynav {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.yb-sd-daynav__day {
    font-family: var(--yb-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.84rem;
    color: var(--yb-text);
    padding: 0.32rem 0.7rem;
    background: var(--yb-surface-2);
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-sm);
    white-space: nowrap;
}

/* ── Buttons ──────────────────────────────────────────────────────────────── */
.yb-sd-btn {
    font: inherit;
    font-size: 0.79rem;
    font-weight: 600;
    padding: 0.32rem 0.7rem;
    cursor: pointer;
    color: var(--yb-text);
    background: var(--yb-surface);
    border: 1px solid var(--yb-border-strong);
    border-radius: var(--yb-radius-sm);
}

.yb-sd-btn:hover:not(:disabled) { color: var(--yb-brand-600); border-color: var(--yb-brand-600); }
.yb-sd-btn:disabled { opacity: 0.45; cursor: default; }

.yb-sd-btn--primary {
    color: #fff;
    background: var(--yb-brand-600);
    border-color: var(--yb-brand-600);
}

.yb-sd-btn--primary:hover:not(:disabled) {
    color: #fff;
    background: var(--yb-brand-900);
    border-color: var(--yb-brand-900);
}

/* ── The day in numbers (#187) ─────────────────────────────────────────────
   Chips, not a stat-tile grid: these are small facts read in passing, and giving each one a card
   would make the count of them feel like the point. Every chip is a thing the teacher would
   otherwise have to add up off the screen. */
.yb-sd-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem;
    margin: 0 0 1.25rem;
}

.yb-sd-chip {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
    padding: 0.35rem 0.7rem;
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-sm);
    background: var(--yb-surface);
    font-size: 0.78rem;
    color: var(--yb-text-muted);
    white-space: nowrap;
}

.yb-sd-chip b {
    font-family: var(--yb-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.86rem;
    font-weight: 700;
    color: var(--yb-text);
}

.yb-sd-chip__sub { font-size: 0.72rem; opacity: 0.85; }

.yb-sd-chip.is-alert { border-color: rgba(var(--yb-danger-rgb), 0.35); }
.yb-sd-chip.is-alert b { color: var(--yb-required); }

/* The workload (#191): what the day asked of them, and what it gave back. */
.yb-sd-chip.is-load b { color: var(--yb-brand-600); }

.yb-sd-chip.is-free {
    border-color: rgba(var(--yb-success-rgb), 0.4);
    background: rgba(var(--yb-success-rgb), 0.05);
}

.yb-sd-chip.is-free b { color: var(--yb-success); }

.yb-sd-chip.is-stress { border-color: rgba(var(--yb-warning-rgb, 180 83 9), 0.35); }

/* Every subject settled. The only chip allowed to look pleased with itself. */
.yb-sd-chip.is-done { border-color: rgba(var(--yb-success-rgb), 0.4); }
.yb-sd-chip.is-done b { color: var(--yb-success); }

.yb-sd-chip.is-todo b { color: var(--yb-text); }

/* "We couldn't measure you" is not a number, and must never be dressed as one. */
.yb-sd-chip.is-muted { border-style: dashed; }

/* ── The workspace: the spine, and the moment ─────────────────────────────── */
.yb-sd-work {
    display: grid;
    grid-template-columns: minmax(280px, 380px) 1fr;
    gap: 1.25rem;
    align-items: start;
}

/* On a phone the day comes first and the detail follows it — a teacher scrolls to the moment they
   tapped, rather than losing the spine to a side rail that has nowhere to sit. */
/* On a phone the day comes first and the detail follows it — a teacher scrolls to the moment they
   tapped. Neither column gets a scrollbar of its own; the page is the scroll. */
@media (max-width: 900px) {
    .yb-sd-work { grid-template-columns: 1fr; }

    .yb-sd-pane,
    .yb-sd-spine {
        position: static;
        max-height: none;
        overflow: visible;
    }
}

/* ── SIGNATURE: the spine — the day as it was actually lived ───────────────
   One column, in order, with the class you held, the alert that pulled you out of it and the stress
   that sat on top of both on the SAME rail. The old screen drew three separate strips and left the
   teacher to line them up by eye. The rail is the day; the marks say what kind of thing happened. */
.yb-sd-spine {
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-sm);
    background: var(--yb-surface);
    padding: 1rem 1rem 0.75rem;

    /* The day scrolls in its own column, so the pane beside it never leaves the screen. A full day is
       sixteen half-hour blocks; without this the teacher scrolls the whole page to reach 15:30 and
       loses the very thing they were reading. */
    max-height: calc(100vh - 8rem);
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* Slim scrollbars. The bar is a control, not a piece of furniture: a 17px platform bar down the middle
   of a two-column workspace is the widest, loudest thing on a screen otherwise made of hairlines.

   `scrollbar-width: thin` is applied ONLY where the ::-webkit-scrollbar pseudos don't exist (Firefox).
   Set unconditionally, it WINS over them in Chromium and pins the bar at ~11px, so the 6px rules below
   would silently do nothing. */
@supports not selector(::-webkit-scrollbar) {
    .yb-sd-spine,
    .yb-sd-pane {
        scrollbar-width: thin;
        scrollbar-color: var(--yb-border-strong) transparent;
    }
}

.yb-sd-spine::-webkit-scrollbar,
.yb-sd-pane::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}

.yb-sd-spine::-webkit-scrollbar-track,
.yb-sd-pane::-webkit-scrollbar-track {
    background: transparent;
}

.yb-sd-spine::-webkit-scrollbar-thumb,
.yb-sd-pane::-webkit-scrollbar-thumb {
    border-radius: 999px;
    background: var(--yb-border-strong);
}

.yb-sd-spine:hover::-webkit-scrollbar-thumb,
.yb-sd-pane:hover::-webkit-scrollbar-thumb {
    background: var(--yb-text-muted);
}

.yb-sd-spine__head { margin-bottom: 0.9rem; }

.yb-sd-spine__title {
    margin: 0;
    font-family: "Fraunces", Georgia, serif;
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--yb-text);
}

.yb-sd-spine__sub {
    display: block;
    margin-top: 0.15rem;
    font-size: 0.76rem;
    line-height: 1.45;
    color: var(--yb-text-muted);
}

.yb-sd-moments {
    list-style: none;
    margin: 0;
    padding: 0;
}

.yb-sd-moment {
    position: relative;
    display: grid;
    grid-template-columns: 3.1rem 1.1rem 1fr;
    align-items: start;
    gap: 0.4rem;
    width: 100%;
    padding: 0.55rem 0.5rem;
    border: 0;
    border-radius: var(--yb-radius-sm);
    background: transparent;
    text-align: left;
    cursor: pointer;
    transition: background 0.12s ease;
}

.yb-sd-moment:hover { background: var(--yb-surface-2); }

.yb-sd-moment:focus-visible {
    outline: 2px solid var(--yb-brand-500, var(--yb-info));
    outline-offset: 1px;
}

/* The open moment. A left rail, not a fill: the pane beside it is already shouting. */
.yb-sd-moment.is-selected {
    background: var(--yb-surface-2);
    box-shadow: inset 3px 0 0 0 var(--yb-brand-600, var(--yb-info));
}

.yb-sd-moment__at {
    padding-top: 0.05rem;
    font-family: var(--yb-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.76rem;
    color: var(--yb-text-muted);
}

/* THE RAIL. One continuous line down the day, with a mark per moment — so the gaps between things
   are as visible as the things, which is most of what a day is. */
.yb-sd-moment__mark {
    position: relative;
    align-self: stretch;
    display: block;
    min-height: 1.6rem;
}

.yb-sd-moment__mark::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: -0.55rem;
    left: 50%;
    width: 1px;
    transform: translateX(-50%);
    background: var(--yb-border);
}

.yb-sd-moments li:last-child .yb-sd-moment__mark::before { bottom: 0.6rem; }

.yb-sd-moment__mark::after {
    content: "";
    position: absolute;
    top: 0.3rem;
    left: 50%;
    width: 9px;
    height: 9px;
    transform: translateX(-50%);
    border-radius: 2px;
    background: var(--yb-surface);
    border: 2px solid var(--yb-border-strong);
}

/* The three marks differ in SHAPE, not just colour — a red dot and an amber dot are one glance away
   from being the same thing, and colour alone fails anyone who cannot separate the two hues. */

/* A class: a solid square. It was measured, and it occupies time. */
.yb-sd-moment.is-class .yb-sd-moment__mark::after {
    background: var(--yb-info);
    border-color: var(--yb-info);
}

/* An alert: a filled circle with a halo — it happened to someone ELSE and it came for the teacher.
   The loudest thing in a day, so it is the loudest mark. */
.yb-sd-moment.is-alert .yb-sd-moment__mark::after {
    width: 11px;
    height: 11px;
    top: 0.25rem;
    background: var(--yb-required);
    border-color: var(--yb-required);
    border-radius: 50%;
    box-shadow: 0 0 0 3px rgba(var(--yb-danger-rgb), 0.18);
}

/* Stress: a hollow DIAMOND — the teacher's own body, not an event someone else caused. Different
   shape, different weight, and quieter on purpose. */
.yb-sd-moment.is-stress .yb-sd-moment__mark::after {
    top: 0.35rem;
    background: var(--yb-surface);
    border-color: var(--yb-warning);
    border-radius: 1px;
    transform: translateX(-50%) rotate(45deg);
}

/* FREE TIME (#191). Half an hour with no class in it, drawn GREEN and named as the teacher's own.
   It used to be a grey, dashed, italic "no class held" — the timetable's point of view, in which an
   empty period is a hole. From where the teacher stands it is the opposite: it is the part of the day
   they got back, and a day with six green blocks in it is a day that treated them well. So the free
   blocks are the ONE warm thing on the screen, and there is no reason for them to whisper. */
.yb-sd-moment.is-gap {
    cursor: default;
    background: rgba(var(--yb-success-rgb), 0.06);
    border-radius: var(--yb-radius-sm);
    margin-bottom: 2px;
}

.yb-sd-moment.is-gap .yb-sd-moment__mark::after {
    display: block;
    width: 7px;
    height: 7px;
    top: 0.4rem;
    background: var(--yb-success);
    border-color: var(--yb-success);
    border-radius: 50%;
    opacity: 0.55;
}

.yb-sd-moment.is-gap .yb-sd-moment__mark::before {
    background: repeating-linear-gradient(
        to bottom,
        rgba(var(--yb-success-rgb), 0.45) 0 3px,
        transparent 3px 7px);
}

.yb-sd-moment.is-gap .yb-sd-moment__what {
    font-weight: 600;
    color: var(--yb-success);
}

.yb-sd-moment__kind.is-free {
    background: rgba(var(--yb-success-rgb), 0.14);
    color: var(--yb-success);
}

/* The kind chip and the name of the thing, on ONE line. Stacked, a nine-minute reading took three
   lines and a selected row read as a paragraph (#191). */
.yb-sd-moment__line {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
    min-width: 0;
}

/* What KIND of thing this was, in words. Two coloured dots never said "someone else's emergency"
   versus "your own heartbeat"; a label does. */
.yb-sd-moment__kind {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    align-self: flex-start;
    margin-bottom: 0.1rem;
    padding: 0.05rem 0.35rem;
    border-radius: var(--yb-radius-sm);
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.yb-sd-moment__kind.is-alert {
    background: rgba(var(--yb-danger-rgb), 0.12);
    color: var(--yb-required);
}

.yb-sd-moment__kind.is-stress {
    background: rgba(var(--yb-warning-rgb), 0.16);
    color: var(--yb-warning);
}

.yb-sd-moment__called { font-weight: 400; color: var(--yb-text-muted); }

/* WHAT HAPPENED DURING THE CLASS. Indented under the lesson it interrupted, because that is where it
   happened: the alert at 11:12 came in the middle of the 11:09 lesson and took the teacher out of the
   room. As a sibling it read as a separate episode of the day; nested, it reads as the truth. The
   bracket down the left is the class still running around it. */
.yb-sd-during {
    margin: 0.1rem 0 0.35rem 1.55rem;
    padding-left: 0.75rem;
    border-left: 2px solid var(--yb-info);
    border-bottom-left-radius: var(--yb-radius-sm);
    opacity: 0.95;
}

/* The children hang off the class's bracket, so they don't need a rail of their own. */
.yb-sd-during .yb-sd-moment__mark::before { display: none; }

.yb-sd-during .yb-sd-moment { padding-top: 0.4rem; padding-bottom: 0.4rem; }

.yb-sd-moment__body {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
}

.yb-sd-moment__what {
    font-weight: 600;
    font-size: 0.88rem;
    color: var(--yb-text);
}

.yb-sd-moment__meta {
    font-size: 0.74rem;
    color: var(--yb-text-muted);
}

/* The subject rides along on the spine, and a guess still LOOKS like a guess here. */
.yb-sd-moment__subj {
    align-self: flex-start;
    margin-top: 0.15rem;
    font-size: 0.72rem;
}

.yb-sd-moment__subj.is-assumed {
    font-style: italic;
    color: var(--yb-text-muted);
    border-bottom: 1px dotted var(--yb-border-strong);
}

.yb-sd-moment__subj.is-confirmed { color: var(--yb-success); font-weight: 600; }
.yb-sd-moment__subj.is-open { color: var(--yb-warning, #b45309); font-weight: 600; }

/* ── The moment, opened ───────────────────────────────────────────────────── */
/* The pane holds its place while the day is read.
   `position: sticky` alone could not do it: an ancestor in the app shell is a scroll CONTAINER
   (overflow-y: auto) that never actually scrolls — the window does — so the pane was sticking to a
   scrollport that stands still, and slid away off the top of the screen. Rather than reach up and
   restyle the shell, the workspace becomes a real master–detail: the spine scrolls in its own column
   and the pane stays put beside it, which is what the teacher wanted from it anyway. */
.yb-sd-pane {
    position: sticky;
    top: 1rem;
    max-height: calc(100vh - 8rem);
    overflow-y: auto;
    overscroll-behavior: contain;
}

.yb-sd-pane__empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 3rem 1rem;
    border: 1px dashed var(--yb-border);
    border-radius: var(--yb-radius-sm);
    color: var(--yb-text-muted);
    font-size: 0.85rem;
}

.yb-sd-detail {
    border: 1px solid var(--yb-border);
    border-left: 3px solid var(--yb-info);
    border-radius: var(--yb-radius-sm);
    background: var(--yb-surface);
    padding: 1.15rem 1.25rem;
}

.yb-sd-detail.is-low { border-left-style: dashed; border-left-color: var(--yb-border-strong); }
.yb-sd-detail.is-alert { border-left-color: var(--yb-required); }
.yb-sd-detail.is-stress { border-left-color: var(--yb-warning, #b45309); }

.yb-sd-detail__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.7rem;
    flex-wrap: wrap;
    margin-bottom: 0.6rem;
}

.yb-sd-detail__title {
    margin: 0;
    font-family: "Fraunces", Georgia, serif;
    font-size: 1.18rem;
    font-weight: 600;
    color: var(--yb-text);
}

/* The escalation level, shown only when the alert actually escalated (#198). A quiet prefix to the
   step's meaning — the meaning is the sentence, the level is a qualifier on it. */
.yb-sd-trail__level {
    margin-right: 0.35rem;
    font-size: 0.76rem;
    font-weight: 600;
    color: var(--yb-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* The criticality, beside the kind rather than instead of it (#196). Secondary weight and colour:
   the kind is what the alert WAS, the criticality is how urgent — the title should read in that
   order, not compete. Tokens only, so dark mode follows without its own rule. */
.yb-sd-detail__crit {
    margin-left: 0.45rem;
    font-family: "Hanken Grotesk", system-ui, sans-serif;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--yb-text-muted);
    letter-spacing: 0.01em;
}

.yb-sd-detail__meta {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin: 0.25rem 0 0;
}

/* The call, in facts. A definition list because that is what it is. */
.yb-sd-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 0.75rem;
    margin: 0.9rem 0 0;
    padding: 0.85rem;
    border-radius: var(--yb-radius-sm);
    background: var(--yb-surface-2);
}

.yb-sd-facts dt {
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--yb-text-muted);
}

.yb-sd-facts dd {
    margin: 0.15rem 0 0;
    font-size: 0.85rem;
    color: var(--yb-text);
}

.yb-sd-facts__none { color: var(--yb-text-muted); font-style: italic; }

/* Stress: where the reading sat, and where the day sat — named, never numbered (#205). Two tiles, not
   the three SI values this used to be, so auto-fit rather than a fixed column count: with one band
   resolved and not the other, the surviving tile takes the row instead of leaving a hole. */
.yb-sd-si {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: 0.6rem;
    margin-top: 0.9rem;
}

.yb-sd-si__stat {
    padding: 0.7rem 0.6rem;
    border-radius: var(--yb-radius-sm);
    background: var(--yb-surface-2);
    text-align: center;
}

/* A band NAME, so it takes the display face rather than the tabular-numeral one the SI value wanted —
   and it must survive an organization calling D3 "Considerably above usual", hence the wrap and the
   restrained size. */
.yb-sd-si__band {
    display: block;
    font-family: var(--yb-font-display);
    font-size: 1.05rem;
    font-weight: 600;
    line-height: 1.25;
    color: var(--yb-text);
    text-wrap: balance;
}

.yb-sd-si__label {
    display: block;
    margin-top: 0.15rem;
    font-size: 0.7rem;
    line-height: 1.3;
    color: var(--yb-text-muted);
}

/* SparklineChart draws into a 300-wide viewBox and lets it centre inside whatever box it is given, so
   in a wide pane the line floats in the middle with dead air either side and reads as a broken chart.
   Give it a box its own width instead of changing a component three analytics screens depend on. */
.yb-sd-spark {
    margin-top: 0.9rem;
    max-width: 320px;
}

.yb-sd-spark__cap {
    display: block;
    margin-top: 0.2rem;
    font-size: 0.72rem;
    color: var(--yb-text-muted);
}

/* The trend, drawn ON the school's scale. The green patch is WITHIN BASE — everything above it is the
   deviation, seen rather than asserted (#189). */
.yb-sd-trend { margin-top: 0.9rem; }

.yb-sd-trend__svg {
    display: block;
    width: 100%;
    height: 96px;
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-sm);
    background: var(--yb-surface);

    /* Keep the band blending inside the chart: without this the rects would blend with whatever the
       card happens to sit on. */
    isolation: isolate;
}

/* THE BANDS ARE A WASH, NOT A FILL.
   They are the context a reading is placed in, so they must sit UNDER the line and never compete with
   it. A translucent colour on a dark plate can only get darker — which is why these came out muddy in
   dark mode — so the blend mode does the work instead: multiply on a light plate (pale pastel), SCREEN
   on a dark one (a light tint, lit from within). The colour stays the school's either way; only the
   weight changes. */
.yb-sd-trend__band {
    --band-wash: 0.07;

    opacity: var(--band-wash);
    mix-blend-mode: multiply;
}

/* Within base is the one band with a job to do — it is what the reading is judged against — so it is
   allowed to be seen. Still a wash. */
.yb-sd-trend__band.is-base { --band-wash: 0.13; }

[data-theme="dark"] .yb-sd-trend__band {
    --band-wash: 0.10;

    mix-blend-mode: screen;
}

[data-theme="dark"] .yb-sd-trend__band.is-base { --band-wash: 0.17; }

.yb-sd-trend__key {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-top: 0.35rem;
    font-size: 0.72rem;
    color: var(--yb-text-muted);
}

.yb-sd-trend__swatch {
    width: 10px;
    height: 10px;
    border-radius: 2px;
    opacity: 0.55;
}

.yb-sd-trend__cap { margin-left: auto; font-style: italic; }

/* The deviation, said in one sentence: this far from YOUR OWN normal, in your school's word for it. */
.yb-sd-dev-say {
    margin: 0.8rem 0 0;
    font-size: 0.85rem;
    line-height: 1.55;
    color: var(--yb-text);
}

.yb-sd-dev-say__band { color: var(--yb-warning); }

/* The ORGANIZATION's scale. Labels, colours and bounds all come from the API, which took them from the
   school's own configuration — Trilok supplies no word of its own here (#189). The band the reading
   fell into is marked; the rest are context, so the reading can be PLACED rather than judged. */
.yb-sd-scale {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    margin-top: 0.75rem;
}

.yb-sd-scale__band {
    flex: 1 1 auto;
    min-width: 72px;
    padding: 0.4rem 0.5rem;
    border: 1px solid var(--yb-border);
    border-top: 3px solid var(--yb-sd-band, var(--yb-border-strong));
    border-radius: var(--yb-radius-sm);
    background: var(--yb-surface-2);
    opacity: 0.6;
}

/* Where this reading actually fell. */
.yb-sd-scale__band.is-here {
    opacity: 1;
    border-color: var(--yb-sd-band, var(--yb-warning));
    background: var(--yb-surface);
    box-shadow: 0 1px 6px rgba(16, 31, 64, 0.08);
}

/* Its own line-height, now that the band's numeric bounds are gone (#205): on the inherited one a
   single short label sat in a 36px line box and the ramp kept the height of the two-line cell it used
   to be. Still wraps — an organization may well call D3 "Considerably above usual". */
.yb-sd-scale__label {
    display: block;
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--yb-text);
}

/* ── The opened call (TrilokAPI #168) ─────────────────────────────────────── */

/* Who it was about. The one fact a teacher actually wants after an alert. */
.yb-sd-subject {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    margin-top: 0.9rem;
    padding: 0.75rem 0.85rem;
    border-radius: var(--yb-radius-sm);
    border-left: 3px solid var(--yb-required);
    background: var(--yb-surface-2);
}

.yb-sd-subject.is-unknown { border-left-style: dashed; border-left-color: var(--yb-border-strong); }

.yb-sd-subject__label {
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--yb-text-muted);
}

.yb-sd-subject__who {
    font-family: "Fraunces", Georgia, serif;
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--yb-text);
}

.yb-sd-subject__where { font-size: 0.78rem; color: var(--yb-text-muted); }

/* The escalation as they lived it: told at level 1, answered at level 2 — a sequence, not a status. */
.yb-sd-trail { margin-top: 0.9rem; }

.yb-sd-trail__title,
.yb-sd-mystress__title {
    display: block;
    margin-bottom: 0.35rem;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--yb-text-muted);
}

.yb-sd-trail__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 0.25rem;
}

.yb-sd-trail__step {
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    padding: 0.3rem 0.5rem;
    border-left: 2px solid var(--yb-border);
    font-size: 0.8rem;
    color: var(--yb-text-muted);
}

.yb-sd-trail__step.is-attended {
    border-left-color: var(--yb-success);
    color: var(--yb-text);
}

.yb-sd-trail__at {
    font-family: var(--yb-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.75rem;
}

.yb-sd-mystress { margin-top: 0.9rem; }

.yb-sd-devs { margin-top: 0.9rem; }

.yb-sd-devs__title {
    display: block;
    margin-bottom: 0.35rem;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--yb-text-muted);
}

.yb-sd-devs__list { display: flex; flex-wrap: wrap; gap: 0.35rem; }

.yb-sd-dev {
    padding: 0.2rem 0.5rem;
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-sm);
    font-size: 0.75rem;
    color: var(--yb-text-muted);
}

.yb-sd-dev b {
    font-family: var(--yb-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    color: var(--yb-text);
}

.yb-sd-cohort {
    font-family: "Fraunces", Georgia, serif;
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--yb-text);
}

/* The section on a weak read is a best guess, and the copy says so out loud. */
.yb-sd-cohort__hedge {
    font-family: var(--yb-font-sans, inherit);
    font-size: 0.82rem;
    font-weight: 400;
    font-style: italic;
    color: var(--yb-text-muted);
}

.yb-sd-card.is-low .yb-sd-cohort { color: var(--yb-text-muted); }

.yb-sd-when {
    font-family: var(--yb-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.8rem;
    color: var(--yb-text-muted);
}

.yb-sd-room { font-size: 0.78rem; color: var(--yb-text-muted); }

.yb-sd-conf {
    margin-left: auto;
    font-size: 0.7rem;
    font-weight: 700;
    padding: 0.14rem 0.45rem;
    border-radius: var(--yb-radius-sm);
    white-space: nowrap;
}

.yb-sd-conf.is-high {
    color: var(--yb-brand-600);
    background: rgba(var(--yb-info-rgb), 0.1);
    border: 1px solid rgba(var(--yb-info-rgb), 0.3);
}

.yb-sd-conf.is-low {
    color: var(--yb-text-muted);
    background: var(--yb-surface-2);
    border: 1px solid var(--yb-border);
}

[data-theme="dark"] .yb-sd-conf.is-high { color: var(--yb-brand-400); }

.yb-sd-why { margin: 0.5rem 0 0; font-size: 0.8rem; line-height: 1.5; color: var(--yb-text-muted); }

/* Attendance: the roster as people, not a percentage. */
.yb-sd-att {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin-top: 0.85rem;
}

.yb-sd-dots { display: flex; gap: 2px; flex-wrap: wrap; max-width: 340px; }

.yb-sd-dots i {
    width: 9px;
    height: 9px;
    border-radius: 2px;
}

.yb-sd-dots i.is-here { background: var(--yb-info); opacity: 0.75; }

/* Away: has a wearable, wasn't sensed. A hollow seat — the strongest thing we are entitled to say,
   and still not the word "absent" (a wearable left in a bag reads exactly like a child at home). */
.yb-sd-dots i.is-out {
    background: transparent;
    border: 1px solid var(--yb-border-strong);
}

/* No wearable: we could never have sensed them (#183 / TrilokAPI#159). Drawn as a BLIND SPOT, not an
   empty seat — a faint dotted mark that reads as "no signal here", so it can't be miscounted as
   absence at a glance. Deliberately quieter than .is-out: it is a fact about our instruments. */
.yb-sd-dots i.is-unsensable {
    background: transparent;
    border: 1px dotted var(--yb-border-strong);
    opacity: 0.5;
}

/* Who was away, and who we simply cannot see. Two statements, never one number.
   Left-aligned so each label anchors under the attendance dots it explains — centred, the chip
   floats into the middle of the sentence and stops reading as a label at all. */
.yb-sd-who-out,
.yb-sd-who-blind {
    margin: 0.45rem 0 0;
    font-size: 0.8rem;
    line-height: 1.5;
    text-align: left;
    color: var(--yb-text);
}

.yb-sd-who-blind { color: var(--yb-text-muted); }

.yb-sd-who-out__label,
.yb-sd-who-blind__label {
    display: inline-block;
    margin-right: 0.35rem;
    padding: 0.05rem 0.35rem;
    border-radius: var(--yb-radius-sm);
    font-family: var(--yb-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.68rem;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    background: var(--yb-surface-2);
    color: var(--yb-text-muted);
}

.yb-sd-who-out__label {
    background: rgba(var(--yb-danger-rgb), 0.10);
    color: var(--yb-required);
}

.yb-sd-who-out__hint,
.yb-sd-who-blind__hint {
    color: var(--yb-text-muted);
}

.yb-sd-att__num {
    font-family: var(--yb-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.82rem;
    color: var(--yb-text);
}

.yb-sd-att__num span { color: var(--yb-text-muted); }

/* ── THE ASK — the one write on the screen ────────────────────────────────── */
.yb-sd-ask {
    margin-top: 0.95rem;
    padding: 0.75rem 0.9rem;
    border-radius: var(--yb-radius-sm);
    border: 1px dashed var(--yb-border-strong);
    background: var(--yb-surface-2);
}

/* Settled — the only state that is a fact. */
.yb-sd-ask.is-settled {
    border: 1px solid rgba(var(--yb-success-rgb), 0.35);
    background: rgba(var(--yb-success-rgb), 0.07);
}

/* Covering someone's class: the assumption is at its weakest, so ask properly. */
.yb-sd-ask.is-pressing {
    border: 1px dashed rgba(var(--yb-warning-rgb), 0.6);
    background: rgba(var(--yb-warning-rgb), 0.08);
}

.yb-sd-ask__head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.yb-sd-ask__label {
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--yb-text-muted);
}

.yb-sd-ask__subject {
    font-family: "Fraunces", Georgia, serif;
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--yb-text);
}

/* A guess LOOKS like a guess. This is the single most important rule in the file. */
.yb-sd-ask__subject.is-guess {
    font-style: italic;
    font-weight: 500;
    color: var(--yb-text-muted);
}

.yb-sd-ask__ok {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--yb-success);
}

.yb-sd-ask__acts { margin-left: auto; display: flex; gap: 0.4rem; flex-wrap: wrap; }

.yb-sd-ask__saving {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.78rem;
    color: var(--yb-text-muted);
}

.yb-sd-ask__why { margin: 0.35rem 0 0; font-size: 0.79rem; line-height: 1.5; color: var(--yb-text-muted); }
.yb-sd-ask__why strong { color: var(--yb-text); }

.yb-sd-ask__exam {
    margin: 0.45rem 0 0;
    font-size: 0.78rem;
    color: var(--yb-text-muted);
}

.yb-sd-ask__exam i { color: var(--yb-info); }
.yb-sd-ask__exam strong { color: var(--yb-text); }

.yb-sd-ask__error {
    margin: 0.5rem 0 0;
    font-size: 0.79rem;
    font-weight: 600;
    color: var(--yb-danger);
}

/* The picker: their OWN subjects, primary starred. */
.yb-sd-picker {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
    margin-top: 0.7rem;
    padding-top: 0.65rem;
    border-top: 1px dashed var(--yb-border-strong);
}

.yb-sd-picker__label { font-size: 0.7rem; font-weight: 600; color: var(--yb-text-muted); }
.yb-sd-picker__none { font-size: 0.78rem; color: var(--yb-text-muted); }

.yb-sd-chip {
    font: inherit;
    font-size: 0.78rem;
    font-weight: 600;
    padding: 0.26rem 0.6rem;
    cursor: pointer;
    color: var(--yb-text);
    background: var(--yb-surface);
    border: 1px solid var(--yb-border-strong);
    border-radius: var(--yb-radius-sm);
}

.yb-sd-chip:hover:not(:disabled) { color: var(--yb-brand-600); border-color: var(--yb-brand-600); }
.yb-sd-chip:disabled { opacity: 0.5; cursor: default; }
.yb-sd-chip.is-primary i { color: var(--yb-warning); margin-right: 0.25rem; }

/* ── Stops: the honest half ───────────────────────────────────────────────── */
.yb-sd-stop {
    max-width: 46ch;
    margin: 3rem auto;
    padding: 2rem 1.5rem;
    text-align: center;
    border: 1px dashed var(--yb-border-strong);
    border-radius: var(--yb-radius-sm);
    background: var(--yb-surface);
}

.yb-sd-stop.is-error { border-color: rgba(var(--yb-danger-rgb), 0.35); }

.yb-sd-stop > i { font-size: 1.8rem; color: var(--yb-text-muted); opacity: 0.7; }
.yb-sd-stop.is-error > i { color: var(--yb-danger); opacity: 1; }

.yb-sd-stop__title {
    margin: 0.7rem 0 0.4rem;
    font-family: "Fraunces", Georgia, serif;
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--yb-text);
}

.yb-sd-stop__body {
    margin: 0 0 0.5rem;
    font-size: 0.87rem;
    line-height: 1.6;
    color: var(--yb-text-muted);
}

.yb-sd-idle {
    padding: 2rem 1rem;
    text-align: center;
    border: 1px dashed var(--yb-border-strong);
    border-radius: var(--yb-radius-sm);
    background: var(--yb-surface-2);
}

.yb-sd-idle > i { font-size: 1.5rem; color: var(--yb-text-muted); opacity: 0.7; }
.yb-sd-idle__title { margin: 0.6rem 0 0.25rem; font-weight: 700; color: var(--yb-text); }
.yb-sd-idle__sub { margin: 0; font-size: 0.85rem; color: var(--yb-text-muted); }

/* .yb-sd-loading removed — StaffDay and StaffAlertDetail use YbStateBlock (#233). */

.yb-sd-note {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    margin-top: 0.85rem;
    padding: 0.7rem 0.85rem;
    font-size: 0.82rem;
    line-height: 1.5;
    color: var(--yb-text-muted);
    border: 1px solid rgba(var(--yb-info-rgb), 0.26);
    border-radius: var(--yb-radius-sm);
    background: rgba(var(--yb-info-rgb), 0.07);
}

.yb-sd-note i { flex: none; margin-top: 0.1rem; color: var(--yb-info); }

/* ============================================================================
   MOTION (#193)

   The screen has one thesis — THE DAY ARRIVES AS A GUESS AND THE TEACHER INKS IT IN — so the motion
   has one job: to make that sentence something you can watch happen. Everything else stays still.

   Four beats, and no more:

     1. THE DAY ASSEMBLES.  The spine reconstructs itself top-down on load, because that is literally
                            what it is: a day rebuilt from presence, one moment at a time.
     2. THE INK.            The subject stops being a guess. THE signature moment of the product, and
                            the only place any real boldness is spent.
     3. THE READING TRACES. The SI line draws itself across the scale, so the crossing out of the
                            green patch is seen as it happens rather than found already done.
     4. FREE TIME BREATHES. The green blocks lift, softly, under the cursor. They are the part of the
                            day that belongs to the teacher; they are allowed to feel alive.

   Everything here is off under prefers-reduced-motion — including the assemble, which is the one that
   would hurt most: a person who asked for stillness should not be made to watch their day rebuild
   itself every time they step a date.
   ============================================================================ */

/* 1. THE DAY ASSEMBLES ─────────────────────────────────────────────────────
   A short stagger, capped: a sixteen-block day must not take a second and a half to appear. */
@keyframes yb-sd-rise {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}

.yb-sd-moments > li {
    animation: yb-sd-rise 0.34s cubic-bezier(0.22, 1, 0.36, 1) both;
    animation-delay: calc(min(var(--i, 0) * 28ms, 420ms));
}

/* The pane answers the spine: a new moment rises into place rather than being swapped out. */
.yb-sd-detail,
.yb-sd-pane__empty {
    animation: yb-sd-rise 0.28s cubic-bezier(0.22, 1, 0.36, 1) both;
}

/* 2. THE INK ───────────────────────────────────────────────────────────────
   A guess is dotted and italic. When the teacher settles it, the dots dissolve, the italic stands up,
   and the row is briefly lit from within — the closest a screen gets to ink drying on paper. This is
   the one interaction the whole page exists for, so it is the one that gets to be noticed. */
@keyframes yb-sd-ink {
    0%   { opacity: 0.35; transform: translateX(-3px) scale(0.98); }
    55%  { opacity: 1; transform: none; }
    100% { opacity: 1; transform: none; }
}

@keyframes yb-sd-ink-glow {
    0%   { background: rgba(var(--yb-success-rgb), 0.22); }
    100% { background: transparent; }
}

.yb-sd-moment__subj.is-confirmed {
    animation:
        yb-sd-ink 0.42s cubic-bezier(0.22, 1, 0.36, 1) both,
        yb-sd-ink-glow 1.1s ease-out 0.1s both;
    border-radius: var(--yb-radius-sm);
}

.yb-sd-moment__subj.is-confirmed i {
    display: inline-block;
    animation: yb-sd-ink 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) 0.12s both;
}

/* 3. THE READING TRACES ────────────────────────────────────────────────────
   A left-to-right WIPE, not a dashed path draw. Every sample's x rises with its index, so uncovering
   the chart left to right IS the line drawing itself — and unlike stroke-dashoffset it doesn't care
   how long the path is.

   THE TRAP that forced this: the line carries `vector-effect="non-scaling-stroke"`, and it has to —
   the svg is stretched by `preserveAspectRatio="none"`, so a scaled stroke comes out fat on the steep
   segments and thin on the flat ones. But non-scaling-stroke strokes in DEVICE space, which defeats
   `pathLength` normalisation: the dash was measured in user units (~342 across a 300-wide viewBox)
   and then laid along the RENDERED path (~710px at a wide viewport). The line stopped dead at 48%
   and the pattern's next dash reappeared as a stub at the right edge — and it settled that way, with
   the animation already finished. The wider the window, the less of the reading a teacher saw. */
@keyframes yb-sd-draw {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
}

.yb-sd-trend__wipe {
    transform-box: fill-box;
    transform-origin: left center;
    animation: yb-sd-draw 0.9s cubic-bezier(0.65, 0, 0.35, 1) 0.15s both;
}

/* The scale settles first, then the line is drawn across it — the band is the context, so it arrives
   before the thing it gives meaning to.

   THE TRAP: these fade UP TO THEIR OWN WASH, not to 1. An animation with `both` holds its final
   keyframe, and that final value BEATS the element's own opacity declaration — so a generic
   fade-to-1 quietly repainted every band at full strength, and the pale washes came out as slabs of
   solid colour. The end state is read from the same custom property the band is styled with, so the
   animation cannot disagree with the design. */
@keyframes yb-sd-band-in {
    from { opacity: 0; }
    to   { opacity: var(--band-wash); }
}

@keyframes yb-sd-base-in {
    from { opacity: 0; }
    to   { opacity: 0.7; }
}

.yb-sd-trend__band { animation: yb-sd-band-in 0.4s ease-out both; }
.yb-sd-trend__base { animation: yb-sd-base-in 0.4s ease-out both; }

/* 4. TRANSITIONS ───────────────────────────────────────────────────────────
   Hover and selection are transitions, not animations: they answer the cursor, they don't perform. */
.yb-sd-moment {
    transition:
        background 0.16s ease,
        box-shadow 0.16s ease,
        transform 0.16s cubic-bezier(0.22, 1, 0.36, 1);
}

.yb-sd-moment:not(.is-gap):hover { transform: translateX(2px); }

/* Free time lifts under the cursor. The one soft thing on the screen, and the only place a shadow is
   spent — these are the blocks the teacher got back. */
.yb-sd-moment.is-gap:hover {
    background: rgba(var(--yb-success-rgb), 0.11);
    transform: translateY(-1px);
    box-shadow: 0 2px 10px rgba(var(--yb-success-rgb), 0.16);
}

.yb-sd-chip { transition: border-color 0.16s ease, background 0.16s ease; }

.yb-sd-scale__band { transition: opacity 0.2s ease, box-shadow 0.2s ease; }

.yb-sd-btn { transition: background 0.16s ease, border-color 0.16s ease, transform 0.12s ease; }
.yb-sd-btn:active:not(:disabled) { transform: scale(0.97); }

/* ── Stillness, when it is asked for ──────────────────────────────────────
   Not "shorter animations" — none. A person who has asked their machine to stop moving things has
   asked for a reason, and a day that rebuilds itself on every date step is precisely the thing they
   were asking it to stop doing. */
@media (prefers-reduced-motion: reduce) {
    .yb-sd-moments > li,
    .yb-sd-detail,
    .yb-sd-pane__empty,
    .yb-sd-moment__subj.is-confirmed,
    .yb-sd-moment__subj.is-confirmed i,
    .yb-sd-trend__wipe,
    .yb-sd-trend__band,
    .yb-sd-trend__base {
        animation: none;
    }

    .yb-sd-moment,
    .yb-sd-chip,
    .yb-sd-scale__band,
    .yb-sd-btn {
        transition: none;
    }

    .yb-sd-moment:hover,
    .yb-sd-moment.is-gap:hover,
    .yb-sd-btn:active:not(:disabled) {
        transform: none;
    }
}
