/* Motion, ring states and scroll performance (round 3, workstream B). Linked after every other
   stylesheet (base.html), so a rule here wins over the same selector in design.css/app.css.
   Only motion, the countdown ring's states and performance overrides live here; layout and
   colour tokens stay in design.css. Every moving thing below stops under reduced motion. */

/* ---- theme switch and page changes: one short crossfade (G22). app.js wraps the theme toggle
   in document.startViewTransition; cross-page tab changes already use @view-transition. */
::view-transition-old(root), ::view-transition-new(root) { animation-duration: .25s; }

/* ---- job cards: the same 180ms in and out on hover (G22, motion F-B).
   The reveal used to share "transform" with the hover lift, so leaving a card ran the slow
   0.5s reveal transition (with its stagger delay) in reverse. The reveal now moves the
   separate "translate" property; "transform" is left to the hover alone. */
.jr.card { transition: border-color .18s, box-shadow .18s, transform .18s cubic-bezier(.2, .7, .2, 1); }
.jr.card.rv { transform: none; translate: 0 14px; }
.jr.card.rv.in {
  translate: none;
  transition: opacity .5s ease, translate .5s cubic-bezier(.2, .7, .2, 1), transform .18s cubic-bezier(.2, .7, .2, 1), border-color .18s, box-shadow .18s;
  transition-delay: var(--stagger, 0ms), var(--stagger, 0ms), 0ms, 0ms, 0ms;
}
/* no press-shrink: on a phone it read as a jolt under the finger, on a laptop it undid the lift */
.jr.card:active { transform: none; }
/* J25 (MO F5): a revealed job card lifted 2px (design.css .jr.card.rv.in:hover outranked the
   rule here) while series cards lift 3px; both now lift 3px, and a press settles to 1px in
   80ms, so a click is felt. Pointer devices only. */
@media (hover: hover) {
  .jr.card:hover, .jr.card.rv.in:hover { transform: translateY(-3px); }
  .jr.card:active, .jr.card.rv.in:active, .sr-card:active { transform: translateY(-1px); transition-duration: .08s; }
}
/* a touch screen keeps :hover after a tap; there the card simply stays put */
@media (hover: none) { .jr.card:hover, .jr.card.rv.in:hover { transform: none; } }

/* J25 (MO F6): the Compact toggle cross-fades the list, and then the rows it pulls into view
   used to reveal themselves (fade, slide, ring draw) for another 500ms: a second wave. In the
   compact list a row is shown finished, so when the reveal observer marks it later nothing
   is left to animate. (design.css already stops every transition for the frame of the swap.) */
.dens-swap .ring .ra, .dens-swap .rv { transition: none !important; }
.dens-compact .feed .jr.card.rv:not(.in) { opacity: 1; translate: none; transform: none; transition: none; }
/* a reveal still running when the list turns compact ends at once too */
.dens-compact .feed .jr.card.rv.in { transition-property: border-color, box-shadow, transform; }
.dens-compact .feed .jr.card.rv .ring .ra { stroke-dashoffset: var(--arc); transition: none; }

/* ---- phones: the header hides on the way down and the tabs row follows it up (G22, motion F-I).
   Works whether app.js marks <body> or <header class="top">.
   R8 (Q16, M4): the distance is the header's real height (--hdr-h, app.js measures it), so
   at 200% text the row neither slides under the re-shown header nor leaves a gap.
   MW1 (iPhone Safari, 17 Oct): the row follows the header by its sticky offset ("top"), not a
   transform. A transform moved the row even while it sat in its own place in the page (header
   already hidden, row not yet stuck): it rode up over the hero card and left a blank band of the
   header's height under it, until the next scroll event, which iOS delays in momentum scrolling.
   "top" only acts while the row is stuck, so wherever the scroll stops the row is either in its
   place or flush under the header (at the very top when the header is away). The /exams jump
   chips (.sr-jump) follow the header the same way instead of leaving a strip of page above them. */
.tabs-row, .week, .sr-jump { transition: top .2s ease; }
@media (max-width: 959px) {
  :root:has(.hdr-hide) .tabs-row, :root:has(.hdr-hide) .week { top: 0; }
  :root:has(.hdr-hide) .sr-jump { top: 0; }
  :root:has(.hdr-hide) header.top { transform: translateY(-100%); }
}

/* ---- countdown rings (H8; all ring CSS lives here, K6). "The brand mark must be flawless":
   the number sits inside the ring with at least 2px clear of the stroke, and the unit ("days",
   "दिन") hangs just under the ring, where it can never touch the stroke (in a 44px ring it
   used to sit in the narrow chord and clip the arc). .ring-t goes static so <small> positions
   against the ring itself; the ring keeps 13px under it for the unit, so nothing overlaps. */
