/* ============================================================
   CCS Aspire prototype — app-level additions on top of
   brand.css + cascade.css (charts, modals, toasts, CRUD forms).
   ============================================================ */

/* ---------- charts ---------- */
.chart-wrap { position: relative; }
.chart-wrap svg.chart { width: 100%; height: auto; display: block; }
svg.chart .ax { font-size:14px; fill: var(--ink-muted); font-family: var(--font-body); }
svg.chart .dl { font-size:14px; font-weight: 600; fill: var(--ink-strong); font-family: var(--font-body); }
.chart-empty { padding: 22px; text-align: center; color: var(--ink-muted); font-size:15px; }
.chart-tip {
  position: fixed; display: none; z-index: 90; pointer-events: none;
  background: var(--ink-strong); color: var(--surface-raised); font-size:14px; line-height: 1.5;
  border-radius: 8px; padding: 8px 11px; max-width: 280px;
  box-shadow: 0 4px 16px rgba(31, 42, 41, .25);
}
.chart-legend { display: flex; gap: 16px; align-items: center; font-size:14px; color: var(--ink-strong); margin-top: 8px; flex-wrap: wrap; }
.chart-legend .li { display: inline-flex; align-items: center; gap: 6px; }
.chart-legend .sw { width: 14px; height: 3px; border-radius: 2px; display: inline-block; }
.chart-legend .sw.dash { background: repeating-linear-gradient(90deg, var(--ink-muted) 0 5px, transparent 5px 9px); height: 2px; }
.chart-legend .sw.dot3 { background: repeating-linear-gradient(90deg, var(--chart-1) 0 2px, transparent 2px 6px); height: 2px; }

/* ---------- modal ---------- */
#modal-root:empty { display: none; }
.modal-scrim {
  position: fixed; inset: 0; background: rgba(31, 42, 41, .45); z-index: 60;
  display: flex; align-items: flex-start; justify-content: center; padding: 6vh 20px 20px;
}
.modal {
  background: var(--surface-raised); border-radius: 14px; width: 100%; max-width: 640px;
  max-height: 86vh; display: flex; flex-direction: column;
  box-shadow: 0 18px 50px rgba(31, 42, 41, .3);
}
.modal.wide { max-width: 860px; }
.modal-head { display: flex; align-items: center; gap: 12px; padding: 18px 22px; border-bottom: 0.5px solid var(--line); }
.modal-head h2 { font-size:18px; font-weight: 700; color: var(--ink-strong); }
.modal-head .sub { font-size:14px; color: var(--ink-muted); margin-top: 2px; }
.modal-head .close { margin-inline-start: auto; background: none; border: none; cursor: pointer; color: var(--ink-muted); padding: 6px; border-radius: 8px; }
.modal-head .close:hover { background: var(--surface-page); color: var(--ink-strong); }
.modal-body { padding: 20px 22px; overflow-y: auto; }
.modal-foot { padding: 14px 22px; border-top: 0.5px solid var(--line); display: flex; gap: 10px; justify-content: flex-end; }

/* ---------- toasts ---------- */
/* Lifted clear of the language switcher, which holds the same corner. */
#toasts { position: fixed; bottom: 78px; inset-inline-end: 22px; z-index: 80; display: flex; flex-direction: column; gap: 10px; max-width: 440px; }
#toasts .alert { box-shadow: 0 8px 30px rgba(31, 42, 41, .18); background-clip: padding-box; animation: toast-in .22s ease; }
@keyframes toast-in { from { transform: translateY(8px); opacity: 0; } to { transform: none; opacity: 1; } }

