/* Night Shift composition: tokens, scale and static layout. Motion lives in the feature stylesheets. */

/* ---------- Tokens (Auto theme kept: light "paper", dark "graphite") ---------- */
:root{--hub-bg:#f2f0ea;--hub-panel:#fbfaf6;--hub-ink:#151c1f;--hub-muted:#58625f;--hub-line:#dad7cd;--hub-soft:#e8e6de;--hub-focus:#0f6d62;
 --ns-stage:#151e22;--ns-stage-2:#11191c;--ns-glass:rgb(251 250 246 / .72);--ns-glass-line:rgb(21 28 31 / .09);--ns-shadow:0 1px 0 rgb(255 255 255 / .7) inset,0 30px 60px -40px rgb(21 28 31 / .35);
 --ns-hot:#d24a2a;--ns-mono:ui-monospace,"SFMono-Regular",Menlo,Consolas,monospace;--ns-ease:cubic-bezier(.22,1,.36,1);--ns-ease-in-out:cubic-bezier(.76,0,.24,1)}
:root[data-theme=dark]{--hub-bg:#0f1619;--hub-panel:#151f23;--hub-ink:#eef0ea;--hub-muted:#a1b0ae;--hub-line:#24333a;--hub-soft:#1b282d;--hub-focus:#c6e6d6;
 --ns-glass:rgb(21 31 35 / .66);--ns-glass-line:rgb(238 240 234 / .08);--ns-shadow:0 1px 0 rgb(255 255 255 / .05) inset,0 30px 70px -40px rgb(0 0 0 / .8);--ns-hot:#ff7a59}
@media(prefers-color-scheme:dark){:root:not([data-theme=light]){--hub-bg:#0f1619;--hub-panel:#151f23;--hub-ink:#eef0ea;--hub-muted:#a1b0ae;--hub-line:#24333a;--hub-soft:#1b282d;--hub-focus:#c6e6d6;
 --ns-glass:rgb(21 31 35 / .66);--ns-glass-line:rgb(238 240 234 / .08);--ns-shadow:0 1px 0 rgb(255 255 255 / .05) inset,0 30px 70px -40px rgb(0 0 0 / .8);--ns-hot:#ff7a59}}
/* Desk and stage (semester-book spec §6.2): the desk the course book lies on, and the type that sits on it.
   Light is a daylit desk, dark a lamp-lit one; posters are transparent over this same CSS desk. */
:root{--ns-desk:#e6dfd1;--ns-desk-2:#d5cbb8;--ns-desk-light:rgb(255 252 243 / .9);--ns-desk-vignette:rgb(70 52 24 / .14);
 --ns-stage-ink:#151c1f;--ns-stage-muted:#434c49;--ns-stage-soon:#8a4f12;--ns-stage-hot:#9a3a20;--ns-grain:.015;--ns-dock-h:64px}
:root[data-theme=dark]{--ns-desk:#162024;--ns-desk-2:#0b1113;--ns-desk-light:rgb(255 196 138 / .16);--ns-desk-vignette:rgb(0 0 0 / .55);
 --ns-stage-ink:#eef0ea;--ns-stage-muted:#a1b0ae;--ns-stage-soon:#ffc9a3;--ns-stage-hot:#ff9a7c;--ns-grain:.025}
@media(prefers-color-scheme:dark){:root:not([data-theme=light]){--ns-desk:#162024;--ns-desk-2:#0b1113;--ns-desk-light:rgb(255 196 138 / .16);--ns-desk-vignette:rgb(0 0 0 / .55);
 --ns-stage-ink:#eef0ea;--ns-stage-muted:#a1b0ae;--ns-stage-soon:#ffc9a3;--ns-stage-hot:#ff9a7c;--ns-grain:.025}}
/* CEN's legacy tokens follow the shared ones. */
body.editorial[data-course]{--bg:var(--hub-bg);--tile:var(--hub-panel);--ink:var(--hub-ink);--ink2:var(--hub-muted);--line:var(--hub-line)}
body.workspace{--ns-accent:var(--accent);--ns-tint:color-mix(in srgb,var(--accent) 9%,var(--hub-panel));
 background:radial-gradient(1100px 520px at 88% 0,color-mix(in srgb,var(--accent) 10%,transparent),transparent 70%) no-repeat,var(--hub-bg);
 -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
:root[data-theme=dark] body.workspace[data-course]{--strong:var(--accent)}
@media(prefers-color-scheme:dark){:root:not([data-theme=light]) body.workspace[data-course]{--strong:var(--accent)}}
/* The course accent as small type on the daylit desk: --strong deepened toward the stage ink, so the 9-11 px eyebrow
   and HUD labels keep 4.5:1 over the desk's darker corners and vignette. It is set where --strong is (body), and the
   lamp-lit desk keeps --strong itself. */
body.workspace{--ns-stage-strong:color-mix(in srgb,var(--strong) 75%,var(--ns-stage-ink))}
:root[data-theme=dark] body.workspace{--ns-stage-strong:var(--strong)}
@media(prefers-color-scheme:dark){:root:not([data-theme=light]) body.workspace{--ns-stage-strong:var(--strong)}}

/* ---------- Frame ---------- */
.course-workspace{max-width:1840px}
@media(min-width:1001px){
 .course-workspace{grid-template-columns:248px minmax(0,1fr)}
 body.workspace .wrap,body.workspace .math-wrap{--page-gutter:clamp(28px,3.6vw,64px);max-width:1480px;padding:0 var(--page-gutter) 64px}
}
body.workspace .hub-shell{background:color-mix(in srgb,var(--hub-panel) 82%,transparent);backdrop-filter:blur(14px)}
.workspace .course-link[aria-current]{background:color-mix(in srgb,var(--accent) 12%,var(--hub-panel))}
.workspace .course-link[aria-current]:after{background:var(--accent);box-shadow:0 0 14px var(--accent)}
.workspace .course-link[aria-current] .course-code{color:var(--strong)}
.workspace-nav a{font-size:.9rem}
/* Descriptive text keeps a comfortable reading measure inside the wide layout. */
body.workspace .workspace-panel p:not(.ns-kicker){max-width:68ch}

/* ---------- Hero ---------- */
body.workspace .header-upgraded{background:linear-gradient(180deg,var(--ns-stage) 0%,var(--ns-stage) 70%,var(--ns-stage-2) 100%)}
@media(min-width:1001px){
 body.workspace .header-upgraded{grid-template-rows:clamp(520px,72vh,760px) 76px}
 body.workspace .header-upgraded h1{font-size:clamp(3.6rem,6.4vw,8.4rem);font-variation-settings:'wdth' 78;font-weight:560;letter-spacing:-.05em;line-height:.9;max-width:10ch}
 body.workspace .header-upgraded .hero-copy{max-width:50%;padding-bottom:96px}
 .header-art{inset:24px 24px 150px 40%}
 .scene-meta{bottom:100px}
}
@media(min-width:1001px) and (max-height:700px){body.workspace .header-upgraded{grid-template-rows:480px 72px}.header-art{inset:16px 18px 128px 42%}}
body.workspace .header-upgraded .team,body.workspace .header-upgraded .eyebrow{letter-spacing:.22em}
/* Arrival flourish lives in the hero: the title rises behind a line mask from the first painted frame,
   so it never hides content that was already visible. */
@media(prefers-reduced-motion:no-preference){
 html.night body.workspace .header-upgraded h1{animation:ns-title-rise .9s var(--ns-ease) backwards}
 html.night body.workspace .header-upgraded .hero-copy>:not(h1){animation:ns-fade-up .7s var(--ns-ease) .18s backwards}
}
/* The arrival plays once. The pin later re-parents the header into its spacer, which would restart these
   animations and hide a title the reader is already looking at; course-header marks the header arrived. */
html.night body.workspace .header-upgraded.ns-arrived :is(h1,.hero-copy>*){animation:none}
@keyframes ns-title-rise{from{clip-path:inset(0 0 100% 0);transform:translateY(.35em)}to{clip-path:inset(0 0 -20% 0);transform:none}}
@keyframes ns-fade-up{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.ns-hud{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin:28px 0 0;font:500 11px/1.4 var(--ns-mono);letter-spacing:.1em;text-transform:uppercase;color:#c9d2cf}
.ns-hud .ns-hud-k{color:var(--scene-accent);padding:4px 8px;border:1px solid color-mix(in srgb,var(--scene-accent) 45%,transparent);border-radius:999px}
.ns-hud [data-ns-title]{color:#f4f2e9;text-transform:none;letter-spacing:.02em;font:600 14px/1.3 Archivo,system-ui,sans-serif}
.ns-hud [data-ns-chip]{color:var(--scene-accent);text-transform:none;letter-spacing:.04em}
.ns-hud-sep{opacity:.4}

/* Action bar under the stage */
body.workspace .header-upgraded .workspace-actions{background:var(--hub-bg);border-bottom:1px solid var(--hub-line);gap:10px}
.header-upgraded .workspace-actions button{border-radius:999px;min-height:44px;padding:10px 18px;font-size:.8rem;font-weight:600}
.header-upgraded .workspace-actions .workspace-section{padding-left:16px;border:1px solid var(--hub-line);background:var(--hub-panel);color:var(--hub-ink);display:inline-flex;align-items:center;gap:10px}
.header-upgraded .workspace-section:before{content:'';width:7px;height:7px;border-radius:50%;background:var(--accent);box-shadow:0 0 0 0 var(--accent)}
.header-upgraded .workspace-section[aria-label^="Choose"]:before{background:var(--ns-hot);box-shadow:0 0 0 4px color-mix(in srgb,var(--ns-hot) 22%,transparent)}
.header-upgraded .workspace-search{border:1px solid var(--hub-line);color:var(--hub-ink)}

/* ---------- Editorial page titles ---------- */
body.workspace .workspace-panel{padding-top:clamp(40px,5vw,72px)}
body.workspace .workspace-page-title{font-size:clamp(2.6rem,4.5vw,5.5rem);font-variation-settings:'wdth' 75;font-weight:600;letter-spacing:-.045em;line-height:.92;margin:0 0 clamp(24px,3vw,40px);padding-bottom:clamp(18px,2vw,28px);border-bottom:1px solid var(--hub-line)}
body.workspace .workspace-page-title[data-ns-index]:before{content:attr(data-ns-index);display:block;margin-bottom:18px;font:500 11px/1 var(--ns-mono);letter-spacing:.2em;color:var(--strong);font-variation-settings:normal}
.ns-kicker{margin:0;font:500 11px/1.4 var(--ns-mono);letter-spacing:.18em;text-transform:uppercase;color:var(--hub-muted)}

/* ---------- Next deadline: the dominant card ---------- */
body.workspace .next-layout,body.workspace .cen-next-layout{margin:0 0 clamp(20px,2.4vw,32px)}
body.workspace .next-assessment.ns-next,body.workspace .cen-next-layout .next.ns-next{
 position:relative;isolation:isolate;overflow:hidden;color:var(--hub-ink);background:var(--ns-tint);
 border:1px solid color-mix(in srgb,var(--accent) 34%,var(--hub-line));border-radius:22px;padding:clamp(22px,3vw,44px);box-shadow:var(--ns-shadow)}
body.workspace .ns-next:before{content:'';position:absolute;inset:-40% -10% auto 45%;height:140%;z-index:-1;background:radial-gradient(closest-side,color-mix(in srgb,var(--accent) 28%,transparent),transparent);opacity:.7;pointer-events:none}
@media(min-width:861px){
 body.workspace .next-assessment.ns-next{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(300px,.85fr);column-gap:clamp(24px,4vw,64px);align-items:start}
 body.workspace .next-assessment.ns-next>*{grid-column:1}
 body.workspace .next-assessment.ns-next>.ns-count{grid-column:2;grid-row:1 / span 5;align-self:stretch}
 body.workspace .cen-next-layout .next.ns-next{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(300px,.85fr);column-gap:clamp(24px,4vw,64px);align-items:start}
 body.workspace .cen-next-layout .next.ns-next>.next-open{grid-column:1}
 body.workspace .cen-next-layout .next.ns-next>.next-quick-actions{grid-column:1}
 body.workspace .cen-next-layout .next.ns-next>.ns-count{grid-column:2;grid-row:1 / span 2;align-self:stretch}
}
/* Text inside the card */
body.workspace .ns-next .eyebrow,body.workspace .cen-next-layout .next.ns-next .lbl{display:inline-flex;align-items:center;gap:8px;color:var(--strong);font:500 11px/1.4 var(--ns-mono);letter-spacing:.16em;text-transform:uppercase}
body.workspace .ns-next .lbl svg{color:var(--strong)}
body.workspace .next-assessment.ns-next h2,body.workspace .cen-next-layout .next.ns-next .t{font-size:clamp(1.9rem,3.2vw,3.4rem);font-variation-settings:'wdth' 82;font-weight:600;letter-spacing:-.04em;line-height:1;margin:14px 0 12px;color:var(--hub-ink);text-wrap:balance}
body.workspace .next-assessment.ns-next .when{font-size:1rem;font-weight:500;color:var(--hub-muted);margin:0 0 22px}
body.workspace .next-assessment.ns-next .next-bottom{display:block}
body.workspace .ns-next .countdown,body.workspace .cen-next-layout .next.ns-next .row{position:absolute!important;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
body.workspace .next-assessment.ns-next .next-buttons{display:flex;flex-wrap:wrap;gap:10px}
body.workspace .ns-next .next-buttons button,body.workspace .ns-next .quick-mark{min-height:48px;padding:12px 20px;border-radius:999px;font:650 .86rem Archivo,system-ui,sans-serif;cursor:pointer}
body.workspace .ns-next .next-buttons button:first-child{background:var(--hub-ink);color:var(--hub-bg);border:1px solid var(--hub-ink)}
body.workspace .ns-next .quick-mark{background:transparent;color:var(--hub-ink);border:1px solid color-mix(in srgb,var(--hub-ink) 30%,transparent)}
body.workspace .cen-next-layout .next.ns-next .next-open{color:inherit;text-decoration:none;display:block}
body.workspace .cen-next-layout .next.ns-next .chips{display:flex;flex-wrap:wrap;align-items:center;gap:12px;margin-top:6px}
body.workspace .cen-next-layout .next.ns-next .chip{background:color-mix(in srgb,var(--hub-ink) 8%,transparent);color:var(--hub-ink)}
body.workspace .cen-next-layout .next.ns-next .deadline-action{display:inline-flex;align-items:center;gap:8px;min-height:48px;padding:12px 20px;border-radius:999px;background:var(--hub-ink);color:var(--hub-bg);font:650 .86rem Archivo,system-ui,sans-serif}
body.workspace .cen-next-layout .next.ns-next .next-quick-actions{display:flex;align-items:center;gap:14px;margin-top:22px;padding-top:0;border-top:0}
body.workspace .cen-next-layout .next.ns-next .next-quick-actions small{color:var(--hub-muted);font-size:.78rem}

/* Countdown block (glass surface) */
.ns-count{display:flex;flex-direction:column;justify-content:space-between;gap:20px;min-width:0;padding:clamp(18px,2vw,28px);border-radius:16px;background:var(--ns-glass);border:1px solid var(--ns-glass-line);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
.ns-count-face{display:flex;align-items:center;gap:clamp(14px,1.6vw,22px);min-width:0}
.ns-ring{flex:none;width:clamp(56px,5vw,76px);height:auto;transform:rotate(-90deg);overflow:visible}
.ns-ring circle{fill:none;stroke-width:6}
.ns-ring-track{stroke:color-mix(in srgb,var(--hub-ink) 10%,transparent)}
.ns-ring-fill{stroke:var(--strong);stroke-linecap:round}
.ns-ring-mechanism .ns-ring-track{stroke-width:9;stroke:color-mix(in srgb,var(--hub-ink) 16%,transparent)}
.ns-ring-mechanism .ns-ring-fill{stroke-linecap:butt;transition:stroke-dashoffset .18s steps(1)}
.ns-ring-tangent{stroke:var(--hub-ink);stroke-width:2.2;stroke-linecap:round;opacity:.8}
.ns-ring-plane .ns-ring-fill{stroke-linecap:butt}
.ns-ring-basis{transform-box:view-box;transform-origin:50% 50%;transform:rotate(var(--turn,0deg))}
.ns-ring-basis path{stroke:var(--hub-ink);stroke-width:2.4;stroke-linecap:round;fill:none;opacity:.75}
.ns-digits{display:flex;flex-wrap:nowrap;align-items:flex-start;gap:clamp(6px,.8vw,12px);min-width:0}
.ns-unit{display:grid;justify-items:start;gap:6px;min-width:0}
.ns-unit b{white-space:nowrap;font-size:clamp(2rem,2.9vw,3.3rem);font-weight:520;font-variation-settings:'wdth' 75;font-variant-numeric:tabular-nums;letter-spacing:-.04em;line-height:.9;color:var(--hub-ink)}
.ns-unit+.ns-unit b:before{content:':';margin-right:clamp(6px,.8vw,12px);color:color-mix(in srgb,var(--hub-ink) 28%,transparent);font-weight:400}
.ns-unit i{font:500 10px/1 var(--ns-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--hub-muted);font-style:normal}
.ns-unit+.ns-unit i{padding-left:calc(clamp(6px,.8vw,12px) + .35em)}
.ns-word{font-size:clamp(2rem,3.4vw,3.4rem);font-weight:560;font-variation-settings:'wdth' 78;letter-spacing:-.04em;line-height:.95}
.ns-word-quiet{color:var(--hub-muted)}
.ns-count-label{margin:0 0 6px;font:500 11px/1.4 var(--ns-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--strong)}
.ns-count-when{margin:0;font-size:1.05rem;font-weight:600;color:var(--hub-ink)}
.ns-next .ns-cta,.ns-cta{margin-top:14px;min-height:44px;padding:10px 16px;border-radius:999px;border:1px solid var(--strong);background:transparent!important;color:var(--hub-ink)!important;border-radius:999px!important;font:600 .82rem Archivo,system-ui,sans-serif;cursor:pointer}
.ns-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
:root[data-ns-urgency=hot] .ns-ring-fill{stroke:var(--ns-hot)}
:root[data-ns-urgency=hot] .ns-count-label{color:var(--ns-hot)}

/* ---------- Timeline ---------- */
.ns-timeline{position:relative;margin:0 0 clamp(28px,3vw,44px);padding:22px clamp(18px,2.4vw,32px) 10px;border:1px solid var(--hub-line);border-radius:18px;background:var(--hub-panel)}
.ns-tl-head{display:flex;justify-content:space-between;align-items:baseline;gap:16px;flex-wrap:wrap}
.ns-tl-stats{display:flex;gap:18px;font:500 11px/1.4 var(--ns-mono);letter-spacing:.1em;text-transform:uppercase;color:var(--hub-muted)}
.ns-tl-stats b{color:var(--hub-ink);font-weight:600}
.ns-tl-scroll{overflow-x:auto;overflow-y:hidden;scrollbar-width:none;scroll-snap-type:x proximity}
.ns-tl-scroll::-webkit-scrollbar{display:none}
.ns-tl-track{position:relative;height:128px;min-width:720px;margin:0 14px}
.ns-tl-rail{position:absolute;left:0;right:0;top:64px;height:2px;border-radius:2px;background:var(--hub-line)}
.ns-tl-fill{position:absolute;inset:0 auto 0 0;width:var(--elapsed);border-radius:2px;background:linear-gradient(90deg,color-mix(in srgb,var(--strong) 20%,transparent),var(--strong))}
.ns-tl-tick{position:absolute;top:70px;width:1px;height:6px;background:var(--hub-line)}
.ns-tl-tick-major{height:10px}
.ns-tl-month{position:absolute;top:92px;transform:translateX(2px);font:500 10px/1 var(--ns-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--hub-muted);white-space:nowrap}
.ns-tl-today{position:absolute;top:26px;bottom:44px;width:0;border-left:1px dashed color-mix(in srgb,var(--strong) 70%,transparent);scroll-snap-align:center}
.ns-tl-today>span{position:absolute;top:-14px;left:0;transform:translateX(-50%);font:600 10px/1 var(--ns-mono);letter-spacing:.14em;text-transform:uppercase;color:var(--strong);white-space:nowrap}
.ns-tl-today>i{position:absolute;top:33px;left:-5px;width:9px;height:9px;border-radius:50%;background:var(--strong);box-shadow:0 0 0 4px color-mix(in srgb,var(--strong) 22%,transparent)}
.ns-tl-node{position:absolute;top:65px;width:44px;height:44px;transform:translate(-50%,-50%);display:grid;place-items:center;padding:0;border:0;background:transparent;cursor:pointer;z-index:1}
.ns-tl-node>i{display:grid;place-items:center;width:14px;height:14px;border-radius:50%;background:var(--hub-panel);border:2px solid var(--hub-ink);font:700 8px/1 var(--ns-mono);font-style:normal;color:var(--hub-ink);transition:transform .25s var(--ns-ease),background .2s}
.ns-tl-node:not(:has(i:empty))>i{width:18px;height:18px}
.ns-tl-node.is-past>i{border-color:var(--hub-muted);opacity:.55}
.ns-tl-node.is-done>i{background:var(--hub-muted);border-color:var(--hub-muted);color:var(--hub-panel);opacity:.7}
.ns-tl-node.is-next>i{background:var(--strong);border-color:var(--strong);color:var(--hub-bg);box-shadow:0 0 0 5px color-mix(in srgb,var(--strong) 22%,transparent)}
.ns-tl-node:hover>i,.ns-tl-node:focus-visible>i{transform:scale(1.35)}
.ns-tl-tip{position:absolute;bottom:calc(100% + 2px);left:50%;transform:translate(-50%,4px);display:grid;gap:3px;width:max-content;max-width:220px;padding:9px 11px;border-radius:10px;background:var(--hub-ink);color:var(--hub-bg);font:500 .76rem/1.3 Archivo,system-ui,sans-serif;text-align:left;opacity:0;pointer-events:none;transition:opacity .15s,transform .2s var(--ns-ease)}
.ns-tl-tip b{font:600 10px/1 var(--ns-mono);letter-spacing:.12em;text-transform:uppercase;opacity:.7}
.ns-tl-node:hover .ns-tl-tip,.ns-tl-node:focus-visible .ns-tl-tip{opacity:1;transform:translate(-50%,0)}
.ns-tl-node:focus-visible{outline:none}.ns-tl-node:focus-visible>i{outline:2px solid var(--hub-focus);outline-offset:4px}
.ns-tl-pop{position:absolute;top:72px;z-index:5;min-width:260px;max-width:min(360px,calc(100% - 16px));padding:12px;border-radius:14px;background:var(--hub-panel);border:1px solid var(--hub-line);box-shadow:0 24px 50px -24px rgb(0 0 0 / .45)}
.ns-tl-pop p{margin:2px 6px 8px;font:500 10px/1.4 var(--ns-mono);letter-spacing:.14em;text-transform:uppercase;color:var(--hub-muted)}
.ns-tl-pop ul{list-style:none;margin:0;padding:0;display:grid;gap:2px}
.ns-tl-pop button{display:grid;grid-template-columns:auto 1fr;column-gap:8px;width:100%;min-height:44px;padding:8px 10px;border:0;border-radius:9px;background:transparent;color:var(--hub-ink);text-align:left;font:600 .86rem/1.3 Archivo,system-ui,sans-serif;cursor:pointer}
.ns-tl-pop button>span:not(.ns-tl-check){grid-column:2}.ns-tl-pop small{grid-column:2;font-weight:450;color:var(--hub-muted);font-size:.74rem}
.ns-tl-pop button:hover,.ns-tl-pop button:focus-visible{background:var(--hub-soft)}
.ns-tl-check{color:var(--strong)}
/* Course vocabulary on the track */
.ns-tl-motif{position:absolute;left:0;right:0;pointer-events:none}
.ns-tl-teeth{top:58px;height:14px;background:repeating-linear-gradient(90deg,color-mix(in srgb,var(--hub-ink) 13%,transparent) 0 3px,transparent 3px 11px);-webkit-mask:linear-gradient(180deg,#000 0 4px,transparent 4px 10px,#000 10px);mask:linear-gradient(180deg,#000 0 4px,transparent 4px 10px,#000 10px)}
.ns-tl-teeth:after{content:'';position:absolute;inset:0 auto 0 0;width:var(--elapsed);background:repeating-linear-gradient(90deg,color-mix(in srgb,var(--strong) 55%,transparent) 0 3px,transparent 3px 11px)}
.ns-tl-motif.ns-tl-grid{top:20px;height:88px;background-image:linear-gradient(color-mix(in srgb,var(--hub-ink) 7%,transparent) 1px,transparent 1px),linear-gradient(90deg,color-mix(in srgb,var(--hub-ink) 7%,transparent) 1px,transparent 1px);background-size:22px 22px;background-position:0 -1px;-webkit-mask:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);mask:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);transform:skewX(-14deg)}
svg.ns-tl-motif{top:31px;width:100%;height:68px;overflow:visible}
.ns-tl-flow{fill:none;stroke:color-mix(in srgb,var(--hub-ink) 14%,transparent);stroke-width:1.5;vector-effect:non-scaling-stroke}
.ns-tl-flow-done{stroke:var(--strong);stroke-width:2;opacity:.65}

/* ---------- Assessment rows ---------- */
body.workspace .workspace-filters{margin-bottom:16px}
body.workspace #assessment-list,body.workspace #teamlist,body.workspace #youlist{border:1px solid var(--hub-line);border-radius:18px;background:var(--hub-panel);overflow:hidden}
body.workspace .assessment-list>li+li{border-top:1px solid var(--hub-line)}
body.workspace .assessment-list>li{border-bottom:0}
body.workspace .assessment>summary,body.workspace .tile .head{position:relative;grid-template-columns:clamp(84px,9vw,128px) minmax(0,1fr) 44px;gap:clamp(16px,2vw,32px);padding:clamp(16px,1.7vw,24px) clamp(16px,1.8vw,26px) clamp(16px,1.7vw,24px) 0}
body.workspace .assessment.next>summary:before,body.workspace .tile.now .head:before{content:'';position:absolute;left:0;top:18px;bottom:18px;width:3px;border-radius:0 3px 3px 0;background:var(--strong)}
/* Date column */
body.workspace .date-tile,body.workspace .tile .date{background:transparent!important;color:var(--hub-ink)!important;border:0;border-right:1px solid var(--hub-line);border-radius:0;min-height:0;padding:4px 0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px}
body.workspace .date-tile span,body.workspace .tile .date .m,body.workspace .tile .date .x{font:500 10px/1.2 var(--ns-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--hub-muted)}
body.workspace .date-tile b,body.workspace .tile .date .dd{font-size:clamp(2rem,2.8vw,3rem);font-weight:520;font-variation-settings:'wdth' 78;font-variant-numeric:tabular-nums;letter-spacing:-.04em;line-height:.9}
body.workspace .date-tile b.date-unknown{font-size:clamp(1.1rem,1.4vw,1.4rem);letter-spacing:-.02em}
body.workspace .assessment.next .date-tile b,body.workspace .tile.now .date .dd{color:var(--strong)}
/* Title + meta */
body.workspace .assessment-title,body.workspace .tile .title{font-size:clamp(1.15rem,1.6vw,1.55rem);font-weight:600;letter-spacing:-.025em;line-height:1.15}
body.workspace .assessment-meta,body.workspace .tile .badges{margin-top:10px;gap:6px}
body.workspace .assessment-meta .pill{border-radius:999px;padding:5px 10px;font-size:.72rem;background:var(--hub-soft);color:var(--hub-ink)}
body.workspace .assessment-meta .pill.active{background:color-mix(in srgb,var(--accent) 55%,var(--hub-panel));color:var(--hub-ink)}
body.workspace .tile .chip{border-radius:999px;padding:5px 10px;font-size:.7rem}
body.workspace .tile .arrow,body.workspace .assessment>summary:after{justify-self:center}
@media(hover:hover) and (pointer:fine){
 body.workspace .assessment>summary:hover,body.workspace .tile .head:hover{background:color-mix(in srgb,var(--accent) 7%,transparent)}
}
body.workspace .panel-intro{margin:0 0 12px}
body.workspace #p-team>.lead,body.workspace #p-you>.lead{font-size:.9rem;color:var(--hub-muted)}
body.workspace #p-you{margin-top:36px}
body.workspace .workspace-disclosure,body.workspace #workspace-info .tools,body.workspace #workspace-info .guide-tools,body.workspace #workspace-info .section-panel,body.workspace #workspace-info .profile-picker{border-radius:14px}

/* ---------- Dock ---------- */
.ns-dock{position:static;height:0;--page-gutter:clamp(18px,3.6vw,64px)}
.ns-dock-bar{position:fixed;z-index:40;top:0;left:var(--ns-dock-left,0);width:var(--ns-dock-width,100%);display:flex;align-items:center;gap:clamp(12px,2vw,28px);height:64px;padding:0 var(--page-gutter,36px);background:var(--ns-glass);border-bottom:1px solid var(--ns-glass-line);backdrop-filter:blur(18px) saturate(1.3);-webkit-backdrop-filter:blur(18px) saturate(1.3);transform:translateY(-100%);opacity:0;visibility:hidden;transition:transform .45s var(--ns-ease),opacity .3s,visibility 0s .45s}
:root.ns-docked .ns-dock-bar{transform:none;opacity:1;visibility:visible;transition:transform .45s var(--ns-ease),opacity .3s}
/* Scroll progress along the bottom edge; scroll.mjs drives --ns-progress. */
.ns-dock-progress{position:absolute;left:0;right:0;bottom:-1px;height:2px;background:var(--strong);transform-origin:0 50%;transform:scaleX(var(--ns-progress,0))}
.ns-dock-id{display:flex;align-items:center;gap:10px;min-height:44px;color:var(--hub-ink);text-decoration:none;white-space:nowrap}
.ns-dock-id i{width:9px;height:9px;border-radius:50%;background:var(--accent);box-shadow:0 0 12px var(--accent)}
.ns-dock-id b{font:600 11px/1 var(--ns-mono);letter-spacing:.14em}
.ns-dock-id span{font-weight:600;font-size:.95rem}
/* The way back to the Desk: a quiet pill beside the course identity, kept on every width. */
.ns-dock-desk{flex:none;display:inline-flex;align-items:center;min-height:44px;padding:0 14px;border:1px solid var(--hub-line);border-radius:999px;color:var(--hub-ink);text-decoration:none;font:500 11px/1 var(--ns-mono);letter-spacing:.14em;text-transform:uppercase;white-space:nowrap}
@media(hover:hover){.ns-dock-desk:hover{border-color:var(--hub-ink)}}
.ns-dock-id:focus-visible,.ns-dock-desk:focus-visible{outline:2px solid var(--hub-focus);outline-offset:2px}
.ns-dock-next{display:flex;align-items:center;gap:10px;min-width:0;flex:1;padding-left:clamp(12px,2vw,28px);border-left:1px solid var(--hub-line)}
.ns-dock-k{font:500 10px/1 var(--ns-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--hub-muted)}
.ns-dock-title{font-weight:600;font-size:.92rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.ns-dock-chip{flex:none;padding:5px 10px;border-radius:999px;background:color-mix(in srgb,var(--accent) 22%,transparent);color:var(--hub-ink);font:600 11px/1 var(--ns-mono);letter-spacing:.06em;font-variant-numeric:tabular-nums}
:root[data-ns-urgency=hot] .ns-dock-chip{background:color-mix(in srgb,var(--ns-hot) 24%,transparent)}
.ns-dock-actions{display:flex;gap:8px}
.ns-dock-actions button{display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:8px 14px;border-radius:999px;border:1px solid var(--hub-line);background:var(--hub-panel);color:var(--hub-ink);font:600 .78rem Archivo,system-ui,sans-serif;cursor:pointer;white-space:nowrap}
.ns-dock-actions button:focus-visible{outline:2px solid var(--hub-focus);outline-offset:2px}
.ns-dock-actions kbd{font:500 10px/1 var(--ns-mono);padding:3px 5px;border-radius:5px;border:1px solid var(--hub-line);color:var(--hub-muted)}
.ns-dock-motion i{width:10px;height:10px;display:inline-block;background:linear-gradient(90deg,currentColor 0 35%,transparent 35% 65%,currentColor 65%)}
.ns-dock-motion[aria-pressed=true] i{background:currentColor;clip-path:polygon(0 0,100% 50%,0 100%)}
.ns-dock-motion:disabled{opacity:.5;cursor:default}

/* ---------- Tablet & phone ---------- */
@media(max-width:1000px){
 body.workspace .workspace-page-title{font-size:clamp(2.2rem,7vw,3.6rem)}
}
@media(max-width:860px){
 .ns-count{margin-top:22px}
 body.workspace .cen-next-layout .next.ns-next .ns-count{margin-top:18px}
}
@media(max-width:760px){
 body.workspace .header-upgraded h1{font-variation-settings:'wdth' 80}
 .ns-hud{margin-top:14px;font-size:10px}.ns-hud [data-ns-title]{font-size:13px}
 .header-upgraded .workspace-actions button{padding:10px 12px;font-size:.72rem}
 body.workspace .assessment>summary,body.workspace .tile .head{grid-template-columns:64px minmax(0,1fr) 28px;gap:14px;padding:18px 14px 18px 0}
 body.workspace .date-tile b,body.workspace .tile .date .dd{font-size:1.8rem}
 body.workspace #assessment-list,body.workspace #teamlist,body.workspace #youlist{border-radius:14px}
 .ns-timeline{padding:18px 0 6px;overflow:hidden}.ns-tl-head{padding:0 16px}
 .ns-tl-track{min-width:860px;margin:0 24px}
 .ns-dock-bar{height:56px;gap:10px}
 .ns-dock-id span,.ns-dock-k,.ns-dock-section,.ns-dock-motion span,.ns-dock-search span,.ns-dock-search kbd{display:none!important}
 .ns-dock-search:before{content:'⌕';font-size:1.1rem}
 .ns-dock-actions button{padding:8px 12px}
 /* Icon-only on phones: keep a 44 px target. */
 .ns-dock-actions :is(.ns-dock-motion,.ns-dock-search){min-width:44px;justify-content:center}
 /* Long status chips ("Date passed (time not posted)") shrink with an ellipsis instead of covering the buttons. */
 .ns-dock-chip{flex:0 1 auto;min-width:0;max-width:42vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
 .ns-dock-desk{padding:0 10px;letter-spacing:.08em}
 .ns-dock-next{padding-left:10px}
}
@media(max-width:420px){.ns-unit b{font-size:2rem}.ns-ring{width:48px}}
/* Narrow phones: identity, Desk, chip and actions fill the bar, so the title is read out but not drawn. */
@media(max-width:480px){.ns-dock-title{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.ns-dock-next{justify-content:flex-start}}

@media print{.ns-dock,.ns-timeline,.ns-hud,.ns-count{display:none!important}}

/* =====================================================================================================
   The semester book (spec §6): MTH140's hero is the open sketchbook on a desk. html[data-book] is set by
   course-header.mjs while a book route is mounted. Everything here reads finished with motion paused:
   the stage, the rail (caption and week controls) and the action bar are the paused composition.
   ===================================================================================================== */

/* ---------- Skip to coursework: first tab stop, Desk styling ---------- */
html[data-book] body.workspace>.skip-link{position:fixed;top:10px;left:10px;z-index:10001;display:inline-flex;align-items:center;box-sizing:border-box;min-height:44px;padding:12px 18px;border:1px solid var(--hub-line);border-radius:999px;background:var(--hub-panel);color:var(--hub-ink);font:650 .9rem Archivo,system-ui,sans-serif;text-decoration:none;box-shadow:0 18px 40px -22px rgb(0 0 0 / .5);transform:translateY(-200%)}
html[data-book] body.workspace>.skip-link:focus{transform:none;outline:3px solid var(--hub-focus);outline-offset:2px}

/* ---------- The dock: actionable from arrival, shown when it has a job ----------
   On a book route the dock is never inert (deadline.mjs). At arrival it waits just above the viewport, in
   the tab order: focusing any of its controls brings it down. It also arrives when the action bar scrolls
   away (ns-docked) and while the closing book is handed to it (ns-dock-show), so the book lands in its dot. */
html[data-book] .ns-dock-bar{visibility:visible}
html[data-book] .ns-dock-bar:focus-within,:root[data-book].ns-dock-show .ns-dock-bar{transform:none;opacity:1;transition:transform .45s var(--ns-ease),opacity .3s}
html[data-book]{scroll-padding-top:calc(var(--ns-dock-h) + 16px)}
html[data-book][data-motion=off] .ns-dock-bar{transition:none}
/* The closed book lands in the dock's course dot: one static glow, then rest (deadline.mjs). */
html[data-book] .ns-dock-id i{transition:box-shadow .4s var(--ns-ease),transform .4s var(--ns-ease)}
html[data-book].ns-dock-received .ns-dock-id i{box-shadow:0 0 0 5px color-mix(in srgb,var(--accent) 30%,transparent),0 0 22px var(--accent);transform:scale(1.25)}
html[data-book][data-motion=off] .ns-dock-id i{transition:none}

/* ---------- Stage, rail and action bar ---------- */
html[data-book] body.workspace .header-upgraded{
 --book-stage:clamp(520px,66vh,640px);--book-pool:62% 42%;
 grid-template-columns:minmax(0,1fr);grid-template-rows:var(--book-stage) auto auto;
 background:var(--hub-bg);overflow:clip;isolation:isolate}
/* The desk under the canvas (posters are transparent over it), then grain and vignette over both. */
html[data-book] body.workspace .header-upgraded::before,html[data-book] body.workspace .header-upgraded::after{content:'';grid-row:1;grid-column:1;align-self:stretch;justify-self:stretch;pointer-events:none}
html[data-book] body.workspace .header-upgraded::before{z-index:0;
 background:radial-gradient(60% 70% at var(--book-pool),var(--ns-desk-light),transparent 70%),linear-gradient(160deg,var(--ns-desk),var(--ns-desk-2))}
/* Static blue-noise grain over desk and book alike; never animated. */
html[data-book] body.workspace .header-upgraded::after{z-index:2;background:url(grain.png) 0 0/256px 256px repeat;opacity:var(--ns-grain)}
html[data-book] body.workspace .header-upgraded>.header-art{grid-row:1;grid-column:1;align-self:stretch;justify-self:stretch;position:relative;inset:auto;z-index:1;width:auto;height:auto;min-height:0;
 border-radius:0;touch-action:pan-y;cursor:default;user-select:none;-webkit-user-select:none;contain:layout paint;overflow:hidden}
/* The vignette sits over the canvas too, inside the slot (spec decision 9). */
html[data-book] body.workspace .header-upgraded>.header-art::after{content:'';display:block;position:absolute;inset:0;z-index:1;pointer-events:none;background:none;box-shadow:inset 0 0 160px var(--ns-desk-vignette)}
html[data-book] .header-art[data-cursor=open]{cursor:pointer}
html[data-book] .header-art[data-cursor=turn]{cursor:grab}
html[data-book] .header-art[data-cursor=drag],html[data-book] .header-art[data-dragging=true]{cursor:grabbing}
html[data-book] .header-art .scene-poster{object-fit:cover;object-position:var(--book-pool);animation:none!important;transform:none!important;transition:opacity .2s linear .3s}
html[data-book] .header-art[data-renderer=poster] .scene-poster{opacity:1}
html[data-book][data-motion=off] .header-art .scene-poster{transition:none}
html[data-book] body.workspace .header-upgraded>.hero-copy{grid-row:1;grid-column:1;z-index:3;align-self:center;justify-self:start;
 max-width:31%;padding:0 0 calc(var(--book-stage) * .1) var(--page-gutter);margin:0;box-sizing:content-box;pointer-events:none}
html[data-book] body.workspace .header-upgraded>.hero-copy a,html[data-book] body.workspace .header-upgraded>.hero-copy button{pointer-events:auto}
html[data-book] body.workspace .header-upgraded h1{color:var(--ns-stage-ink)}
html[data-book] body.workspace .header-upgraded .hero-copy :is(.team,.eyebrow){color:var(--ns-stage-strong)}
html[data-book] body.workspace .header-upgraded .hero-copy :is(.subline,.hero-organization){display:none}
html[data-book] .ns-hud{color:var(--ns-stage-muted)}
html[data-book] .ns-hud [data-ns-title]{color:var(--ns-stage-ink)}
html[data-book] .ns-hud .ns-hud-k,html[data-book] .ns-hud [data-ns-chip]{color:var(--ns-stage-strong)}
html[data-book] .ns-hud .ns-hud-k{border-color:color-mix(in srgb,var(--ns-stage-strong) 45%,transparent)}
html[data-book] body.workspace .header-upgraded>.workspace-actions{grid-row:3;grid-column:1;position:relative;z-index:3}
/* Hidden feeds: visuals.js keeps CourseVisuals.rows for the palette; its strip never shows beside a book. */
html[data-book] .semester-rail{display:none!important}

/* Hint, fallback notice and the phone pause control, at the foot of the stage. */
html[data-book] body.workspace .header-upgraded>.ns-book-meta{grid-row:1;grid-column:1;z-index:3;position:relative;inset:auto;align-self:end;
 display:flex;align-items:flex-end;justify-content:space-between;gap:16px;padding:0 var(--page-gutter) 22px;pointer-events:none}
.ns-book-meta>*{pointer-events:auto}
.ns-book-hint{display:none;align-items:center;gap:9px;margin:0;font:500 10px/1.5 var(--ns-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--ns-stage-muted)}
.ns-book-hint i{width:5px;height:5px;border-radius:50%;background:var(--strong)}
html[data-book] .header-upgraded[data-book-view=webgl2] .ns-book-hint{display:inline-flex}
html[data-book] .header-upgraded.ns-explored .ns-book-hint{display:none}
.ns-book-fallback{display:grid;gap:4px;max-width:min(360px,100%);padding:14px 16px;border-radius:14px;background:var(--ns-glass);border:1px solid var(--ns-glass-line);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);color:var(--ns-stage-ink)}
.ns-book-fallback[hidden]{display:none}
.ns-book-fallback-title{margin:0;font:600 .95rem/1.3 Archivo,system-ui,sans-serif}
.ns-book-fallback-text{margin:0;font:450 .9rem/1.4 Archivo,system-ui,sans-serif;color:var(--ns-stage-muted)}
.ns-book-retry{justify-self:start;margin-top:8px;min-height:44px;padding:0 18px;border-radius:999px;border:1px solid color-mix(in srgb,var(--ns-stage-ink) 30%,transparent);background:transparent;color:var(--ns-stage-ink);font:600 .82rem Archivo,system-ui,sans-serif;cursor:pointer}
.ns-book-retry[hidden]{display:none}
.ns-book-retry:focus-visible{outline:2px solid var(--hub-focus);outline-offset:3px}
html[data-book] .ns-book-pause{margin-left:auto;border-color:color-mix(in srgb,var(--ns-stage-ink) 22%,transparent);background:color-mix(in srgb,var(--ns-desk) 55%,transparent);color:var(--ns-stage-ink)}
@media(min-width:761px){html[data-book] .ns-book-pause{display:none}}

/* ---------- The rail: caption for the selected spread and the week controls (§6.3) ---------- */
.ns-spread{grid-row:2;grid-column:1;position:relative;z-index:3;display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"caption jump" "weeks weeks";
 column-gap:clamp(20px,3vw,40px);row-gap:18px;align-items:center;padding:16px var(--page-gutter) 14px;
 background:var(--hub-bg);border-top:1px solid var(--hub-line);color:var(--hub-ink);container:ns-spread / inline-size}
/* The caption never runs under the jump group: its rows wrap inside their column (an entry's when text first, then
   its section button), and if even that cannot fit, the entries drop below the week heading. */
.ns-spread-caption{grid-area:caption;display:flex;flex-wrap:wrap;align-items:center;gap:clamp(16px,1.6vw,22px);min-width:0;min-height:48px}
.ns-spread-head{flex:none;display:grid;gap:5px}
.ns-spread-kicker{margin:0;font:500 11px/1.25 var(--ns-mono);letter-spacing:.18em;text-transform:uppercase;color:var(--strong);white-space:nowrap}
.ns-spread-kicker b{font-weight:500;color:var(--hub-ink)}
.ns-spread-dates{margin:0;display:flex;flex-wrap:wrap;align-items:baseline;column-gap:.35em;font:600 1.25rem/1.15 Archivo,system-ui,sans-serif;letter-spacing:-.012em;font-variant-numeric:tabular-nums;color:var(--hub-ink)}
.ns-spread-dates time{white-space:nowrap}
.ns-spread-dates .ns-dash{color:var(--hub-muted);font-weight:400}
.ns-spread-note{margin-left:.5em;font:500 .8rem/1 Archivo,system-ui,sans-serif;letter-spacing:0;color:var(--hub-muted);white-space:nowrap}
.ns-spread-body{flex:1;min-width:auto;align-self:stretch;display:flex;align-items:center;padding-left:clamp(16px,1.6vw,22px);border-left:1px solid var(--hub-line)}
.ns-spread-items{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;align-items:center;gap:4px 22px;min-width:0}
.ns-spread-item{display:flex;flex-wrap:wrap;align-items:center;gap:10px 14px;min-width:0;border-radius:12px}
.ns-spread-open{flex:1 1 12em;display:grid;align-content:center;row-gap:3px;min-height:48px;min-width:44px;padding:4px 10px 4px 0;margin:0;border:0;background:none;color:var(--hub-ink);font:inherit;text-align:left;cursor:pointer;border-radius:10px}
.ns-item-line{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 10px;min-width:0}
.ns-item-kind{font:500 10px/1 var(--ns-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--strong)}
.ns-item-title{position:relative;font:650 1rem/1.2 Archivo,system-ui,sans-serif;letter-spacing:-.01em}
.ns-item-when{font:450 1rem/1.2 Archivo,system-ui,sans-serif;color:var(--hub-muted);text-wrap:pretty}
.ns-spread-item:is([data-chip=NEXT],[data-chip=SOON],[data-chip=NOW]) .ns-item-title{padding-right:14px}
.ns-spread-item:is([data-chip=NEXT],[data-chip=SOON],[data-chip=NOW]) .ns-item-title::after{content:'';position:absolute;right:0;top:50%;width:6px;height:6px;margin-top:-3px;border-radius:50%;background:var(--strong)}
.ns-spread-item[data-urgency=soon] .ns-item-title::after{background:var(--ns-stage-soon)}
.ns-spread-item[data-urgency=hot] .ns-item-title::after{background:var(--ns-hot)}
.ns-item-status{align-self:center;padding:4px 8px;border-radius:999px;font:500 10px/1 var(--ns-mono);letter-spacing:.12em;text-transform:uppercase;background:color-mix(in srgb,var(--accent) 24%,transparent);color:var(--hub-ink);white-space:nowrap}
.ns-spread-item[data-urgency=hot] .ns-item-status{background:color-mix(in srgb,var(--ns-hot) 24%,transparent)}
.ns-spread-item[data-done] .ns-item-title{text-decoration:line-through;text-decoration-thickness:1px;text-decoration-color:color-mix(in srgb,var(--hub-ink) 45%,transparent)}
.ns-spread-item[data-done] .ns-item-status,.ns-spread-item[data-passed] .ns-item-status{background:var(--hub-soft);color:var(--hub-muted)}
@media(hover:hover){.ns-spread-open:hover .ns-item-title{text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px}}
.ns-spread-item[data-hover] .ns-item-title{text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px}
/* Rail focus rings are scoped under .ns-spread so they outrank the shared button:focus-visible rings
   (course-header.css, guide-motion.css: offset 4px), which the tick scroller would clip. */
.ns-spread .ns-spread-open:focus-visible{outline:2px solid var(--hub-focus);outline-offset:2px}
.ns-spread .ns-spread-cta{margin:0;min-height:44px;padding:0 15px;font-size:.78rem;white-space:nowrap}
.ns-spread-empty{margin:0;font:450 1rem/1.3 Archivo,system-ui,sans-serif;color:var(--hub-muted)}
.ns-spread-more{position:relative}
.ns-spread-more>summary{display:inline-flex;align-items:center;min-height:44px;padding:0 12px;border-radius:999px;cursor:pointer;font:500 11px/1 var(--ns-mono);letter-spacing:.14em;text-transform:uppercase;color:var(--hub-muted);list-style:none}
.ns-spread-more>summary::-webkit-details-marker{display:none}
.ns-spread-more[open]>.ns-spread-items{position:absolute;z-index:6;left:0;top:100%;display:grid;min-width:280px;padding:8px 12px;border-radius:14px;background:var(--hub-panel);border:1px solid var(--hub-line);box-shadow:0 24px 50px -24px rgb(0 0 0 / .45)}

/* Today and Next assessment */
.ns-spread-jump{grid-area:jump;display:flex;align-items:center;justify-content:flex-end;gap:8px}
.ns-spread-jump button,.ns-week-step{display:inline-flex;align-items:center;gap:8px;min-height:44px;min-width:44px;padding:0 15px;border-radius:999px;border:1px solid var(--hub-line);background:var(--hub-panel);color:var(--hub-ink);font:600 .82rem/1.1 Archivo,system-ui,sans-serif;white-space:nowrap;cursor:pointer}
.ns-week-today i{width:7px;height:7px;border-radius:50%;box-shadow:0 0 0 1.5px var(--strong);background:transparent}
.ns-week-today[aria-disabled=true]{color:var(--hub-muted);cursor:default}
.ns-week-today[aria-disabled=true] i{background:var(--strong)}
.ns-week-next{max-width:min(380px,40vw)}
.ns-week-next[hidden]{display:none}
.ns-week-next-k{flex:none;font:500 10px/1 var(--ns-mono);letter-spacing:.14em;text-transform:uppercase;color:var(--strong)}
.ns-week-next-t{min-width:0;overflow:hidden;text-overflow:ellipsis}
.ns-week-next b{font-weight:500;color:var(--hub-muted)}
.ns-week-next[data-mode=open]{background:color-mix(in srgb,var(--accent) 26%,var(--hub-panel));border-color:color-mix(in srgb,var(--strong) 40%,transparent)}
.ns-week-step b{font-weight:400;font-size:1.05rem;line-height:1;color:var(--hub-muted)}
.ns-week-step[aria-disabled=true]{opacity:.45;cursor:default}
.ns-spread .ns-spread-jump button:focus-visible,.ns-spread .ns-week-step:focus-visible{outline:2px solid var(--hub-focus);outline-offset:2px}
@media(hover:hover){.ns-spread-jump button:not([aria-disabled=true]):hover,.ns-week-step:not([aria-disabled=true]):hover{border-color:color-mix(in srgb,var(--hub-ink) 45%,transparent)}.ns-week-next[data-mode=open]:hover{border-color:var(--hub-ink)}}

/* Week ticks: a semester ruler. Each mark rises with the spread's tallest pop-up (final > midterm > quiz >
   minor; a hairline when empty, an open bracket for the dateless exam spread). The ruler's line is filled up to
   today; today's number wears the accent ring, the selected week a 2 px underline. */
.ns-weeks{grid-area:weeks;display:flex;align-items:center;gap:8px;min-width:0}
.ns-week-scroll{flex:1;min-width:0;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;scroll-snap-type:x proximity;padding-top:14px;margin-top:-14px;overscroll-behavior-x:contain}
.ns-week-scroll::-webkit-scrollbar{display:none}
.ns-week-ticks{--elapsed:0%;position:relative;display:flex;width:100%;min-width:max-content}
.ns-week-ticks::before,.ns-week-ticks::after{content:'';position:absolute;left:22px;top:21px;height:1px;pointer-events:none}
.ns-week-ticks::before{right:22px;background:var(--hub-line)}
.ns-week-ticks::after{width:calc(var(--elapsed) - 22px);height:2px;top:20px;border-radius:2px;background:var(--strong)}
.ns-tick{--mark:3px;position:relative;flex:1 0 44px;min-width:44px;height:44px;padding:0;margin:0;border:0;background:none;color:var(--hub-muted);cursor:pointer;scroll-snap-align:center;font:inherit;border-radius:8px}
.ns-tick-bar{position:absolute;left:50%;bottom:23px;width:4px;height:var(--mark);margin-left:-2px;border-radius:2px 2px 0 0;background:color-mix(in srgb,var(--hub-ink) 30%,transparent)}
.ns-tick[data-kind=minor] .ns-tick-bar{--mark:6px}
.ns-tick:is([data-kind=quiz],[data-kind=lab]) .ns-tick-bar{--mark:9px}
.ns-tick[data-kind=midterm] .ns-tick-bar{--mark:13px}
.ns-tick[data-kind=final] .ns-tick-bar{--mark:18px}
.ns-tick[data-kind=none] .ns-tick-bar{width:1px;margin-left:0;border-radius:0;background:color-mix(in srgb,var(--hub-ink) 22%,transparent)}
.ns-tick[data-past] .ns-tick-bar{background:var(--strong)}
.ns-tick[data-past][data-kind=none] .ns-tick-bar{background:color-mix(in srgb,var(--strong) 70%,transparent)}
.ns-tick-pending .ns-tick-bar{width:12px;margin-left:-6px;--mark:12px;background:none!important;border:1.5px solid color-mix(in srgb,var(--hub-ink) 42%,transparent);border-bottom:0;border-radius:3px 3px 0 0}
.ns-tick[data-done] .ns-tick-bar::after{content:'';position:absolute;left:50%;bottom:calc(100% + 4px);width:7px;height:3.5px;margin-left:-4px;border-left:1.5px solid var(--strong);border-bottom:1.5px solid var(--strong);transform:rotate(-45deg)}
.ns-tick-n{position:absolute;left:0;right:0;top:24px;font:500 11px/14px var(--ns-mono);letter-spacing:.02em;text-align:center;font-variant-numeric:tabular-nums}
.ns-tick[data-today] .ns-tick-n{color:var(--hub-ink)}
.ns-tick[data-today] .ns-tick-n::before{content:'';position:absolute;left:50%;top:50%;width:20px;height:20px;margin:-10px 0 0 -10px;border-radius:50%;box-shadow:0 0 0 1.5px var(--strong)}
.ns-tick[data-today]::before{content:'Today';position:absolute;left:50%;top:-12px;transform:translateX(-50%);font:600 9px/1 var(--ns-mono);letter-spacing:.14em;text-transform:uppercase;color:var(--strong);white-space:nowrap}
.ns-tick[aria-checked=true]{color:var(--hub-ink)}
.ns-tick[aria-checked=true] .ns-tick-n{font-weight:700}
.ns-tick[aria-checked=true]::after{content:'';position:absolute;left:50%;width:18px;margin-left:-9px;bottom:0;height:2px;border-radius:2px;background:var(--hub-ink)}
@media(hover:hover){.ns-tick:hover{background:color-mix(in srgb,var(--hub-ink) 5%,transparent)}}
.ns-spread .ns-tick:focus-visible{outline:2px solid var(--hub-focus);outline-offset:-2px}

/* Desktop wide enough for the whole ruler: it spans the rail. */
@media(min-width:761px) and (max-width:1000px){
 html[data-book] body.workspace .header-upgraded{--book-stage:clamp(480px,62vh,580px);--book-pool:50% 60%}
 html[data-book] body.workspace .header-upgraded>.hero-copy{align-self:start;max-width:none;padding:28px var(--page-gutter) 0}
 .ns-spread{grid-template-columns:minmax(0,1fr);grid-template-areas:"caption" "jump" "weeks"}
 .ns-spread-jump{justify-content:flex-start}
}
/* A desktop column too narrow for the widest caption minimum (week heading plus a section button, about 465 px)
   beside the widest jump group (Today plus a Next capped at 380 px, about 505 px, and the 40 px gap) stacks them like
   the tablet rail. A container query, so the sidebar and zoom are already accounted for; the rail's own grid cannot
   change from inside it, so its children are placed instead. */
@media(min-width:1001px){@container ns-spread (max-width:1009.98px){
 .ns-spread-caption{grid-area:auto;grid-column:1 / -1;grid-row:1}
 .ns-spread-jump{grid-area:auto;grid-column:1 / -1;grid-row:2;justify-content:flex-start}
 .ns-weeks{grid-area:auto;grid-column:1 / -1;grid-row:3}
}}
/* Phone: copy above the stage on the same desk, then the rail and the action bar. */
@media(max-width:760px){
 html[data-book] body.workspace .header-upgraded{--book-stage:300px;--book-pool:50% 70%;grid-template-rows:auto auto var(--book-stage) auto auto}
 html[data-book] body.workspace .header-upgraded::before,html[data-book] body.workspace .header-upgraded::after{grid-row:1 / 4}
 html[data-book] body.workspace .header-upgraded>.header-art{grid-row:3}
 /* One vignette for copy and stage together, under the canvas, so the seam between them never darkens. */
 html[data-book] body.workspace .header-upgraded>.header-art::after{box-shadow:none}
 html[data-book] body.workspace .header-upgraded::before{background:radial-gradient(130% 90% at 50% 55%,transparent 55%,var(--ns-desk-vignette)),radial-gradient(60% 60% at var(--book-pool),var(--ns-desk-light),transparent 70%),linear-gradient(160deg,var(--ns-desk),var(--ns-desk-2))}
 html[data-book] .header-art .scene-poster{object-position:50% 53%}
 html[data-book] body.workspace .header-upgraded>.hero-copy{grid-row:1;align-self:start;max-width:none;min-height:0;padding:24px var(--page-gutter) 4px}
 /* The hint and the pause control get their own line between the copy and the book, on the same desk. */
 html[data-book] body.workspace .header-upgraded>.ns-book-meta{grid-row:2;align-self:center;align-items:center;min-height:44px;padding:0 var(--page-gutter)}
 html[data-book] body.workspace .header-upgraded>.workspace-actions{grid-row:5}
 .ns-spread{grid-row:4;grid-template-columns:minmax(0,1fr);grid-template-areas:"caption" "weeks" "jump";row-gap:14px;padding:18px var(--page-gutter) 16px}
 .ns-spread-caption{display:grid;gap:8px;min-height:0}
 .ns-spread-body{padding:0;border:0}
 .ns-spread-items{display:grid;gap:0;width:100%}
 .ns-spread-item{flex-wrap:wrap;gap:4px 12px;padding:2px 0 10px;border-top:1px solid var(--hub-line);border-radius:0}
 .ns-spread-item:first-child{border-top:0}
 .ns-spread-open{flex:1 1 100%}
 .ns-item-when{white-space:normal}
 .ns-spread-dates{font-size:1.15rem}
 .ns-weeks{display:grid;grid-template-columns:1fr 1fr;grid-template-areas:"ticks ticks" "prev next";gap:10px 8px}
 .ns-week-scroll{grid-area:ticks;margin-inline:calc(var(--page-gutter) * -1);padding-inline:var(--page-gutter);scroll-padding-inline:var(--page-gutter);
  -webkit-mask:linear-gradient(90deg,transparent,#000 var(--page-gutter),#000 calc(100% - var(--page-gutter)),transparent);mask:linear-gradient(90deg,transparent,#000 var(--page-gutter),#000 calc(100% - var(--page-gutter)),transparent)}
 .ns-weeks .ns-week-step[data-step="-1"]{grid-area:prev}
 .ns-weeks .ns-week-step[data-step="1"]{grid-area:next;justify-content:flex-end}
 .ns-week-step{justify-content:flex-start}
 .ns-spread-jump{display:grid;grid-template-columns:auto minmax(0,1fr);gap:8px}
 .ns-week-next{max-width:none;justify-content:space-between}
}

/* ---------- §6.8 the fallback week view (poster or low tier only) ---------- */
.ns-weekview[hidden]{display:none}
.ns-weekview .ns-tl-head h2{margin:0}
.ns-wv-track{height:132px}
.ns-wv-week{position:absolute;top:0;height:44px;min-width:44px;padding:0;border:0;background:none;color:var(--hub-muted);font:500 11px/1 var(--ns-mono);font-variant-numeric:tabular-nums;cursor:pointer;border-radius:8px}
.ns-wv-week>span{position:absolute;left:50%;top:14px;transform:translateX(-50%)}
.ns-wv-week.is-today{color:var(--strong);font-weight:700}
.ns-wv-week[data-selected]{color:var(--hub-ink);font-weight:700}
.ns-wv-week[data-selected]::after{content:'';position:absolute;left:30%;right:30%;bottom:4px;height:2px;border-radius:2px;background:var(--hub-ink)}
@media(hover:hover){.ns-wv-week:hover{background:color-mix(in srgb,var(--hub-ink) 5%,transparent)}}
.ns-weekview .ns-wv-week:focus-visible{outline:2px solid var(--hub-focus);outline-offset:-2px}
.ns-wv-band{position:absolute;top:46px;bottom:28px;left:var(--selected,0);width:var(--slot,0);border-radius:10px;background:color-mix(in srgb,var(--accent) 14%,transparent);pointer-events:none}
.ns-weekview .ns-tl-rail{top:76px}
.ns-weekview .ns-tl-node{top:77px}
.ns-weekview .ns-tl-node.is-week>i{border-style:dashed}
.ns-weekview .ns-tl-month{top:108px}
.ns-weekview .ns-tl-today{top:44px;bottom:30px}
.ns-weekview .ns-tl-today>span{display:none}
.ns-weekview .ns-tl-today>i{top:27px}
@media print{html[data-book] .header-upgraded::before,html[data-book] .header-upgraded::after,.ns-spread .ns-weeks,.ns-spread-jump{display:none!important}}

/* ScrollTrigger measures the pin's height with its margins zeroed. With an auto width the header would lose its full
   bleed for that moment, and the rail, which wraps to its width, would be measured taller than it lays out (the
   pinned header then keeps blank rows). An explicit full-bleed width keeps the measured height the real one (on
   screen only: print drops the bleed margins). */
@media screen{html[data-book] body.workspace .header-upgraded{width:calc(100% + 2 * var(--page-gutter))}}
/* The book pin (pinType transform) leaves the header in flow inside its spacer. GSAP copies the header's
   width without its full-bleed margins, which would leave a strip on the right; let it fill the spacer. */
html[data-book] body.workspace .pin-spacer>.course-heading.ns-scrub{width:auto!important;max-width:none!important}