.ring > .ring-t { position: static; letter-spacing: -.01em; }
.ring > .ring-t small { position: absolute; top: 100%; left: 50%; transform: translateX(-50%); margin-top: 2px; font: 600 11px/1 var(--sans); letter-spacing: 0; color: var(--ink-2); white-space: nowrap; }
.ring:has(> .ring-t small) { margin-bottom: 13px; }
/* M20 (DS F7): Devanagari needs more size than Latin to read the same; no ring unit under
   12.5px on /hi ("दिन" was 11px), and the ring keeps the extra 2px under it */
.ring > .ring-t small:lang(hi), .ring.ex-ring > span small:lang(hi) { font-size: 12.5px; }
.ring:has(> .ring-t small:lang(hi)) { margin-bottom: 15px; }
.jr-lead { height: auto; }
/* the feed ring is 50px like the deadline lists (44px left "Today" under 2px from the stroke) */
.jr-lead, .jr-lead .ring { width: 50px; }
.jr-lead .ring { height: 50px; }
.jr.card { grid-template-columns: 50px minmax(0, 1fr) auto; }
/* R9 (R4, UP trunc at 1440): the board column keeps at least the board's own width (the eye's
   min-content is the board, flex: none) and the deadline/kind line takes at most 55%; its grey
   context ellipsises first. Before, an "auto" kind line with a long context left the board
   15px ("SSC CR" 15/48). */
@media (min-width: 760px) { .jr.card { grid-template-columns: 50px minmax(min-content, 1fr) fit-content(55%) auto; } }

/* "closes today": a full red ring on a red tint with a bold "Today"/"आज" (G23). J17/OD22: one
   treatment for every ring of 30px or more (feed, deadline lists, the hero's "Closing this
   week", the /exam aside), and no ring text under 11px: "Today" is 11px, which fits inside a
   50px ring (and the 44px hero ring, whose stroke is thinner) with clear space all round. */
/* M20 (DS F3): ONE "Today" ring on every surface (hero list, rail, feed, /closing): a full
   red stroke on an 8% red disc, drawn finished. It used to draw in with the card's reveal,
   so a rail ring not yet revealed showed only the pale track and disc (a second dialect). */
/* P21 (QM N6): the disc is opaque (8% red on the card), so the rail's connector line no
   longer runs through "Today" */
.ring.r-today { border-radius: 50%; background: color-mix(in srgb, var(--hot) 8%, var(--surface)); }
.ring.r-today .ra, .rv .ring.r-today .ra, .rv.in .ring.r-today .ra { stroke: var(--hot); stroke-dashoffset: 0; transition: none; }
.ring.r-today .rt { stroke: color-mix(in srgb, var(--hot) 25%, transparent); }
.ring.r-today > .ring-t { font: 700 11px/1 var(--display); letter-spacing: -.02em; color: var(--hot); }
.ring.r-today > .ring-t:lang(hi) { font-size: 12px; letter-spacing: 0; }
/* Anek's Latin sits a little high and its last letter carries the negative tracking: nudge
   the word onto the ring's true centre (it has no unit under it, so it may move) */
.ring.r-today > .ring-t:not(:lang(hi)) { position: relative; top: .7px; left: -.5px; }
.ring.r-today::after { content: none; }

/* a row with no countdown keeps its place with a muted dash, never an empty circle */
.ring-off { display: grid; place-items: center; }
.ring-off::before { content: "–"; font: 600 15px/1 var(--display); color: var(--ink-3); }

/* the hero's "Closing this week": the day count inside (no unit: the row says "3 days left"
   beside it). J17: "Today" here is the same red-tint ring with the word as everywhere else, so
   the ring is 46px with a thinner stroke (the word needs that room at 11px). The row's grid
   keeps its 32px column: the ring overhangs it by 7px on each side (into the row's padding
   and the column gap), and 3px above and below, so a row grows by only 5px and the ring
   stays clear of the separators. */
.cw-i .ring, .cw-i .ring-off { width: 46px; height: 46px; margin: -3px -7px; }
/* M20 (MO F6): a 1.5 stroke (2px at 46px) leaves "Today" at 11px 2px of air all round */
.cw-i .ring circle { stroke-width: 1.5; }
.cw-i .ring-off { border-width: 2px; }
.cw-i .ring-t { display: grid; font-size: 15px; }
.cw-i .ring > .ring-t small { display: none; }
.cw-i .ring:has(> .ring-t small) { margin-bottom: -3px; }
.cw-i .ring-off::before { font-size: 13px; }
/* R8 (Q22, MO F2): "Today" left 2.2px of air in the 46px ring (31px of word in 34px). Here the
   ring holds a red "0" (days left) on its full red ring and tint, as the compact list's Today
   ring does and as an Apple Watch complication holds a glyph; the word stays in the row's
   "Closes today" beside it (the ring is aria-hidden). Rail and feed rings
   (50px) keep the word with 4.9px of air. */
/* R9 (R6, OD63 "one Today ring"): the "0" glyph made a second dialect beside the rail's
   word. The hero ring now holds the word as the rail and /closing do: 11px (the 15px day
   count above no longer applies to it), set on a 1-line grid cell so the word's box is the
   ring's centre; with the 1.5 stroke the 46px ring leaves 5px of air beside "Today". */
