/* Classroom. Layered on top of site.css, same palette and fonts.
   The marketing site is light with dark bands. The classroom is dark by
   default: it is a workspace people sit in rather than a page they skim, the
   lesson content VE wrote is itself dark green and gold, and a light chrome
   around dark content looks like a mistake. */

.cr{background:var(--near-2);color:#fff;padding-bottom:0}
.cr h1{color:#fff;font-size:var(--step-4);text-wrap:balance}
/* site.css defaults the italic accent to GREEN, which is right on the marketing
   site's light sections and unreadable here: the classroom chrome is near-black
   and green on it measures about 2:1. The site's own rule is amber on dark, and
   the classroom is dark, so it takes the dark variant. */
.cr em.accent{color:var(--amber)}
/* SAME BUG, SECOND COMPONENT, found 2026-08-24 the first time the local gate
   could actually run. site.css gives .btn--ghost dark ink on transparent, and
   flips it to white only under an `.on-dark` ancestor. The classroom chrome is
   dark WITHOUT that class, so the lesson page's "Previous" button rendered dark
   ink on near-black at 1.44:1: on the page, in the tab order, and invisible.
   The classroom is dark, so it takes site.css's dark variant, exactly like the
   accent above. Any other site.css component borrowed into .cr needs the same
   check, because nothing about it looks wrong in the source. */
.cr .btn--ghost{border-color:rgba(255,255,255,.4);color:#fff}
.cr .btn--ghost:hover{border-color:#fff;background:rgba(255,255,255,.1);color:#fff}
.cr h2{color:#fff}
.cr .container{max-width:1080px}
.cr-lede{font-size:var(--step-1);color:rgba(255,255,255,.78);max-width:60ch;margin-top:16px}
.cr .eyebrow{color:var(--amber-lift);background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.18)}
.cr .note{background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.16);color:rgba(255,255,255,.75)}

/* --- top bar ------------------------------------------------------------ */
.cr-bar{position:sticky;top:0;z-index:50;background:rgba(18,32,25,.94);
  backdrop-filter:saturate(140%) blur(12px);border-bottom:1px solid rgba(255,255,255,.12)}
.cr-bar__in{max-width:1080px;margin-inline:auto;padding:0 24px;min-height:66px;
  display:flex;align-items:center;gap:14px}
.cr-bar__in--wide{max-width:1400px}
.cr-bar .brand img{height:34px;width:auto}
.cr-bar__tag{font-size:.68rem;font-weight:700;letter-spacing:.18em;text-transform:uppercase;
  color:var(--amber);border:1px solid rgba(234,165,30,.4);border-radius:999px;padding:5px 11px}
.cr-bar__right{margin-left:auto;display:flex;align-items:center;gap:14px}
.cr-bar__who{font-size:.9rem;color:rgba(255,255,255,.72)}
.cr-signout{background:transparent;border:1px solid rgba(255,255,255,.42);color:#fff;
  font:inherit;font-size:.86rem;font-weight:600;padding:9px 15px;border-radius:999px;cursor:pointer;min-height:40px}
.cr-signout:hover{background:rgba(255,255,255,.1)}

/* --- login -------------------------------------------------------------- */
.cr--login{display:flex;flex-direction:column;min-height:100vh}
.cr-login{flex:1;display:grid;place-items:center;padding:48px 20px}
.cr-login__card{width:100%;max-width:440px;background:rgba(255,255,255,.05);
  border:1px solid rgba(255,255,255,.14);border-radius:var(--radius);padding:36px 32px}
.cr-login__card h1{font-size:var(--step-3);margin-bottom:10px}
.cr-login__sub{color:rgba(255,255,255,.72);font-size:.96rem;margin-bottom:26px}
.cr-login .field label{color:#fff}
.cr-login .field input{background:rgba(0,0,0,.28);border-color:rgba(255,255,255,.22);color:#fff}
.cr-login .field input:focus{border-color:var(--amber);box-shadow:0 0 0 3px rgba(234,165,30,.22)}
.cr-login__help{margin-top:20px;font-size:.85rem;color:rgba(255,255,255,.62);text-align:center}
.cr-login__help a{color:var(--amber-lift)}
.cr-login__hint{margin-top:6px;font-size:.8rem;color:rgba(255,255,255,.62)}
.cr .formstatus{min-height:0;padding:0;margin:0 0 14px}
.cr .formstatus--err{display:block;background:transparent;color:#F0A08A;font-weight:600;font-size:.9rem;padding:0}

/* --- project cards ------------------------------------------------------ */
/* Teachable's catalogue leads with the cover art VE had made for every
   project, dark green and gold with the address and the trade on it. Ours had
   no image at all, so seven real jobsites read as seven paragraphs. The art is
   theirs and is already public on their own /p/ pages; it is served static
   here because a cover is marketing, not a contract, and everything actually
   private still goes through the gated asset route. */
.cr-grid{display:grid;gap:20px;grid-template-columns:repeat(auto-fill,minmax(min(100%,320px),1fr));margin-top:34px}
.cr-card{display:flex;flex-direction:column;text-decoration:none;background:rgba(255,255,255,.05);
  border:1px solid rgba(255,255,255,.14);border-radius:var(--radius);overflow:hidden;
  transition:border-color .18s ease,transform .18s ease}
.cr-card:hover{border-color:var(--amber);transform:translateY(-2px)}
.cr-card__cover{display:block;aspect-ratio:720/468;background:#0E1C14;overflow:hidden}
/* CONTAIN, not cover. These are designed cards with the address set in type
   across them, and the set is two different aspect ratios (1280x720 and
   812x528). Cropping to fill ate the first character of every title: "80 SHORE
   DRIVE" rendered as "0 SHORE DRIVE". Letterboxing against the card's own
   green loses nothing and reads as intentional. */
.cr-card__cover img{width:100%;height:100%;object-fit:contain;display:block}
.cr-card__cover--none{background:linear-gradient(135deg,#12261B,#0B1711)}
.cr-card__body{display:flex;flex-direction:column;flex:1;padding:22px 22px 24px}
.cr-card h2{font-size:1.3rem;margin-bottom:8px;line-height:1.2}
.cr-card p{color:rgba(255,255,255,.7);font-size:.92rem;margin:0 0 18px}
/* The meter and its count are pinned to the bottom so a short blurb and a long
   one still line their progress up across a row. */
.cr-card__foot{display:block;margin-top:auto}
.cr-card__meta{display:block;font-size:.82rem;color:rgba(255,255,255,.6);margin:10px 0 0}
.cr-meter{display:block;height:6px;border-radius:999px;background:rgba(255,255,255,.14);overflow:hidden}
.cr-meter span{display:block;height:100%;background:var(--amber);border-radius:999px}
.cr-meter--lg{height:9px;margin:22px 0 0;max-width:520px}

/* --- project page ------------------------------------------------------- */
.cr-back{display:inline-block;font-size:.86rem;font-weight:600;color:var(--p-dim);
  text-decoration:none;margin-bottom:16px}
.cr-back:hover{text-decoration:underline;color:var(--p-text)}
.cr-back::before{content:"\2190  "}
.cr-phase{margin-top:44px}
.cr-phase h2{font-size:1.1rem;font-family:var(--sans);font-weight:600;letter-spacing:-.005em;
  display:flex;align-items:center;gap:14px;padding-bottom:12px;border-bottom:1px solid rgba(255,255,255,.14)}
.cr-phase__n{font-family:var(--serif);font-size:.95rem;color:var(--amber);
  border:1px solid rgba(234,165,30,.4);border-radius:999px;padding:3px 10px}
.cr-lessons{list-style:none;margin:0;padding:0}
.cr-lesson a{display:flex;align-items:center;gap:14px;padding:14px 8px;text-decoration:none;
  color:rgba(255,255,255,.9);border-bottom:1px solid rgba(255,255,255,.08);font-size:.98rem}
.cr-lesson a:hover{background:rgba(255,255,255,.05);color:#fff}
.cr-lesson__name{flex:1}
.cr-lesson__len{font-size:.8rem;color:rgba(255,255,255,.5)}
.cr-lesson--empty a{color:rgba(255,255,255,.42)}
.cr-tag{font-size:.7rem;letter-spacing:.06em;text-transform:uppercase;color:rgba(255,255,255,.5);
  border:1px dashed rgba(255,255,255,.24);border-radius:999px;padding:3px 9px}
.cr-tick{width:19px;height:19px;border-radius:50%;border:1.5px solid rgba(255,255,255,.3);flex:none}
.cr-tick--on{background:var(--amber);border-color:var(--amber);position:relative}
.cr-tick--on::after{content:"\2713";position:absolute;inset:0;display:grid;place-items:center;
  color:#231A05;font-size:.7rem;font-weight:900}
/* Content-type icon, straight off Teachable's curriculum rows. It answers
   "is the next thing a video, a set of plans, or reading?" before a tap. */
.cr-kind{flex:none;display:grid;place-items:center;width:20px;height:20px;color:rgba(255,255,255,.46)}
.cr-kind svg{width:17px;height:17px;fill:currentColor}
.cr-kind svg .o{fill:none;stroke:currentColor;stroke-width:1.4}
.cr-kind svg .s{fill:none;stroke:currentColor;stroke-width:1.4;stroke-linecap:round}
.cr-kind--video{color:var(--amber-lift)}
.cr-lesson a:hover .cr-kind{color:rgba(255,255,255,.75)}

/* --- lesson ------------------------------------------------------------- */
/* THE CURRICULUM STAYS ON SCREEN. Measured off Teachable's own player, which
   holds a 350px sidebar beside the lesson for its whole length: where you are,
   what is done, and what is next, without going back a page. Ours had a back
   link and a Next button at the bottom of a long scroll, so the shape of the
   project was invisible from inside it. */
.cr-shell{display:flex;align-items:flex-start;gap:0;max-width:1400px;margin-inline:auto}

.cr-side{flex:0 0 340px;width:340px;position:sticky;top:66px;align-self:flex-start;
  max-height:calc(100vh - 66px);overflow-y:auto;overscroll-behavior:contain;
  border-right:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.02);
  padding:22px 20px 40px}
.cr-side__head{padding-bottom:18px;border-bottom:1px solid rgba(255,255,255,.12)}
.cr-side__head .cr-back{margin-bottom:12px}
.cr-side__head .cr-card__meta{margin-top:8px}
.cr-side .cr-phase{margin-top:26px}
.cr-side .cr-phase h2{font-size:.82rem;letter-spacing:.04em;gap:10px;padding-bottom:9px}
.cr-side .cr-phase__n{font-size:.72rem;padding:2px 8px}
.cr-side .cr-lesson a{padding:11px 6px;font-size:.88rem;gap:11px;align-items:flex-start}
.cr-side .cr-tick,.cr-side .cr-kind{margin-top:1px}
.cr-side .cr-lesson__len{font-size:.72rem;white-space:nowrap}
/* The row you are reading. Teachable fills it solid; on this palette a solid
   amber row under white text fails contrast, so it is an amber rail and a lift
   instead, which reads as "you are here" at a glance and stays legible. */
.cr-lesson--current > a{background:rgba(234,165,30,.13);color:#fff;
  box-shadow:inset 3px 0 0 var(--amber);border-radius:0 6px 6px 0}
.cr-lesson--current .cr-lesson__name{font-weight:600}
.cr-lesson--current .cr-kind{color:var(--amber)}
/* The current row's amber lift raises the backdrop luminance, and the muted
   runtime measured 4.39:1 on it against a 4.5 floor. Caught by the gate on the
   run that introduced the row, not after a deploy. */
.cr-lesson--current .cr-lesson__len{color:rgba(255,255,255,.72)}

.cr-main{flex:1;min-width:0;padding:34px 40px 70px;
  /* CONTAINMENT, AND IT IS LOAD BEARING. 110 of 259 lessons carry a
     position:fixed "Ask VEX" launcher at z-index 9999, and every VE block is
     width:96vw with a negative margin to break out of its container. overflow
     alone contains neither: fixed escapes it, and 96vw resolves against the
     viewport, so both used to sail over the page furniture. `contain` makes
     this column the containing block for fixed descendants and clips the
     bleed, so their CSS stays inside the lesson where it belongs. */
  contain:layout paint;position:relative}
.cr-lessonpage__head{padding-top:0}
.cr-lessonpage__phase{font-size:.72rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
  color:var(--amber-lift);margin:0 0 8px}
.cr--lesson h1{font-size:var(--step-3)}
/* VE's lesson HTML brings its own full width layout and its own dark palette.
   It is contained rather than restyled: overriding their CSS from out here
   would be a fight we would lose on 163 different blocks. */
.cr-body{margin-top:28px;overflow-x:hidden}
.cr-block{width:100%}
/* NEUTRALISE THE FULL-BLEED BREAKOUT. VE's own wrapper is
   `width:96vw; max-width:1600px; margin-left:calc(-48vw + 50%)`, on 121 of the
   lesson blocks. That is a deliberate escape from whatever container it is in,
   written for a page where the lesson was the only thing on screen. Beside a
   340px sidebar it computes 160px wider than the column on each side, and
   `contain` then CLIPS it, which is the wrong kind of fixed: nothing overflows
   the page and the edges of their panels are quietly cut off. Overriding the
   three properties on their own class makes the bleed a no-op instead, so the
   block is exactly the column and nothing is lost.
   92vw and 99vw appear on inner elements too, so the rule is by width, not by
   class alone. */
.cr-body .ve5,.cr-body .ve-breakout,.cr-body .ve-module-wrap{
  width:100%!important;max-width:100%!important;margin-left:0!important;margin-right:0!important}
.cr-body [style*="vw"]{max-width:100%!important}
.cr-media{margin:26px auto;max-width:1000px}
.cr-media video,.cr-media img{width:100%;border-radius:var(--radius);background:#000;display:block}
.cr-media figcaption{font-size:.85rem;color:rgba(255,255,255,.6);margin-top:10px}
.cr-doc{display:flex;align-items:center;gap:16px;text-decoration:none;color:#fff;
  background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.16);
  border-radius:var(--radius);padding:18px 20px}
.cr-doc:hover{border-color:var(--amber);color:#fff}
.cr-doc__ico{font-size:.7rem;font-weight:800;letter-spacing:.06em;background:var(--amber);
  color:#231A05;border-radius:6px;padding:8px 10px;flex:none}
.cr-lessonfoot{display:flex;flex-wrap:wrap;gap:14px;align-items:center;justify-content:space-between;
  padding-top:30px;margin-top:40px;border-top:1px solid rgba(255,255,255,.14)}
.cr-defects{margin:0 0 24px;padding:16px 20px;
  background:rgba(192,86,47,.14);border:1px solid rgba(240,160,138,.4);border-radius:var(--radius)}
.cr-defects__h{font-size:.8rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:#F0A08A;margin:0 0 8px}
.cr-defects ul{margin:0;padding-left:20px}
.cr-defects li{font-size:.88rem;color:rgba(255,255,255,.82);margin-bottom:4px}

/* --- complete and continue ---------------------------------------------- */
/* ONE action, Teachable's, in the bar AND at the foot. Marking done and moving
   on were two separate buttons at the bottom of a long page: two taps for the
   thing every lesson ends in, and a scroll to reach either. */
.cr-cta{display:inline-flex;align-items:center;gap:9px;font:inherit;font-size:.92rem;font-weight:700;
  background:var(--amber);color:#231A05;border:1px solid var(--amber);border-radius:999px;
  padding:10px 18px;cursor:pointer;min-height:42px;white-space:nowrap;
  transition:background .15s ease,border-color .15s ease}
.cr-cta:hover{background:var(--amber-lift);border-color:var(--amber-lift)}
.cr-cta--done{background:transparent;color:#fff;border-color:rgba(255,255,255,.42)}
.cr-cta--done:hover{background:rgba(255,255,255,.1)}
.cr-cta[disabled]{opacity:.6;cursor:default}
.cr-cta__chev{font-size:1.15em;line-height:1;margin-top:-2px}
.cr-lessonfoot .cr-cta{margin-left:auto}

/* --- the sidebar on a phone --------------------------------------------- */
/* Teachable collapses the same sidebar behind a list icon in the bar at narrow
   widths. Same idea, as a slide-over, because 340px of curriculum on a 390px
   screen is the whole screen. */
.cr-sidetoggle{display:none;background:transparent;border:1px solid rgba(255,255,255,.28);
  border-radius:10px;width:40px;height:40px;cursor:pointer;padding:0;place-items:center}
.cr-sidetoggle span,.cr-sidetoggle span::before,.cr-sidetoggle span::after{
  display:block;width:16px;height:2px;background:#fff;border-radius:2px;content:""}
.cr-sidetoggle span{position:relative}
.cr-sidetoggle span::before{position:absolute;top:-5px}
.cr-sidetoggle span::after{position:absolute;top:5px}
/* [hidden] must beat the media query below, which turns the scrim on. */
.cr-side__scrim,.cr-side__scrim[hidden]{display:none}

@media (max-width:1040px){
  .cr-sidetoggle{display:grid}
  .cr-side{position:fixed;top:0;left:0;bottom:0;width:min(88vw,340px);max-height:none;z-index:60;
    background:var(--near-2);padding-top:78px;transform:translateX(-101%);
    transition:transform .22s ease;border-right:1px solid rgba(255,255,255,.16)}
  .cr-side.is-open{transform:none}
  .cr-side__scrim{display:block;position:fixed;inset:0;z-index:55;background:rgba(0,0,0,.6)}
  .cr-main{padding:26px 22px 60px}
}

@media (max-width:760px){
  .cr-bar__in{padding:0 14px;min-height:58px;gap:10px}
  .cr-bar__tag{display:none}
  .cr-bar__who{display:none}
  .cr-bar__right{gap:10px}
  /* The label goes and the chevron stays, exactly as Teachable does it. The
     action is still one tap and still the widest thing in the bar's right. */
  .cr--lesson .cr-bar .cr-cta span[data-cta-label]{position:absolute;width:1px;height:1px;
    overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
  .cr--lesson .cr-bar .cr-cta{padding:10px 14px}
  .cr-main{padding:22px 16px 56px}
  .cr-lessonfoot{gap:10px}
  .cr-lessonfoot .btn,.cr-lessonfoot .cr-cta{flex:1;justify-content:center}
}

/* --- Recovered-value gaps -------------------------------------------------
   Teachable rendered a failed variable substitution as the literal word
   "undefined" 664 times, including inside the answer options of 77 quiz
   questions. 107 of those were recovered from the project documents or from
   the lesson's own words; the rest are marked rather than guessed, because
   inventing a building-code value on a licensure product is the one error a
   candidate cannot catch.

   Deliberately conspicuous. A gap styled to blend in is a gap nobody fills. */
.ve-gap {
  display: inline-block;
  padding: 0 .4em;
  margin: 0 .15em;
  border-radius: 4px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ve-gap-fg, #7a4a00);
  background: var(--ve-gap-bg, #ffe9b8);
  border: 1px dashed var(--ve-gap-br, #c98a00);
  cursor: help;
}

/* A question we cannot grade honestly says so, rather than marking somebody
   wrong for an answer the platform lost. data-correct is stripped upstream in
   classroom/tools/repair.py, so this is the visible half of the same fact. */
.qitem.ve-ungraded { position: relative; }
.qitem.ve-ungraded::before {
  content: "Not graded. A value is missing from this question.";
  display: block;
  margin: 0 0 .75rem;
  padding: .5rem .75rem;
  border-radius: 6px;
  font-size: .8125rem;
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--ve-gap-fg, #7a4a00);
  background: var(--ve-gap-bg, #fff4dd);
  border-left: 3px solid var(--ve-gap-br, #c98a00);
}
.qitem.ve-ungraded .opt { cursor: default; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ve-gap-fg: #ffd88a;
    --ve-gap-bg: rgba(201, 138, 0, .16);
    --ve-gap-br: #a97400;
  }
}
:root[data-theme="dark"] {
  --ve-gap-fg: #ffd88a;
  --ve-gap-bg: rgba(201, 138, 0, .16);
  --ve-gap-br: #a97400;
}

/* --- Wrong jurisdiction ---------------------------------------------------
   80 Shore Drive's permitting and scheduling modules are WP Lane's with the
   town swapped, and everything under the heading is the other county's portal,
   office, code and phone number. The words are left alone because rewriting a
   permitting module is not ours to do, so the page carries the correction
   instead. Red, not amber: a candidate filing from this module files in the
   wrong county. */
.ve-jurisdiction {
  margin: 0 0 1.5rem;
  padding: .9rem 1.1rem;
  border-radius: 8px;
  font-size: .9375rem;
  line-height: 1.55;
  color: var(--ve-warn-fg, #7f1d1d);
  background: var(--ve-warn-bg, #fee2e2);
  border-left: 4px solid var(--ve-warn-br, #dc2626);
}
.ve-jurisdiction strong { display: block; margin-bottom: .25rem; }

.qitem.ve-ungraded-juris::before {
  content: "Not graded. This question is about a different county than this project.";
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ve-warn-fg: #fecaca;
    --ve-warn-bg: rgba(220, 38, 38, .16);
    --ve-warn-br: #ef4444;
  }
}
:root[data-theme="dark"] {
  --ve-warn-fg: #fecaca;
  --ve-warn-bg: rgba(220, 38, 38, .16);
  --ve-warn-br: #ef4444;
}

/* --- Recovered values -----------------------------------------------------
   A value that has been recovered IS the lesson's content, so it is styled as
   ordinary text rather than badged. Marking three hundred numbers would make
   every page look provisional and would tell a candidate nothing they can act
   on, which is the opposite of what .ve-gap is for: a gap is a warning, a
   recovered value is just the sentence working again.

   The provenance lives in the title attribute and, properly, in
   classroom/data/resolved-values.md, which lists every filled value against the
   code section or the quoted sentence behind it. That file is the review
   surface. The page is not. */
.ve-filled {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
}

/* --- staff: the People page --------------------------------------------- */
/*
 * Rebuilt 2026-08-24 after Corey called the first pass sloppy and hard to read.
 * He was right, and the interesting part is WHY the gate missed it.
 *
 * The text was never the problem: measured against the panel, the greys ran
 * 6.7:1 to 11.4:1, comfortably past AA. What was unreadable was everything that
 * is NOT text. The input fill sat at 1.11:1 against the panel it lived on and
 * its border at about 2.2:1, so the fields were invisible as SHAPES: you could
 * not see where to type. WCAG 1.4.11 asks 3:1 for a control's boundary and
 * tools/audit_classroom.mjs only ever measured text nodes, so it passed the page
 * happily. The gate now checks borders too.
 *
 * The other two faults were judgement, not measurement. Gold appeared EIGHT
 * times on one screen (nav pill, tag, rule, back link, h1 accent, a bold phrase,
 * a full amber panel, and a glowing CTA), and the luxury spec is explicit that
 * one accent used rarely is the whole effect. And the five column table hid the
 * two row BUTTONS off the right edge of a phone, so the page's only actions did
 * not exist at 390px.
 *
 * Gold is now three things and no more: the h1 accent, the primary button, and
 * the Staff chip. Everything else is the neutral scale below.
 */

/* Measured against the panel (#1F2924 = white .04 over --near-2). Solid values,
   not alpha on alpha, so a nested surface cannot quietly wash one out. */
.cr{
  --p-surface:rgba(255,255,255,.045);
  --p-line:rgba(255,255,255,.13);
  --p-text:#F4F7F5;      /* 13.9:1  names, values, input text */
  --p-body:#DDE5E0;      /* 11.7:1  labels, body copy */
  --p-meta:#C6D2CB;      /*  9.6:1  table values */
  --p-dim:#A4B5AC;       /*  7.0:1  emails, hints, column heads */
  --p-field:#101714;     /* the well: darker than the panel, so it reads as one */
  --p-edge:rgba(255,255,255,.42);  /* 3.8:1 against the panel, past 1.4.11's 3:1 */
}

.cr-bar__link{color:var(--p-body);text-decoration:none;font-size:.9rem;font-weight:600;
  padding:8px 12px;border-radius:9px;border:1px solid var(--p-line);white-space:nowrap}
.cr-bar__link:hover{background:rgba(255,255,255,.09);color:#fff;border-color:var(--p-edge)}
.cr-bar__link[aria-current]{color:var(--amber);border-color:rgba(234,165,30,.45)}

.cr-panel{background:var(--p-surface);border:1px solid var(--p-line);
  border-radius:16px;padding:32px;margin-top:36px}
@media (max-width:640px){.cr-panel{padding:22px 18px;margin-top:26px;border-radius:14px}}
.cr-panel h2{font-size:var(--step-2);margin:0 0 4px}
.cr-panel__sub{color:var(--p-dim);font-size:.94rem;margin:0 0 24px;max-width:62ch}

.cr-panel .field{margin-top:22px}

/* ONE input treatment for the whole classroom, and it belongs here rather than
   on the People page, because the page that needed it most was the PASSWORD
   page: site.css's `.field input` is tuned for the light marketing pages
   (`--surface` white fill, `--ink` text, `--line` border) and the classroom
   card is near-black. Inherited unchanged, the field came out as a 2.04:1
   outline on the first screen every candidate ever sees. Same family as the
   `.btn--ghost` bug on 2026-08-24: a site.css component borrowed into `.cr`
   without a dark variant, invisible in the source, obvious on screen. */
.cr .field label{color:var(--p-body);font-weight:600;font-size:.95rem;margin-bottom:8px}
.cr .field input,.cr .field select,.cr .field textarea{
  background:var(--p-field);border:1px solid var(--p-edge);
  color:var(--p-text);border-radius:11px;padding:13px 15px;min-height:50px}
.cr .field input::placeholder{color:var(--p-dim)}
.cr .field input:hover,.cr .field textarea:hover{border-color:rgba(255,255,255,.6)}
/* A focus ring you can see on near-black, and it does not shift the layout. */
.cr .field input:focus,.cr .field select:focus,.cr .field textarea:focus{
  outline:none;border-color:var(--amber);box-shadow:0 0 0 3px rgba(234,165,30,.28)}

.cr-formrow{display:grid;gap:22px}
.cr-formrow .field{margin-top:0}
@media (min-width:760px){.cr-formrow{grid-template-columns:1fr 1fr}}

/* Input and button on one baseline. They were different heights before, which
   is the sort of thing that reads as unfinished before anybody can say why. */
.cr-passrow{display:flex;gap:10px;align-items:stretch}
.cr-passrow input{flex:1;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  letter-spacing:.02em}
.cr-passrow .cr-mini{flex:none;min-height:50px;padding:0 16px}
@media (max-width:520px){
  .cr-passrow{flex-direction:column}
  .cr-passrow .cr-mini{width:100%}
}
.cr-hint{color:var(--p-dim);font-size:.88rem;line-height:1.55;margin-top:9px;max-width:64ch}

/* Neutral, not amber. An amber block stacked directly above an amber button was
   two loud things fighting; the sentence carries itself. */
.cr-note{margin-top:24px;padding:14px 16px;border-radius:11px;
  background:rgba(255,255,255,.05);border:1px solid var(--p-line);
  color:var(--p-body);font-size:.94rem;line-height:1.5}
.cr-note strong{color:var(--p-text);font-weight:700}

/* site.css puts a 26px amber halo under every primary button. On the light
   marketing pages it reads as lift; on near-black it reads as a 2010 gradient
   button, and it was under the one CTA on the password screen too. */
.cr .btn--primary{box-shadow:none}
.cr .btn--primary:hover{box-shadow:none}
.cr-panel .btn--primary{margin-top:26px}

.cr-mini{background:transparent;border:1px solid var(--p-edge);color:var(--p-text);
  border-radius:10px;padding:11px 14px;font:inherit;font-size:.87rem;font-weight:600;
  cursor:pointer;white-space:nowrap;min-height:44px}
.cr-mini:hover{border-color:#fff;background:rgba(255,255,255,.1)}
.cr-mini--off:hover{border-color:#F0A08A;color:#F0A08A;background:rgba(240,160,138,.1)}
.cr-mini[disabled]{opacity:.5;cursor:default}

/* --- the roster ---------------------------------------------------------- */
.cr-tablewrap{margin-top:20px}
.cr-people{width:100%;border-collapse:collapse}
.cr-people th{text-align:left;font-size:.74rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--p-dim);font-weight:700;padding:0 18px 12px 0;white-space:nowrap}
.cr-people td{padding:18px 18px 18px 0;border-top:1px solid var(--p-line);vertical-align:middle}
.cr-people__name{display:block;color:var(--p-text);font-weight:600;font-size:1rem}
.cr-people__email{display:block;color:var(--p-dim);font-size:.87rem;margin-top:3px}
.cr-people__meta{color:var(--p-meta);font-size:.92rem}
.cr-people__meta--dim{color:var(--p-dim);font-size:.87rem}
/* The flex lives on a DIV inside the cell. `display:flex` on a <td> takes it out
   of table-cell layout: its border-top then draws at its own height instead of
   the row's, so the roster showed a second, offset rule above every button
   group. Nothing about that reads as a layout-mode bug on screen. */
.cr-people__actcell{text-align:right}
.cr-people__act{display:flex;flex-wrap:wrap;gap:9px;justify-content:flex-end}

/* State as a word with a quiet dot, not a colour-only signal: colour alone
   fails anybody who cannot separate these two greens. */
.cr-state{display:inline-flex;align-items:center;gap:8px;color:var(--p-meta);font-size:.92rem}
.cr-state::before{content:"";width:7px;height:7px;border-radius:50%;flex:none;
  background:currentColor;opacity:.9}
.cr-state--on{color:#9BD8A8}
.cr-state--new{color:var(--amber-lift)}
.cr-state--off{color:#F0A08A}

.cr-chip{display:inline-block;font-size:.7rem;font-weight:700;letter-spacing:.13em;
  text-transform:uppercase;padding:5px 11px;border-radius:999px;
  border:1px solid var(--p-line);color:var(--p-dim)}
.cr-chip--staff{border-color:rgba(234,165,30,.45);color:var(--amber-lift);
  background:rgba(234,165,30,.1)}

/* A switched-off row stays fully legible. Dimming it to 40% is how a revoked
   account becomes invisible on the one page that exists to show you it. */
.cr-row--off .cr-people__name{color:var(--p-meta)}

/* --- under 760px the table becomes cards -------------------------------- */
/* Not a horizontal scroller. A scroller put the two buttons off the right edge
   with nothing on screen saying they were there. */
@media (max-width:760px){
  .cr-people,.cr-people tbody,.cr-people tr,.cr-people td{display:block;width:100%}
  .cr-people thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
  .cr-people tr{border:1px solid var(--p-line);border-radius:13px;padding:16px;
    margin-top:14px;background:rgba(255,255,255,.03)}
  .cr-people td{border:0;padding:0;margin-top:11px;display:flex;gap:14px;
    align-items:baseline;justify-content:space-between}
  .cr-people td:first-child{margin-top:0;display:block}
  .cr-people td[data-label]:not([data-label=""])::before{
    content:attr(data-label);color:var(--p-dim);font-size:.74rem;font-weight:700;
    letter-spacing:.13em;text-transform:uppercase;flex:none}
  .cr-people__actcell{margin-top:16px;padding-top:14px;border-top:1px solid var(--p-line);
    display:block;text-align:left}
  .cr-people__actcell::before{display:none}
  .cr-people__act{justify-content:stretch}
  .cr-people__act .cr-mini{flex:1}
  .cr-people__act .cr-mini{flex:1}
}

.cr .formstatus--ok{display:block;background:rgba(155,216,168,.1);
  border:1px solid rgba(155,216,168,.34);border-radius:10px;padding:12px 14px;
  color:#BFE8C8;font-weight:600;font-size:.92rem;overflow-wrap:anywhere;line-height:1.5}
.cr .formstatus--err{display:block;background:rgba(240,160,138,.1);
  border:1px solid rgba(240,160,138,.34);border-radius:10px;padding:12px 14px;
  color:#F4B7A5;font-weight:600;font-size:.92rem;line-height:1.5}