/* ---------- forms / CRUD ---------- */
textarea.input { min-height: 84px; resize: vertical; line-height: 1.55; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.field .err { font-size:14px; color: var(--status-past-due); margin-top: 5px; font-weight: 600; }
.input[aria-invalid="true"], .select[aria-invalid="true"] { border-color: var(--status-past-due); }
.btn-danger { background: var(--wash-past-due); color: var(--status-past-due); border-color: var(--wash-past-due); }
.btn[disabled] { opacity: .5; cursor: not-allowed; }
.icon-btn { background: none; border: none; padding: 6px; border-radius: 7px; cursor: pointer; color: var(--ink-muted); display: inline-flex; }
.icon-btn:hover { background: var(--surface-page); color: var(--ink-strong); }
.icon-btn svg { width: 16px; height: 16px; }

/* focus visibility (screen reader / keyboard demo requirement) */
a:focus-visible, button:focus-visible, [tabindex]:focus-visible,
.input:focus-visible, .select:focus-visible, .nav-item:focus-visible {
  outline: 2px solid var(--brand); outline-offset: 2px;
}
.skip-link {
  position: absolute; inset-inline-start: -9999px; top: 10px; z-index: 100;
  background: var(--surface-raised); color: var(--brand-hover); padding: 10px 16px; border-radius: 8px;
  font-weight: 600; box-shadow: 0 4px 16px rgba(31, 42, 41, .2);
}
.skip-link:focus { inset-inline-start: 12px; }

/* In a table cell a status chip should hold one line rather than break
   mid-phrase ("BLOCKING · / OVERRIDABLE"). Outside tables chips may carry
   longer sentences and must stay free to wrap. */
table.tbl .badge { white-space: nowrap; }

/* Configuration element browser. One column of prose (the resolved value and
   the illustrative note under it) sits between a column of long element titles
   and two of status chips, and the rule above holds chips to a single line.
   Auto layout gives width to whatever refuses to fold, so the chips and the
   unbreakable element keys took it and the note rendered as a twelve-line
   ribbon two words wide while both chip columns kept whitespace they had no
   content for.

   The fix is a floor on the prose column, not a share for every column:
   declared percentages fought the width the chips genuinely need, which pushed
   the table past its card and clipped the last button. The chips claim their
   real minimum, the prose column is guaranteed a readable one, and what is
   left goes to the element name. Cells align to the top because a tall note
   was floating its own row's element name into the vertical middle, away from
   the value it names. */
table.tbl-elements thead th, table.tbl-elements tbody td { vertical-align: top; }
table.tbl-elements .el-value { font-weight: 600; color: var(--ink-strong); }
/* Above the mobile breakpoint only. Below it every .tbl is already held to
   640px and scrolls inside its card, and adding floors on top of that widens
   the table for no gain — the squeeze these floors answer is a desktop
   distribution problem, not a narrow-screen one. */
@media (min-width: 861px) {
  table.tbl-elements .el-val  { min-width: 200px; }
  table.tbl-elements .el-name { min-width: 180px; }
}
/* Two columns here carry the registry's own kebab-case identifiers as status
   chips, and the longest is 250px held to one line — wider than the prose
   column it was starving, and enough on its own to push the table past the
   card and clip the last button. The identifiers stay verbatim, because they
   are keys rather than wording we are free to shorten, so the chips fold at
   their hyphens in this table. The cap is what keeps that fold at two lines
   instead of three. */
table.tbl-elements td .badge { white-space: normal; max-width: 160px; }
table.tbl-elements .hint { margin-top: 6px; line-height: 1.5; }
table.tbl-elements .btn { white-space: nowrap; }

/* Wide content scrolls inside its card — never the page body, and never past
   the card border. Tables exceed 100% of a squeezed card (auto layout grows to
   min content width), so this must hold at every viewport width, not only the
   mobile breakpoint. */
.card { overflow-x: auto; }

/* Cards size to their content instead of stretching to the tallest sibling,
   so a short card doesn't render as a card with a hole in it. */
.grid-2, .grid-3, .grid-4 { align-items: start; }

/* ---------- misc widgets ---------- */
.kbd-hint { font-size:14px; color: var(--ink-muted); }
.two-col { display: grid; grid-template-columns: 280px 1fr; gap: 18px; align-items: start; }
.crumb-link { color: var(--brand); cursor: pointer; text-decoration: none; font-weight: 600; }
.crumb-link:hover { text-decoration: underline; }
/* Used on a <button> where the action is not navigation ("Not you?" on the sign-in
   page). Without this it inherits the UA button chrome and reads as a boxed control
   sitting inside a sentence. */
button.crumb-link { border: none; background: none; padding: 0; font: inherit; }
.empty-state { padding: 34px 20px; text-align: center; color: var(--ink-muted); font-size:15px; }
.empty-state svg { width: 30px; height: 30px; margin-bottom: 8px; color: var(--line); }
.provenance { display: inline-flex; align-items: center; gap: 4px; font-size:14px; font-weight: 600; color: var(--brand-hover); background: var(--brand-wash); border-radius: 5px; padding: 1.5px 7px; vertical-align: middle; }
.provenance svg { width: 11px; height: 11px; }
.thread { display: flex; flex-direction: column; gap: 10px; }
.bubble { max-width: 78%; border-radius: 12px; padding: 10px 14px; font-size:15px; line-height: 1.5; }
.bubble.them { background: var(--surface-page); color: var(--ink-strong); align-self: flex-start; border-bottom-left-radius: 4px; }
.bubble.me { background: var(--brand); color: var(--surface-raised); align-self: flex-end; border-bottom-right-radius: 4px; }
.bubble .meta { font-size:14px; opacity: .75; margin-top: 4px; }
.notif { display: flex; gap: 12px; padding: 13px 16px; border-bottom: 0.5px solid var(--line); align-items: flex-start; }
.notif.unread { background: var(--brand-wash); }
.notif .nicon { flex: 0 0 34px; width: 34px; height: 34px; border-radius: 9px; background: var(--surface-page); display: flex; align-items: center; justify-content: center; color: var(--brand); }
.notif .nt { font-weight: 600; font-size:15px; color: var(--ink-strong); }
.notif .nd { font-size:14px; color: var(--ink-muted); margin-top: 2px; }
.notif .nts { margin-inline-start: auto; font-size:14px; color: var(--ink-muted); white-space: nowrap; }

/* section completeness rail (guided authoring) */
.rail { display: flex; flex-direction: column; gap: 2px; }
.rail-item { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-radius: 8px; font-size:15px; font-weight: 500; color: var(--ink-strong); cursor: pointer; border: none; background: none; text-align: start; width: 100%; }
.rail-item:hover { background: var(--surface-subtle); }
.rail-item.active { background: var(--brand-wash); color: var(--brand-hover); font-weight: 600; }
.rail-item .st { flex: 0 0 18px; width: 18px; height: 18px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; }
.rail-item .st svg { width: 11px; height: 11px; }
.rail-item .st.done { background: var(--status-complete); color: var(--surface-raised); }
.rail-item .st.todo { border: 1.5px solid var(--line); }
.rail-item .st.issue { background: var(--wash-past-due); color: var(--status-past-due); border: 1px solid var(--status-past-due); }

/* ============================================================
   Sign-in
   Two screens, and they are supposed to look like two systems.

   The FRONT DOOR is CCS Aspire's own: a navy brand panel carrying
   the institution and a cream column carrying the job. It offers
   both ways in — single sign-on, which is the district's stated
   preference and keeps the filled button, and a local account,
   which is what the named evaluator logins actually are.

   The PROVIDER SCREENS are dressed as somebody else's system on
   purpose. Choosing single sign-on leaves CCS Aspire, and the
   visual break is what says so.

   Everything from .id-rule down to .foot-lines is the front door.
   Everything under "the identity provider screen" is the other.
   ============================================================ */
.app.signin-mode { display: block; background: var(--surface-page); }
.signin { min-height: 100vh; display: flex; flex-direction: column; }

/* ---- the top band: identity rule, then what this environment is ---- */
.topbar { flex: 0 0 auto; padding-top: env(safe-area-inset-top, 0px); }
/* The second of the two places CCS Red appears. Identity, never status. */
.id-rule { height: 6px; background: var(--identity); }
/* The demonstration notice: a bar across the whole top of the page, over
   everything, dropped down once per sign-in and dismissible until the next. */
.demo-bar { position: fixed; inset-block-start: 0; inset-inline: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center; gap: 12px;
  padding: calc(12px + env(safe-area-inset-top, 0px)) clamp(18px, 3vw, 34px) 12px;
  background: var(--notice); border-block-end: 1px solid var(--notice-line); color: var(--notice-ink);
  box-shadow: var(--shadow-overlay); font-size: 15px; line-height: 1.45; text-align: center; text-wrap: pretty; }
.demo-bar > svg { width: 18px; height: 18px; flex: 0 0 18px; color: var(--notice-icon); }
.demo-bar b { font-family: var(--font-display); font-weight: 600; letter-spacing: .01em; }
.demo-bar span { max-width: 110ch; }
.demo-bar:not(.can-dismiss) { padding-inline-end: clamp(18px, 3vw, 34px); }
.demo-bar-x { flex: 0 0 auto; margin-inline-start: 8px; padding: 6px 12px; border-radius: 8px; border: 1px solid var(--notice-line);
  background: transparent; color: var(--notice-ink); font: inherit; font-size: 14px; font-weight: 700; cursor: pointer; }
.demo-bar-x:hover { background: var(--notice-line); }
.demo-bar.drop { animation: demo-drop .45s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes demo-drop { from { transform: translateY(-100%); } to { transform: translateY(0); } }
@media (prefers-reduced-motion: reduce) { .demo-bar.drop { animation: none; } }
.notice { display: flex; align-items: flex-start; justify-content: center; gap: 10px;
  margin: 0; padding: 11px clamp(18px, 3vw, 34px);
  background: var(--notice); border-block-end: 1px solid var(--notice-line); color: var(--notice-ink);
  font-size: clamp(14px, 1.05vw, 15px); line-height: 1.45; text-align: center; text-wrap: pretty; }
.notice svg { width: 18px; height: 18px; flex: 0 0 18px; margin-top: 1px; color: var(--notice-icon); }
.notice b { font-family: var(--font-display); font-weight: 600; letter-spacing: .01em; }
.notice span { max-width: 110ch; }

/* ---- the two panels ----
   38/62, not 50/50: an even split puts the form's optical centre at roughly
   77% of the viewport and it reads as shoved against the right edge. */
.front-door .screen { flex: 1 1 auto; display: grid; grid-template-columns: 38fr 62fr;
  padding-bottom: env(safe-area-inset-bottom, 0px); }

.brand-panel { position: relative; overflow: hidden; color: var(--on-brand-panel);
  background: var(--brand-panel); display: grid; grid-template-rows: 1fr auto;
  padding: clamp(32px, 4vh, 54px) clamp(24px, 2.8vw, 46px); }
/* The district mark as ground texture. Decorative, and the only reason it can
   be cropped at all is that it is not being presented as the district's logo
   here — the readable lockup at the foot of the panel is. */
/* The watermark is cropped by its own box, not the panel's, so the panel can
   let the working-name sticker hang over its edge on a wide screen. */
.brand-panel .apple-clip { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.brand-panel .apple { position: absolute; inset-inline-end: -140px; inset-block-end: -160px;
  width: 500px; height: auto; opacity: .13; pointer-events: none; }
/* A two-row grid, not a flex column with margin-top:auto. The name and the
   ladder centre in the space ABOVE the district lockup rather than in the
   panel as a whole, which is what keeps the lockup from drifting. */
.brand-main { position: relative; align-self: center; display: flex; flex-direction: column; }

.brand-panel .lockup { position: relative; display: flex; align-items: center; gap: clamp(13px, 1.5vw, 20px); }
.brand-panel .lockup .brand-mark { width: clamp(54px, 5.1vw, 76px); height: auto; flex: 0 0 auto; }
.brand-panel .title { position: relative; margin: 0; font-family: var(--font-display); font-weight: 600;
  font-size: clamp(25px, 3.15vw, 43px); line-height: 1.02; letter-spacing: .06em;
  white-space: nowrap; color: var(--on-brand-panel); }
.brand-panel .title .ccs { color: var(--on-chrome-label); }
/* The third and last place CCS Red appears. */
.title-rule { position: relative; width: 84px; height: 6px; background: var(--identity);
  margin: clamp(15px, 2.2vh, 22px) 0 clamp(20px, 3.2vh, 34px); }

/* The spine is red for the same reason: it is the mark's colour holding the
   product's own name together. It carries no state. */
.ladder { position: relative; list-style: none; margin: 0; padding: 0 0 0 clamp(15px, 1.4vw, 22px);
  border-inline-start: 4px solid var(--identity);
  display: flex; flex-direction: column; gap: clamp(7px, 1.3vh, 14px); }
.ladder li { display: grid; grid-template-columns: auto 1fr; align-items: baseline;
  column-gap: clamp(12px, 1.2vw, 18px); }
.ladder .ltr { font-family: var(--font-display); font-weight: 700; font-size: clamp(25px, 2.7vw, 38px);
  line-height: 1; width: 1.05em; color: var(--on-brand-panel); }
.ladder .wd { font-family: var(--font-display); font-weight: 500; font-size: clamp(15px, 1.45vw, 21px);
  line-height: 1.2; color: var(--on-brand-panel-word); }

.brand-foot { position: relative; width: 100%; margin-top: clamp(26px, 4vh, 44px);
  padding-top: clamp(22px, 3.2vh, 36px);
  display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.brand-foot::before { content: ""; position: absolute; inset-block-start: 0; inset-inline-start: 0;
  width: 100%; height: 1px; background: var(--brand-panel-hairline); }
.brand-foot img { height: clamp(28px, 2.4vw, 34px); width: auto; }
/* No max-width in ch here. That was what made the descriptor wrap early. */
.brand-foot .org { margin: 0; font-size: clamp(14px, 1.05vw, 15px); font-weight: 400;
  letter-spacing: .005em; color: var(--on-brand-panel-subtle); line-height: 1.5; text-wrap: pretty; }

/* ---- the sign-in column ---- */
.signin-col { background: var(--surface-page); display: flex; flex-direction: column;
  justify-content: center; padding: clamp(40px, 6vh, 72px) clamp(26px, 4vw, 60px); }
.signin-col .inner { width: 100%; max-width: 404px; margin: 0 auto; }
.signin-col h1 { font-family: var(--font-display); font-size: clamp(25px, 2.6vw, 30px); font-weight: 600;
  letter-spacing: -.2px; margin: 0 0 6px; color: var(--ink-strong); white-space: nowrap; }
/* Five days of Columbus weather at the foot of the welcome page: an almanac
   line, no cards. Tokens only; the design's 12.5px and 13px are raised to the
   14px floor every screen keeps. Five columns at every width. */
.wx-almanac { margin-top: 34px; padding-top: 18px; border-top: 1px solid var(--line); }
.wx-almanac p { margin: 0 0 12px; font-size: 14.5px; line-height: 1.5; color: var(--ink-muted); }
.wx-almanac ol { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; }
.wx-almanac li { font-size: 14px; line-height: 1.35; color: var(--ink-muted); }
.wx-almanac li svg { width: 24px; height: 24px; display: block; margin: 0 0 6px; color: var(--brand); }
.wx-almanac li b { display: block; font-family: var(--font-display); font-weight: 600; font-size: 19px; line-height: 1.3; color: var(--ink-strong); font-variant-numeric: tabular-nums; }
.wx-almanac li:first-child b { color: var(--brand); }
.wx-almanac li { white-space: nowrap; }
/* On a narrow phone the low drops under the day, rather than the two running into the next column. */
@media (max-width: 420px) { .signin-col { padding-inline: 20px; } .wx-almanac .wx-sep { display: none; } .wx-almanac .wx-lo { display: block; } }
/* A tip beside a button, on hover and on keyboard focus. */
.tip-wrap { position: relative; display: inline-flex; }
.tip { position: absolute; inset-block-end: calc(100% + 8px); inset-inline-start: 0; z-index: 30; width: max-content; max-width: 300px;
  padding: 10px 12px; border-radius: 8px; background: var(--ink-strong); color: var(--surface-page);
  font-size: 14px; line-height: 1.45; box-shadow: var(--shadow-overlay); opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .15s; }
.tip-wrap:hover .tip, .tip-wrap:focus-within .tip { opacity: 1; visibility: visible; }
@media (prefers-reduced-motion: reduce) { .tip { transition: none; } }
/* The working-name note: a sticky note pinned to the brand panel, hanging straight
   down, beside the ladder on a wide panel and under it on a narrow one — near
   the title, where it is seen, rather than at the foot, where it was missed. Two
   seconds after the page opens it appears and swings gently on its pin three or
   four times before settling; with reduced motion it is simply there. Its paper,
   ink and pin are fixed tokens (--note-*), the same in every theme, as a real
   note would be. */
.about-name { position: relative; margin: 46px auto 6px; width: min(100%, 240px); padding: 26px 18px 20px;
  background: linear-gradient(170deg, var(--note-paper) 0%, var(--note-paper-deep) 100%);
  color: var(--note-ink); border-radius: 2px;
  box-shadow: 0 14px 18px -10px rgba(0,0,0,.45), 0 2px 4px rgba(0,0,0,.2);
  transform: rotate(0deg); transform-origin: 50% 0;
  animation: about-name-swing 2.6s ease-out 2s both; }
/* The push pin: a round head with a highlight, and its shadow on the paper. */
.about-name::before { content: ""; position: absolute; inset-block-start: -9px; inset-inline-start: calc(50% - 10px);
  width: 20px; height: 20px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, var(--note-pin-light) 0 18%, var(--note-pin) 45%, var(--note-pin-dark) 100%);
  box-shadow: 2px 4px 4px rgba(0,0,0,.4); }
/* The lifted bottom corner. */
.about-name::after { content: ""; position: absolute; inset-block-end: 0; inset-inline-end: 0; width: 26px; height: 26px;
  background: linear-gradient(135deg, var(--note-paper-deep) 0 50%, transparent 50%);
  box-shadow: -2px -2px 3px rgba(0,0,0,.12); }
.about-name h3 { margin: 0 0 8px; text-align: center; font-family: var(--font-display); font-size: 17px;
  font-weight: 700; line-height: 1.3; color: var(--note-ink); }
.about-name p { margin: 0; font-size: 14px; line-height: 1.5; color: var(--note-ink); }
/* Swinging on the pin: out, back, smaller each time, settling straight down. */
@keyframes about-name-swing {
  0%   { opacity: 0; transform: rotate(0deg); }
  6%   { opacity: 1; }
  14%  { transform: rotate(6deg); }
  30%  { transform: rotate(-5deg); }
  46%  { transform: rotate(3.5deg); }
  62%  { transform: rotate(-2.5deg); }
  78%  { transform: rotate(1.2deg); }
  90%  { transform: rotate(-.5deg); }
  100% { opacity: 1; transform: rotate(0deg); }
}
}
@media (min-width: 1680px) {
  /* Wide enough that the panel's right side is open beside the ladder: the note
     hangs there, level with the ladder, wholly on the navy half. Narrower, it
     hangs under the ladder instead, so it never covers a word. */
  .about-name { position: absolute; margin: 0; width: 212px; inset-block-start: 104px; inset-inline-end: 8px; }
}
@media (prefers-reduced-motion: reduce) { .about-name { animation: none; } }
/* Signing in: a spinner in the button, then one loading step. */
.signin-go[disabled] { opacity: .85; cursor: progress; }
.signin-spin { width: 16px; height: 16px; border-radius: 50%; border: 2px solid currentColor; border-inline-end-color: transparent;
  display: inline-block; animation: signin-spin .8s linear infinite; }
@keyframes signin-spin { to { transform: rotate(360deg); } }
.signin-loading { margin-top: 10px; }
.signin-loading-line { margin: 0 0 16px; font-size: 16px; line-height: 1.6; color: var(--ink-strong); }
.signin-loading-hint { margin: 12px 0 0; font-size: 14px; color: var(--ink-muted); }
.signin-progress { position: relative; height: 6px; border-radius: 999px; background: var(--surface-sunken); overflow: hidden; }
.signin-progress span { position: absolute; inset-block: 0; width: 40%; border-radius: 999px; background: var(--brand);
  animation: signin-bar 1.2s ease-in-out infinite; }
@keyframes signin-bar { from { inset-inline-start: -40%; } to { inset-inline-start: 100%; } }
@media (prefers-reduced-motion: reduce) { .signin-spin, .signin-progress span { animation: none; } .signin-progress span { width: 100%; inset-inline-start: 0; opacity: .5; } }
.signin-choose { font-family: var(--font-display); font-size: 21px; line-height: 28px; font-weight: 600; color: var(--ink-strong); margin: 2px 0 8px; }
.signin-sub { font-size: 16px; line-height: 1.6; color: var(--ink-muted); margin: 0 0 26px; text-wrap: pretty; }
.signin-go { width: 100%; justify-content: center; padding: 14px 18px; font-size: 16px; }

/* Rust, not CCS Red. A failed sign-in must never wear the colour of the
   district mark six pixels above it. */
.signin-error { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 18px; padding: 10px 12px;
  border: 1px solid var(--status-past-due); border-radius: 8px; background: var(--wash-past-due);
  font-size: 15px; line-height: 1.5; color: var(--status-past-due); }
.signin-error svg { width: 15px; height: 15px; flex: 0 0 15px; margin-top: 3px; }

.or { display: flex; align-items: center; gap: 12px; margin: 18px 0; color: var(--ink-muted);
  font-family: var(--font-display); font-size: 14px; font-weight: 500;
  letter-spacing: .08em; text-transform: uppercase; }
.or::before, .or::after { content: ""; flex: 1; height: 1px; background: var(--line); }

.signin-col form { display: flex; flex-direction: column; gap: 14px; }
.signin-col form .signin-go { margin-top: 4px; }
.foot-lines { margin-top: 28px; display: flex; flex-direction: column; align-items: flex-start; gap: 12px;
  font-size: 15px; color: var(--ink-muted); }
.foot-lines p { margin: 0; }
/* The workspace line sits with the other footer notes rather than beside the
   sign-in controls: it reports a state, it is not a thing to do next. Its button
   wraps under the sentence on a narrow column instead of squeezing the text. */
.workspace-line { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px; }

@media (max-width: 960px) {
  /* The brand panel stacks above the sign-in and the role list, as the
     2026-09-25 homepage design has it (.docs/screens, "About the name"). */
  .front-door .screen { grid-template-columns: 1fr; }
  .brand-panel { order: 1; padding-block: 44px 48px; }
  .brand-panel .apple { width: 320px; inset-inline-end: -100px; inset-block-end: -120px; }
  .signin-col { order: 2; padding-block: 56px 40px; }
  .brand-panel .title { font-size: clamp(28px, 5.4vw, 44px); white-space: normal; }
  .ladder .ltr { font-size: clamp(28px, 5vw, 36px); }
  .ladder .wd { font-size: clamp(16px, 2.6vw, 20px); }
}
@media (max-width: 520px) { .ladder { padding-inline-start: 14px; } }

/* ---- the provider screens keep the centred card ---- */
.signin-stack { flex: 1 1 auto; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 18px; padding: 32px 20px; }
.signin-card { width: 100%; max-width: 468px; background: var(--surface-raised); border-radius: var(--radius-md);
  box-shadow: 0 12px 32px rgba(0,0,0,.24); padding: 30px 28px 24px; }
.signin-card h1 { font-size: 22px; font-weight: 700; letter-spacing: -.3px; color: var(--ink-strong); }

.signin-list { list-style: none; display: flex; flex-direction: column; gap: 6px; margin: 6px 0 4px; }
.signin-id { width: 100%; display: flex; align-items: center; gap: 12px; padding: 10px 12px;
  border: 0.5px solid var(--line); border-radius: 10px; background: var(--surface-raised); cursor: pointer; text-align: start; }
.signin-id:hover { background: var(--brand-wash); border-color: var(--brand); }
.signin-id > svg { width: 16px; height: 16px; margin-inline-start: auto; color: var(--ink-muted); flex: 0 0 16px; }
.signin-who { min-width: 0; }
.signin-who b { display: block; font-size:15px; font-weight: 600; color: var(--ink-strong); }
.signin-who small { display: block; font-size:14px; color: var(--ink-muted); margin-top: 1px; }
.signin-back { margin-top: 10px; border: none; background: none; cursor: pointer; display: inline-flex;
  align-items: center; gap: 6px; font-size:14px; font-weight: 600; color: var(--brand-hover); padding: 4px 0; }
.signin-back svg { width: 14px; height: 14px; }

.signin-foot { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; justify-content: center;
  font-size:14px; color: var(--on-chrome-muted); }

/* ---- the identity provider screen ----
   Reads as a different system on purpose. The credential is entered at the
   provider, not in CCS Aspire, and the visual break is what says so. */
.signin.idp-mode { background: var(--chrome-alt); }
.idp-card { border-top: 3px solid var(--brand-hover); }
.idp-brand { display: flex; align-items: center; gap: 11px; margin-bottom: 22px;
  padding-bottom: 16px; border-bottom: 0.5px solid var(--line); }
.idp-seal { width: 34px; height: 34px; flex: 0 0 34px; border-radius: 8px; display: inline-flex;
  align-items: center; justify-content: center; background: var(--brand-hover); }
.idp-seal svg { width: 17px; height: 17px; color: var(--surface-raised); }
.idp-brand .name { font-weight: 700; font-size:16px; letter-spacing: -.2px; color: var(--ink-strong); line-height: 1.25; }
.idp-brand .name small { display: block; font-weight: 500; font-size:14px; color: var(--ink-muted); letter-spacing: 0; }
.idp-card form { display: flex; flex-direction: column; gap: 14px; }
.idp-card form .signin-go { margin-top: 4px; }

.idp-error { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 16px; padding: 10px 12px;
  border: 0.5px solid var(--status-past-due); border-radius: 8px; background: var(--wash-past-due);
  font-size:14px; line-height: 1.5; color: var(--status-past-due); }
.idp-error svg { width: 15px; height: 15px; flex: 0 0 15px; margin-top: 1px; }

/* Organization identity. Initials in a flat teal square — no per-tenant colour,
   and deliberately not a seal: this product is not endorsed by any of them. */
.org-mark { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  min-width: 26px; height: 26px; padding: 0 5px; border-radius: 6px; background: var(--brand-wash);
  border: 0.5px solid var(--brand); color: var(--brand);
  font-size:14px; font-weight: 700; letter-spacing: .02em; }
.org-mark.lg { min-width: 38px; height: 38px; padding: 0 8px; border-radius: 9px; font-size:15px; }

.org-recognized { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; padding: 12px 14px;
  border: 0.5px solid var(--line); border-radius: 10px; background: var(--surface-subtle); }
.org-recognized b { display: block; font-size:15px; font-weight: 700; color: var(--ink-strong); line-height: 1.3; }
.org-recognized small { display: block; font-size:14px; color: var(--ink-muted); margin-top: 2px; }

.signin-org { margin-inline-start: auto; padding-inline-start: 10px; font-size:14px; color: var(--ink-muted); white-space: nowrap; }
.mb-org { display: flex; align-items: center; gap: 9px; padding: 8px 12px 10px;
  border-bottom: 0.5px solid var(--line); font-size:14px; font-weight: 600; color: var(--ink-strong); }

.idp-accounts { margin-top: 18px; padding-top: 14px; border-top: 0.5px solid var(--line); }
.idp-accounts > summary { cursor: pointer; font-size:14px; font-weight: 600; color: var(--brand-hover); }
.idp-accounts .signin-who small { font-variant-numeric: tabular-nums; }
.idp-accounts-note { font-size:14px; line-height: 1.55; color: var(--ink-muted); margin-top: 8px; }

/* The rail's corner: Switch role, then the account behind the name. Chrome
   tokens only — smoke-brand.js measures every one of them against the rail. */
.sidebar .side-foot { flex-direction: column; align-items: stretch; gap: 6px; }
.side-switch { display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 12px; border-radius: 8px;
  border: 1px solid var(--chrome-hairline); background: var(--chrome-hover); color: var(--on-chrome);
  font: inherit; font-size: 15px; font-weight: 600; cursor: pointer; text-align: start; }
.side-switch:hover { background: var(--chrome-hover-strong); }
.side-switch svg { width: 18px; height: 18px; flex: 0 0 18px; }
.side-acct > summary { list-style: none; }
.side-acct > summary::-webkit-details-marker { display: none; }
.side-who { display: flex; align-items: center; gap: 10px; padding: 6px 4px; border-radius: 8px; cursor: pointer; color: var(--on-chrome); }
.side-who:hover { background: var(--chrome-hover); }
.side-who > svg { width: 16px; height: 16px; margin-inline-start: auto; flex: 0 0 16px; color: var(--on-chrome-subtle); }
.side-acct[open] .side-who > svg { transform: rotate(180deg); }
.side-acct-body { padding: 8px 4px 2px; display: flex; flex-direction: column; gap: 8px; }
.side-acct-line { margin: 0; font-size: 14px; line-height: 1.45; color: var(--on-chrome-subtle); word-break: break-word; }
.side-acct-line b { color: var(--on-chrome); font-weight: 600; }
.side-acct-btn { display: flex; align-items: center; gap: 8px; padding: 7px 10px; border-radius: 8px; border: none;
  background: var(--chrome-hover); color: var(--on-chrome-muted); font: inherit; font-size: 14px; cursor: pointer; text-align: start; }
.side-acct-btn:hover { background: var(--chrome-hover-strong); color: var(--on-chrome); }
.side-acct-btn svg { width: 15px; height: 15px; }
.side-switch:focus-visible, .side-who:focus-visible, .side-acct-btn:focus-visible { outline: 2px solid var(--on-chrome-label); outline-offset: 2px; }

/* ============================================================
   Small-screen chrome
   The family portal's anchor screen is phone width, and the demo is
   given on a handset. Below 860px the fixed staff sidebar is replaced
   by an app bar + drawer, and the portal gets a real bottom tab bar.
   ============================================================ */
.mobile-bar { display: none; }
.tabbar { display: none; }

@media (max-width: 860px) {
  .app { flex-direction: column; min-height: 100vh; }
  .sidebar { display: none; }
  .topbar { display: none; }
  .main { min-width: 0; }

  .mobile-bar {
    display: flex; align-items: center; gap: 10px;
    background: var(--chrome); color: var(--on-chrome);
    padding: 10px 14px; position: sticky; top: 0; z-index: 40;
  }
  .mb-mark { width: 26px; height: 26px; flex: 0 0 26px; display: flex;
    border-radius: 6px; }
  .mb-mark:focus-visible { outline: 2px solid var(--on-chrome); outline-offset: 3px; }
  .mb-title { font-weight: 600; font-size:16px; letter-spacing: -.2px; flex: 1; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mb-menu > summary {
    list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; border-radius: 9px; background: var(--chrome-hover); color: var(--on-chrome);
  }
  .mb-menu > summary::-webkit-details-marker { display: none; }
  .mb-menu > summary svg { width: 20px; height: 20px; }
  .mb-drawer {
    position: absolute; inset-inline-end: 10px; top: 58px; width: min(300px, calc(100vw - 20px));
    background: var(--chrome); border-radius: 12px; padding: 10px;
    box-shadow: 0 18px 46px rgba(0,0,0,.4); max-height: 74vh; overflow-y: auto;
  }
  .mb-drawer .nav-item { color: var(--on-chrome-muted); }
  .mb-drawer .nav-item.active { background: var(--on-chrome); color: var(--chrome); }

  /* one column everywhere */
  .content { padding: 16px 14px; }
  .content.narrow { max-width: 100%; }
  .grid-2, .grid-3, .grid-4, .two-col, .field-row, .radio-cards { grid-template-columns: 1fr; }
  .page-head { flex-direction: column; align-items: stretch; gap: 12px; }
  .page-head .actions { margin-left: 0; flex-wrap: wrap; }
  .card-head { flex-wrap: wrap; }
  .card-head .actions { margin-left: 0; width: 100%; flex-wrap: wrap; }

  /* Tables keep a comfortable min-width and are swiped inside their card
     (base .card overflow-x rule), rather than crushing every column to one
     word per line. */
  table.tbl { min-width: 640px; }
  .stepper { min-width: 420px; }

  #toasts { left: 12px; right: 12px; bottom: 12px; max-width: none; }
  .modal-scrim { padding: 0; align-items: flex-end; }
  .modal { max-width: none; border-radius: 16px 16px 0 0; max-height: 92vh; }

  .portal-body { padding: 0; }
}

/* Portal bottom tab bar — thumb-reachable, five targets, 44px minimum */
@media (max-width: 860px) {
  .tabbar {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 45;
    background: var(--surface-raised); border-top: 0.5px solid var(--line);
    padding-bottom: env(safe-area-inset-bottom, 0);
    box-shadow: 0 -2px 14px rgba(31,42,41,.06);
  }
  .tab-item {
    flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 3px; padding: 8px 2px 9px; min-height: 52px; text-decoration: none;
    color: var(--ink-muted); font-size:14px; font-weight: 600; text-align: center; line-height: 1.2;
  }
  .tab-item svg { width: 20px; height: 20px; }
  .tab-item.on { color: var(--brand); }
  .tab-item.on svg { stroke-width: 2.1; }
  main.content { padding-bottom: 74px; }
}

/* ---------- print ----------
   A printed page is read away from the system, most often by a family without
   reliable internet, so it has to carry its own identity: whose record, which
   document, whether it is a draft, who produced it and when. Everything that
   only makes sense with a mouse comes off. */
.print-only { display: none; }

@media print {
  .sidebar, .topbar, .mobile-bar, .tabbar, .lang-switch, .fb-tab, .fb-panel, .fb-pick, #toasts, #modal-root { display: none !important; }
  .no-print, .btn, .actions, .stat-go, .page-head .actions { display: none !important; }
  /* Buttons are hidden above, but a link that is genuinely the content — a
     student name in a table — must stay legible and stop pretending to be a
     link on paper. */
  a { color: inherit !important; text-decoration: none !important; }

  html, body { background: #fff !important; }
  main.content { padding: 0 !important; margin: 0 !important; max-width: none !important; }
  .app, .shell { display: block !important; }

  .print-only { display: block; }

  /* One route can hold more than one printable artifact — the IEP and its edit
     history are on the same page. Each declares itself with data-print, and a
     print control names the one it wants. When a control has named one, nothing
     else prints; a plain browser print with nothing named still produces
     everything printable on the route, which is the sensible default. */
  html.printing-scoped [data-print] { display: none !important; }
  html.printing-scoped [data-print].print-target { display: block !important; }

  .print-head { margin: 0 0 14pt; padding-bottom: 8pt; border-bottom: 1.5pt solid #000; }
  /* 10mm is the mark's minimum printed size for the full form. Clear space is one
     satellite diameter, 20% of the width, so the 2.5mm gap to the brand line is
     the minimum and not a guess. */
  .print-ident { display: flex; align-items: center; gap: 2.5mm; }
  .print-mark { width: 10mm; height: 10mm; flex: 0 0 10mm; }
  .print-brand { font-size: 8pt; letter-spacing: .09em; text-transform: uppercase; color: #333; }
  .print-head h1 { font-size: 16pt; margin: 3pt 0 0; }
  .print-sub { font-size: 10pt; color: #333; margin-top: 2pt; }
  /* The draft-versus-signed statement is the one thing on the page that must not
     be missed, so it is boxed rather than set as another line of prose. */
  .print-status { margin-top: 6pt; padding: 4pt 6pt; border: 1pt solid #000; font-size: 9.5pt; font-weight: 700; }
  .print-status.ok { border-color: #05603A; color: #05603A; }
  .print-status.bad { border-color: #B42318; color: #B42318; }
  .print-meta { margin-top: 7pt; font-size: 8.5pt; display: grid; grid-template-columns: 1fr 1fr; gap: 1pt 18pt; }
  .print-meta .pk { color: #555; margin-right: 5pt; }
  .print-meta .pv { font-weight: 600; }

  /* Cards become plain blocks; a card that breaks across a page is fine, a
     heading orphaned from its table is not. */
  .card { border: none !important; box-shadow: none !important; margin: 0 0 12pt !important;
          break-inside: auto; page-break-inside: auto; }
  .card-head { padding: 0 0 4pt !important; border-bottom: .5pt solid #999 !important;
               break-after: avoid; page-break-after: avoid; }
  .card-body { padding: 6pt 0 0 !important; }
  h1, h2, h3 { break-after: avoid; page-break-after: avoid; }
  table { break-inside: auto; page-break-inside: auto; width: 100% !important; }
  thead { display: table-header-group; }          /* repeat headers across pages */
  tr, .stat { break-inside: avoid; page-break-inside: avoid; }
  .tbl th, .tbl td { font-size: 9pt !important; padding: 3pt 4pt !important; }

  /* details are forced open by the print action, so the summary would otherwise
     print as a stray "View as table" line above the table it opened. */
  details > summary { display: none !important; }
  details[open] { display: block !important; }

  svg { max-width: 100% !important; height: auto !important; }
  .grid, .grid-2, .grid-3, .grid-4 { display: block !important; }
  .alert { border: .5pt solid #999 !important; background: #fff !important; padding: 4pt 6pt !important;
           font-size: 9pt !important; }

  /* Signature space. A participants list on paper is something people sign, and
     a printed page with nowhere to sign sends everyone back to a paper form. */
  .print-signatures { display: block; margin-top: 10pt; break-inside: avoid; page-break-inside: avoid; }
  .print-signatures .sigrow { display: grid; grid-template-columns: 1fr 150pt; gap: 22pt; margin-top: 16pt; }
  .print-signatures .sigline { border-bottom: .75pt solid #000; height: 20pt; }
  .print-signatures .siglabel { font-size: 8pt; color: #333; margin-top: 2pt; }

  @page { margin: 14mm 13mm; }
}