.cw .cw-i .ring.r-today > .ring-t { display: grid; place-items: center; position: static; font: 700 11px/1 var(--display); letter-spacing: -.02em; color: var(--hot); }
.cw .cw-i .ring.r-today > .ring-t:lang(hi) { font-size: 12px; letter-spacing: 0; }

/* the /exam countdown (exam.css .ex-ring, overridden here per K6): the number inside, the unit
   hanging under the ring as in the feed (J17; "days" squeezed into the ring's lower chord
   before), and "Today" the same red-tint ring with an 11px word. */
.ring.ex-ring > span small { position: absolute; top: 100%; left: 50%; transform: translateX(-50%); margin-top: 2px; font: 600 11px/1 var(--sans); color: var(--ink-2); white-space: nowrap; }
.ring.ex-ring:has(> span small) { margin-bottom: 13px; }
.glance-due.ex-today .ring.ex-ring { border-radius: 50%; background: var(--hot-tint); }
.glance-due.ex-today .ring.ex-ring .rt { stroke: color-mix(in srgb, var(--hot) 25%, transparent); }
.glance-due.ex-today .ring.ex-ring > span b { font: 700 11px/1 var(--display); letter-spacing: -.02em; color: var(--hot); }
.glance-due.near .ring.ex-ring .ra { stroke: var(--live-ink); }
.glance-due.urgent .ring.ex-ring .ra { stroke: var(--hot); }
.glance-due.urgent:not(.ex-today) .ring.ex-ring .ra { stroke-dashoffset: 77; }

/* urgency, the same in card and compact mode (J17): closes within a day red (--hot), within
   a week amber (--live-ink), later the brand green; the arc and the date agree. The deadline
   lists carry the class on the row (design.css .near/.urgent); a feed card carries it on its
   deadline line, so the ring reads it through the card. */
.ring .ra { stroke: var(--brand); }
.jr.card:has(.jr-due.near) .jr-lead .ring .ra { stroke: var(--live-ink); }
.jr.card:has(.jr-due.urgent) .jr-lead .ring .ra { stroke: var(--hot); }
.jr.card .jr-due.open b { color: var(--brand); }

/* compact list: a 28px ring with the number at 11px inside, coloured by urgency (the ring
   overhangs a narrower lead column evenly, so the row grid is untouched) */
.dens-compact .feed .jr-lead, .dens-compact .feed .jr-lead .ring { width: 28px; height: 28px; justify-self: center; }
.dens-compact .feed .jr-lead .ring { margin-bottom: 0; }
.dens-compact .feed .jr-lead .ring circle { stroke-width: 3.5; }
.dens-compact .feed .jr-lead .ring-t { display: grid; font: 700 11px/1 var(--display); letter-spacing: -.02em; }
.dens-compact .feed .jr-lead .ring-t small { display: none; }
.dens-compact .feed .jr-lead .ring .ra { stroke: var(--brand); }
.dens-compact .feed .jr.card:has(.jr-due.near) .ring .ra { stroke: var(--live-ink); }
.dens-compact .feed .jr.card:has(.jr-due.urgent) .ring .ra, .dens-compact .feed .ring.r-hot .ra { stroke: var(--hot); }
.dens-compact .feed .jr.card:has(.jr-due.urgent) .ring-t, .dens-compact .feed .ring.r-hot .ring-t { color: var(--hot); }
/* closes today, under 30px: P21 (QM N9) the same red ring on its tint as everywhere else,
   with "0" inside like the other compact rings' day counts (R6 drew a solid red blob, a
   second dialect). "Today" does not fit 28px; the row's deadline words, kept for screen
   readers in compact mode, say "Closes today", and the ring is aria-hidden. */
.dens-compact .feed .ring.r-today .rt, .dens-compact .feed .ring.r-today .ra { stroke: var(--hot); }
.dens-compact .feed .ring.r-today > .ring-t { display: none; }
.dens-compact .feed .ring.r-today::after { content: "0"; position: absolute; inset: 0; width: auto; height: auto; display: grid; place-items: center; border-radius: 50%; background: none; box-shadow: none; font: 700 11px/1 var(--display); color: var(--hot); }

/* phones: the feed ring is 56px (the selector beats design.css's .jr-lead .ring) and its lead
   column grows with it; the deadline lists' rings are 56px too (QM N11) */
@media (max-width: 599px) {
  .jr.card { grid-template-columns: 56px minmax(0, 1fr) auto; }
  .jr-lead { width: 56px; }
  .jr-lead .ring { width: 56px; height: 56px; }
  .jr-lead .ring > .ring-t { font-size: 17px; }
  /* the unit hangs partly into the title's 8px top margin, so the card grows by 10px, not
     13; board and deadline lines stay together, centred on the ring */
  .jr-lead .ring:has(> .ring-t small) { margin-bottom: 10px; }
  .jr-lead .ring:has(> .ring-t small:lang(hi)) { margin-bottom: 12px; }
  .jr.card .jr-eye { align-self: end; }
  .jr.card .jr-due, .jr.card .jr-kind { align-self: start; }
  .ring, .ring-off { width: 56px; height: 56px; }
  .ring > .ring-t { font-size: 17px; }
  /* "Today" keeps its 11px inside the bigger phone ring (the 17px above is for numbers) */
  .ring.r-today > .ring-t, .jr-lead .ring.r-today > .ring-t { font-size: 11.5px; }
  .ring.r-today > .ring-t:lang(hi), .jr-lead .ring.r-today > .ring-t:lang(hi) { font-size: 12.5px; }
  .ctl-i { grid-template-columns: 56px minmax(0, 1fr); }
  .ctl::before { left: 27px; }
  .deadlines .dr { grid-template-columns: 56px minmax(0, 1fr) auto; }
}

/* ---- the card's meta row (J15, K6: these selectors are B's). R4 at 360: four boards drew
   0px wide (app.css keeps the state and "2 h ago" at full width, so the board was the only
   thing that could give way) and 12 of 30 last dates were cut ("Last date 20…"), because the
   "This week" pill took the room. Now:
   - the board shrinks last: the state's shrink factor is 10,000 times the board's, so the
     state gives way first (down to a few letters) and a short board ("HPPSC") is never cut by
     a sub-pixel; a long board keeps all the width the state's few letters and the time ago
     leave it (the factors sum to more than 1, so the whole overflow is always taken up);
   - the last date never shrinks; the pill wraps under it on the narrowest phones;
   - a card with a ring hides "This week" (the amber ring already says it). */
/* M21 (QM F4): the state never truncates ("All In…") and never squeezes the board. The row
   is one line tall and wraps: the state (order 2) either fits whole after the board and the
   time ago or drops to the clipped second line, out of sight. The time ago keeps its place
   beside a long board, which gives way to it (the 5.8em cap) and ellipsises only then. The
   row gap pushes a wrapped line far below the clip edge, so no ascender peeks in. */
.jr.card .jr-eye { display: flex; flex-wrap: wrap; row-gap: 40px; min-width: 0; height: 1.45em; height: 1lh; overflow: clip; overflow-clip-margin: 4px; }
/* R9 (R4, P2): the board never gives way. It keeps its whole width (on phones the short
   .bd-s name, below) and the time ago and the state wrap out of sight after it instead; only
   the "New" pill in front of it caps it, so it stays on the visible line. */
.jr.card .jr-eye .jr-board { flex: 0 0 auto; max-width: 100%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jr.card .jr-eye:has(> .jr-pill-new) .jr-board { max-width: calc(100% - 4.6em); }
.jr.card .jr-eye .jr-state { order: 2; flex: none; white-space: nowrap; }
.jr.card .jr-eye .jr-new { order: 1; flex: none; white-space: nowrap; }
.jr.card .jr-dl { flex: none; min-width: auto; max-width: 100%; overflow: visible; white-space: normal; }
.jr.card:has(.jr-lead .ring) .jr-due.near .jr-left { display: none; }
@media (max-width: 380px) {
  .jr.card .jr-due { flex-wrap: wrap; row-gap: 2px; }
  /* M21 (MO F4): "Hurry" wrapped under the date once the fonts came in (a 0.006 shift at 360
     HI). Under 380px a card with a ring drops it: the red ring and "Closes today" say it */
  .jr.card:has(.jr-lead .ring) .jr-due .jr-left { display: none; }
}
.jr.card .jr-left { white-space: nowrap; }

/* ---- tear-off calendar: when forms close today there is no page to tear, so the date card
   pulses red twice as it comes into view instead (G23, motion F-J). app.js adds .go on view. */
.tear.same::after { content: ""; position: absolute; left: 0; right: 0; top: 8px; bottom: 0; z-index: 4; border-radius: var(--r); border: 2px solid var(--hot); opacity: 0; pointer-events: none; }
.tear.same.go::after { animation: tear-pulse .55s cubic-bezier(0, 0, .2, 1) .1s 2; }
@keyframes tear-pulse { 0% { opacity: .55; transform: scale(1); } 100% { opacity: 0; transform: scale(1.22); } }
/* P21 (MO F6): the pulse plays once. app.js marks the calendar .done 1.2s after .go (when the
   two pulses above have ended), and from then on nothing replays it: the density toggle's
   view transition re-rendered the list and played it again. The rings' draw-in transitions
   stay off for the whole of that transition too (removing the class starts none). */
.tear.same.go.done::after { animation: none; }
:root.vt-dens .ring circle, :root.vt-dens .tear-pg { transition: none !important; }
/* P21 (UF F7): the torn page falls a short way and is clipped just under the calendar, so it
   never crosses the heading below it (R6: a 140px fall reached "Latest jobs" at 1.5s) */
.tear { clip-path: inset(-16px -48px -20px -48px); }
@media (prefers-reduced-motion: no-preference) { .tear.go .tear-top { animation-name: tear-off-short; } }
@keyframes tear-off-short {
  0% { transform: rotate(0); }
  18% { transform: rotate(-4deg) translateY(2px); }
  100% { transform: rotateX(70deg) rotate(-12deg) translate(-18px, 64px); opacity: 0; }
}

/* ---- "N new since your last visit" (G4, motion F-F): the banner slides in once, and every new
   card glows once in the live tint, then settles. H11: the glow waits until the card is seen.
   scenes.js (home only) adds .ns-lit the first time a new card is half in view, and again
   after "Show" scrolls to them; before that the glow layer stays dark. The glow is a layer
   under the card's content (opacity only), so nothing re-lays out. */
.newsince:not([hidden]) { animation: ns-in .24s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes ns-in { from { opacity: 0; transform: translateY(-6px); } }
.jr.card.is-new { position: relative; isolation: isolate; }
.jr.card.is-new::after { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; background: var(--live-tint); opacity: 0; pointer-events: none; animation: none; }
.jr.card.is-new.ns-lit::after { animation: new-glow2 1.6s ease-out both; }
/* a 3px live edge stays on the card, so "new" is still visible after the glow fades */
.jr.card.is-new { box-shadow: inset 3px 0 0 var(--live), var(--shadow-1); }
.jr.card.is-new:hover { box-shadow: inset 3px 0 0 var(--live), var(--shadow-2); }
@keyframes new-glow2 { 0%, 25% { opacity: 1; } 100% { opacity: 0; } }

/* ---- the filter sheet leaves the way it came (H12, motion F3): it slides back down in 200ms
   on an accelerate curve while the scrim fades, instead of vanishing. The entry stays the
   280ms slide up, now as a transition from @starting-style, so in and out are one motion.
   overlay/display allow-discrete keep the closing <dialog> in the top layer until it is off
   screen. Instant under reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  .fsheet-dlg { transform: translateY(100%); transition: transform .2s cubic-bezier(.4, 0, 1, 1), overlay .2s allow-discrete, display .2s allow-discrete; }
  .fsheet-dlg[open] { transform: none; animation: none; transition-duration: .28s; transition-timing-function: cubic-bezier(.2, .8, .2, 1); }
  .fsheet-dlg::backdrop { opacity: 0; animation: none; transition: opacity .2s, overlay .2s allow-discrete, display .2s allow-discrete; }
  .fsheet-dlg[open]::backdrop { opacity: 1; }
  @starting-style {
    .fsheet-dlg[open] { transform: translateY(100%); }
    .fsheet-dlg[open]::backdrop { opacity: 0; }
  }
}

/* ---- phones: solid bars and cheap scrolling (H13). The 96% bars let the page's text show
   through as it scrolled under them, and every frame of the scroll repainted the document
   behind them. Opaque bars with a hairline edge can't show anything through. Cards no longer
   fade and slide in on a phone (each reveal was a repaint as you scrolled), and their
   rings are drawn finished. */
@media (max-width: 599px) {
  .top, header.top { background: var(--surface); box-shadow: 0 1px 0 var(--rule); }
  .tabbar { background: var(--surface); box-shadow: 0 -1px 0 var(--rule); }
  .jr.card.rv, .jr.card.rv.in { opacity: 1; translate: none; transition: border-color .18s, box-shadow .18s; }
  .rv .ring .ra, .rv.in .ring .ra { stroke-dashoffset: var(--arc); transition: none; }
  .rv .ring.r-today .ra, .rv.in .ring.r-today .ra { stroke-dashoffset: 0; }
}

/* ---- reduced motion: nothing above moves; the end states stay */
@media (prefers-reduced-motion: reduce) {
  .top, header.top, .tabs-row, .week, .sr-jump { transition: none !important; }
  .jr.card.rv { translate: none; }
  .jr.card, .jr.card:hover, .jr.card:active, .jr.card.rv.in:hover, .jr.card.rv.in:active, .sr-card:active { transform: none; }
  .newsince:not([hidden]), .tear.same.go::after, .jr.card.is-new::after, .jr.card.is-new.ns-lit::after { animation: none; }
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}
@media print {
  .jr.card.rv { translate: none; }
  .jr.card.is-new::after { display: none; }
}
/* the last date may wrap but is never cut (200% text, WCAG 1.4.4); at normal sizes it fits on one line */
.jr.card .jr-due { flex-wrap: wrap; row-gap: 2px; overflow: visible; }
.jr.card .jr-dl { white-space: nowrap; }
@media (max-width: 380px), (min-resolution: 0dppx) and (max-width: 32em) { .jr.card .jr-dl { white-space: normal; } }

/* M20 (DS F3): "closes tomorrow" is urgent too: its ring draws a short red arc (an eighth of
   the ring) instead of the 4% sliver its share of the window gives, which read as an empty
   grey ring beside a red "Closes tomorrow". The rows carry .urgent (deadline lists, hero,
   /closing); a feed card carries it on its deadline line. No draw-in, like "Today". */
.urgent .ring:not(.r-today) .ra, .rv .urgent .ring:not(.r-today) .ra, .urgent.rv.in .ring:not(.r-today) .ra,
.jr.card:has(.jr-due.urgent) .jr-lead .ring:not(.r-today) .ra { stroke: var(--hot); stroke-dashoffset: 77; transition: none; }

/* M24 (UP): compact titles on a phone take two lines, so two posts of one board
   ("Head constable (motor mechanic)" / "(education and stress counsellor)") read apart */
@media (max-width: 599px) {
  .dens-compact .feed .jr-title a { -webkit-line-clamp: 2; line-clamp: 2; }
  /* the card's 6px title gap (design.css, phones) would take a two-line row past 64px */
  .dens-compact .feed .jr.card .jr-title { margin-top: 0; }
}

/* ======== Round 9, workstream D (FIXES-R8) ======== */

/* -- R4 (P2): a card, rail or /closing board prints its full name (.bd-l, the accessible name)
   and, when it has one, a short one (.bd-s, aria-hidden: "P&H HC", "A&N Admin"). Below 400px the
   short one shows and the full one stays in the text for screen readers and search (visually
   hidden in place, 1px, so it adds nothing to the board's scroll width). */
.jr-board > .bd-s, .dr-board > .bd-s, .cw-b > .bd-s { display: none; }
@media (max-width: 399.98px) {
  .jr-board:has(> .bd-s) > .bd-l, .dr-board:has(> .bd-s) > .bd-l, .cw-b:has(> .bd-s) > .bd-l { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .jr-board > .bd-s, .dr-board > .bd-s, .cw-b > .bd-s { display: inline; }
}
.jr-board:has(> .bd-s), .dr-board:has(> .bd-s), .cw-b:has(> .bd-s) { position: relative; }
/* the grey context beside the kind chip gives way before anything else on the line */
.jr.card .jr-kind > .jr-ctx { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* -- R12: see design.css (beside the slot it fills, so both arrive in the same sheet) */

/* -- R14 (AX hs3): no sideways scroll at 200% text. A section head is a grid whose heading may
   shrink and wrap; the link wraps too and keeps to the end. With big text (html.big-text, the
   header over 90px) the link goes under the heading. The feed's own head keeps its grid. */
.sec-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; }
.sec-head > .h-sec { min-width: 0; overflow-wrap: break-word; }
.sec-link { white-space: normal; text-align: end; }
/* a module inside the feed (Closing soon after card 3) has a plain head, not the feed's
   heading · count · button grid (its link landed in a 54px middle column at 200%) */
.feed .feed-ins .sec-head { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: none; }
.feed .feed-ins .sec-head > .h-sec { grid-area: auto; }
:root.big-text .sec-head:not(.feed .sec-head), :root.big-text .feed .feed-ins .sec-head { grid-template-columns: minmax(0, 1fr); }
:root.big-text .sec-head:not(.feed .sec-head) > .sec-link, :root.big-text .feed .feed-ins .sec-head > .sec-link { justify-self: start; text-align: start; }

/* -- P6: the classes C prints and D styles (FIXES-R8 §2). No inline styles (CSP). */
/* .orig (P1, R5): the board's own words under a stand-in title, outside the heading, in their
   language, two lines at most; button.orig-more ("Show full title") opens it (.is-open /
   [data-open], set by the page's script). A card gives it, and the Hindi meta line (.hi-meta,
   R9), rows of their own between the title and the facts; empty rows take no room (row-gap 0). */
.jr.card { grid-template-areas: "lead eye bm" "lead due bm" "title title title" "orig orig orig" "more more more" "meta meta meta" "facts facts facts"; }
@media (min-width: 760px) {
  .jr.card { grid-template-areas: "lead eye due bm" "lead title title bm" "lead orig orig bm" "lead more more bm" "lead meta meta bm" "lead facts facts bm"; }
}
.jr.card > .orig-more { grid-area: more; justify-self: start; min-height: 32px; }
.orig { margin: 2px 0 0; font-size: .8125rem; line-height: 1.5; color: var(--ink-3); overflow-wrap: anywhere; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }
.orig.is-open, .orig[data-open] { display: block; -webkit-line-clamp: none; line-clamp: none; overflow: visible; }
.jr.card > .orig { grid-area: orig; padding-right: 10px; }
.orig-more { position: relative; z-index: 1; display: inline-flex; align-items: center; min-height: 44px; padding: 0; background: none; border: 0; color: var(--brand); font: inherit; font-size: .8125rem; font-weight: 600; cursor: pointer; }
.orig-more:hover { text-decoration: underline; text-underline-offset: 3px; }
.orig-more[hidden] { display: none; }
/* the row lists clamp to the one line they have */
.dr-orig.orig, .cw .orig { display: block; white-space: nowrap; text-overflow: ellipsis; }
/* .hi-meta (R9, OD77): "कांस्टेबल · 12वीं स्तर · भर्ती" under an English title on /hi: quiet,
   one line, the Devanagari face's own line height */
.hi-meta { margin: 3px 0 0; font-size: .8125rem; line-height: 1.6; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jr.card > .hi-meta { grid-area: meta; padding-right: 10px; }
.dens-compact .feed .jr.card > .orig, .dens-compact .feed .jr.card > .hi-meta { display: none; }
/* .run-more (R3): "{board} · +n more" stands for the rest of a board's run: a quiet dashed row
   the width of the list, a 44px target, never mistaken for a card */
.list > .run-more { grid-column: 1 / -1; }
.run-more > a { display: flex; align-items: center; justify-content: center; gap: 6px; min-height: 44px; padding: 6px 14px; border: 1px dashed var(--rule-2); border-radius: var(--r); color: var(--brand); font-size: .875rem; font-weight: 600; text-decoration: none; }
.run-more > a:hover { background: var(--brand-tint); text-decoration: underline; text-underline-offset: 3px; }
.run-more > a .ico { width: 16px; height: 16px; flex: none; }
.dens-compact .feed .list > .run-more > a { border: 0; border-radius: 0; }
/* .fold-n + details.fold-boards (R23): "· 21 RRBs" after the title's board, and the boards'
   own links behind a disclosure */
.fold-n { white-space: nowrap; color: var(--ink-2); font-weight: 600; }
.fold-boards { position: relative; z-index: 1; margin: 6px 0 0; font-size: .8125rem; }
.jr.card > .fold-boards { grid-column: 1 / -1; }
@media (min-width: 760px) { .jr.card > .fold-boards { grid-column: 2 / -2; } }
.fold-boards > summary { display: inline-flex; align-items: center; min-height: 44px; color: var(--brand); font-weight: 600; cursor: pointer; }
.fold-boards > summary:hover { text-decoration: underline; text-underline-offset: 3px; }
.fold-boards ul { display: flex; flex-wrap: wrap; gap: 4px 8px; margin: 0 0 4px; padding: 0; list-style: none; }
.fold-boards li > a { display: inline-flex; align-items: center; min-height: 32px; padding: 0 10px; border: 1px solid var(--rule); border-radius: var(--r-pill); color: var(--ink-2); text-decoration: none; white-space: nowrap; }
.fold-boards li > a:hover { border-color: var(--brand); color: var(--brand); }
/* .fy-div (R33): a small labelled rule before For-you's amber-chip rows */
.list > .fy-div, .fy-div { grid-column: 1 / -1; display: flex; align-items: center; gap: 10px; margin: 6px 0 0; padding: 0; color: var(--live-ink); font-size: .8125rem; font-weight: 600; list-style: none; }
.fy-div::after { content: ""; flex: 1; height: 1px; background: var(--rule-2); }

/* -- R17 (MO me8): /me and /tracking keep still while their scripts fill them in.
   /me: with a profile (html.fy-slot) the profile panel holds two blank lines the size of the
   summary app.js writes; without one, the server's "no profile" line. The counts line under
   "Tracking" ("0 exams followed · 0 notices saved") has its line kept too. */
.me-ph { display: none; min-height: 1.5em; min-height: 1lh; }
:root.fy-slot #me-profile > .me-ph { display: block; }
:root.fy-slot #me-profile > .me-none { display: none; }
:root.js #me-tracked:empty { min-height: 1.5em; min-height: 1lh; }
/* /tracking: the device footnote waits out of the flow, unseen, until a list or the empty
   card has drawn above it, then appears in its final place (it jumped 257 → 570 before) */
:root.js .track-page:not(:has(> .tgroup:not([hidden]), > #tracked-empty:not([hidden]))) > .fine { position: absolute; visibility: hidden; }

/* -- R9 (UA F1): on /hi/tracking an English notice title leads with its stage in Hindi */
.fl-latest > .fl-st { flex: none; font-weight: 600; color: var(--ink); }

/* -- R30 (DS, MO, QM): no one-word last line in short copy */
.verify-cta .vc-t, .rx-kicker, .newsince > .ns-t, .newsince > .ns-q, .sr-age-v, .sr-cy-line { text-wrap: balance; }

/* -- R34 (QD pdfchk): a printed heading stays with what it heads */
@media print {
  h2, h3, .sec-head, .day-h { break-after: avoid; page-break-after: avoid; }
  .sec-head + .list, .day-h + .list, .day-h + li { break-before: avoid; }
}

/* -- R7: separators. Text pieces join with a no-break space before " · " (series.go dotNB), so a
   line may end with a dot but never start with one; the strip note's dot keeps its left margin
   only (the break and the space follow it); the cycle card's link never splits. */
.fl-note-t > .sep { margin-inline: .32em 0; }
:root:not(.big-text) .sr-cy-line a { white-space: nowrap; }

/* ======== FX-B (round-9 review fixes) ======== */
/* QD F1: the feed's "See the forms you can fill" box has no icon cell: text | button, never the
   text squeezed into the 40px icon column (grid 40px 726px 0px at 1280-1920) */
.ins-fy .fy-setup { grid-template-columns: minmax(0, 1fr) auto; }
@media (max-width: 540px) { .ins-fy .fy-setup { grid-template-columns: 1fr; } }

/* AX F2 (R14): the exam page's eyebrow wraps at large text (390 @200% scrolled 433-595px) */
.ex-eye { flex-wrap: wrap; row-gap: 2px; }
.ex-eye .jr-board { white-space: normal; overflow-wrap: anywhere; }
.ex-eye .ex-cat, .ex-eye .jr-state { flex: 0 1 auto; min-width: 0; white-space: normal; }
/* AX F3: /hi/tracking's "जिन परीक्षाओं पर नज़र है" may wrap (16px sideways at 200%) */
.fl-hrow .h-sec { flex: 0 1 auto; min-width: 0; overflow-wrap: anywhere; }

/* MO F1: /tracking on a phone, arriving from another page, painted before follow.js: the
   aside and the footer sat under an empty list and slid 300-600px down when it drew (CLS
   0.18-0.64). Until the list (or the empty card) is drawn they keep their place unseen, so
   they appear where they end up; the hold lifts by itself after 1.5 s. (:has() cannot nest,
   so the "not drawn yet" test is a :not(:has()) on the ancestor.) */
@keyframes sr-trk-hold { to { visibility: visible; } }
@media (max-width: 819px) {
  :root.js .page-grid:has(> .track-page):not(:has(> .track-page > .tgroup:not([hidden]), > .track-page > #tracked-empty:not([hidden]))) > .page-aside,
  :root.js body:has(.track-page):not(:has(.track-page > .tgroup:not([hidden]), .track-page > #tracked-empty:not([hidden]))) .foot {
    visibility: hidden; animation: sr-trk-hold 0s 1.5s forwards;
  }
  :root.js .track-page:not(:has(> .tgroup:not([hidden]), > #tracked-empty:not([hidden]))) { min-height: 60svh; }
}

/* QM F1 (R12): the kept banner slot shows "Checking what's new…" from the first paint; the
   global [hidden] rule is !important, so this one must be too. QM F2: the English news line
   ("RRB NTPC and 2 more exams have new notices · 18 other new jobs") is held to two lines in
   the slot's 62px, so it never grows the slot (62 → 81px) */
:root.ns-slot #newsince-p[data-ns="wait"] { display: flex !important; animation: none; }
#newsince .newsince > .ns-t { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; padding-block: 0; margin-block: 4px; }

/* QD F3b, L6: the Hindi face's middot has next to no advance ("NTPC ·+14 और"): the separator
   span draws it in the system face, with its own air */
:lang(hi) .sep { font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", sans-serif; }
.fold-n { white-space: nowrap; }
.run-more .sep { margin-inline: .32em; }

/* DS F2: the hero's "Closing this week" ring has air: 56px rows, the ring inset 8px from the
   card's edge, a 44px ring (its circle drawn to the box), "Today" 5px inside the stroke */
.cw .cw-i { grid-template-columns: 44px minmax(0, 1fr) auto; min-height: 56px; padding: 6px 14px 6px 8px; }
.cw .cw-i .ring, .cw .cw-i .ring-off { width: 44px; height: 44px; margin: 0; }
.cw .cw-i .ring svg { inset: calc(44px * -3 / 28); width: calc(44px * 34 / 28); height: calc(44px * 34 / 28); }
.cw .cw-i .ring:has(> .ring-t small) { margin-bottom: 0; }

/* AX polish: a comma for screen readers inside a line (the stepper's "Notification, date not
   printed"): inline, so no space is read before it */
.sr-i { font-size: 0; line-height: 0; }

/* Quiet entrances and tactile feedback. Content is visible without JS or animation. */
@keyframes ui-arrive { from { opacity: .65; translate: 0 8px; } to { opacity: 1; translate: 0 0; } }
@media (prefers-reduced-motion: no-preference) {
 .p-latest .rx-h, .p-me .h-page, .p-exam .h-exam { animation: ui-arrive .45s ease-out both; }
 .p-latest .rx-search { animation: ui-arrive .5s .05s ease-out both; }
 .p-me .me > .panel { animation: ui-arrive .4s ease-out both; }
 .p-me .me > .panel:nth-child(2) { animation-delay: .05s; }
 .quick-state select, .quick-state-go, .p-me .panel-link { transition: border-color .18s, box-shadow .18s, background-color .18s; }
}
.quick-state select:focus-visible, .quick-state-go:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
.quick-state-go:hover { background: var(--brand-tint); border-color: var(--brand); }
@media (hover:hover) and (prefers-reduced-motion:no-preference) {
 :root:not(.dens-compact) .p-latest .jr.card:hover { transform: none; translate: 0 -2px; }
}
