/* Staff web surfaces. Consumes tokens.css; owns no custom-property root of
   its own. Every selector here is scoped under .sk- because Propshaft loads
   this file on every page in the product -- see
   spec/assets/stylesheet_isolation_spec.rb.

   Organized by component as staff.css grows across later tasks:
   - Device gate (.sk-gate): shown when a teacher/admin opens a staff surface
     on a phone -- see StaffGateController.
   - Super admin sign-in / two-factor (.sk-signin*, .sk-field, .sk-cta).
   - App shell (.sk-shell*, .sk-bar__inner): the full-bleed frame every Sa::
     screen sits in (a deliberate divergence from the design's centred panel
     -- see the component comment below). The centred-column look comes from
     --sk-column, which the header, the nav, the per-screen bar and the scroll
     column all read, so none of them can drift out of line with the others.
   - Platform header + tab nav (.sk-hdr*, .sk-tabs*): shared chrome for every
     Sa:: screen.
   - Dashboard (.sk-scroll, .sk-stat*, .sk-card*, .sk-flow*, .sk-concern*):
     sa-home's stat grid and curriculum-flow explainer, and the school admin
     dashboard's named concerns list.
   - School register (.sk-row*, .sk-note): sa-schools' listing rows and the
     family-accounts note.
   - Master curriculum library (.sk-pills*, .sk-subject-row*, .sk-empty*):
     sa-curriculum's grade picker, subject rows and empty grade.
   - Subject screen (.sk-chapter*, .sk-topic-row*, .sk-add-row): sa-subject's
     chapter groups, their topic rows and the dashed add.
   - Topic screen (.sk-material*, .sk-switch*, .sk-question-row*, .sk-tag*):
     sa-topic's study-material blocks, the tutor switch and the question bank.
   - School onboarding (.sk-form*, .sk-input, .sk-chip*, .sk-formbar,
     .sk-done*): sa-add-school's three-card form, its sticky action bar and
     the confirmation screen that follows a save. */

/* layouts/sa.html.erb sets <body class="sa"> for every Sa:: screen except
   sign-in (Sa::TwoFactorController and Sa::BaseController both declare
   `layout 'sa'`; Sa::SessionsController deliberately does not -- see its own
   comment -- so only #new/#create there render under application.css's
   .app-legacy instead, which already resets box-sizing). No stylesheet
   matched .sa at all: not just missing box-sizing, but also the
   `body { margin: 0 }` every other surface's own body-class rule provides
   (application.css's .app-legacy, student.css's .sikai-student,
   landing.css's .sikai-public, admin.css's body.admin above). The visible
   bug: .sk-cta below is `width: 100%; padding: 17px` inside
   .sk-signin__card's `padding: 34px`, so under content-box the Verify button
   overflowed its card by 34px, and the card itself overflowed a phone
   viewport by the default 8px body margin plus that same 34px.

   body.school (layouts/school.html.erb) is the same shell rendering the same
   sk-* components -- .sk-btn, .sk-field, .sk-subhead__back and the rest all
   assume border-box the same way .sk-cta did -- so it is reset alongside
   .sa here rather than waiting to reproduce the same bug on its own. */
body.sa,
body.school {
  margin: 0;
}

body.sa,
body.sa *,
body.school,
body.school * {
  box-sizing: border-box;
}

/* Device gate */
.sk-gate { min-height: 100vh; display: flex; flex-direction: column;
           align-items: center; justify-content: center; gap: 14px;
           padding: 32px; text-align: center;
           background: var(--sk-fill-1); font-family: var(--sk-font-ui); }
.sk-gate__title { font-size: 22px; font-weight: 800; color: var(--sk-ink); margin: 0; }
.sk-gate__body { font-size: 14px; color: var(--sk-text-2); margin: 0; max-width: 34em; }
.sk-gate__url { font-family: var(--sk-font-ui); font-size: 13px;
                color: var(--sk-text-muted); margin: 0; }
.sk-gate__back { font-size: 13px; font-weight: 600; color: var(--sk-accent); }

/* Super admin sign-in / two-factor */
.sk-signin { min-height: 100vh; display: flex; align-items: center; justify-content: center;
             background: var(--sk-fill-1); padding: 32px; font-family: var(--sk-font-ui); }
.sk-signin__card { background: var(--sk-surface); border: 1px solid rgba(23, 24, 26, .08);
                   border-radius: 22px; padding: 34px; width: 100%; max-width: 430px; }
.sk-signin__brand { display: flex; align-items: center; gap: 10px; }
/* The mark itself -- see the note on .p-mark__tile in landing.css. */
/* 32x26 -- the mark's own 119:96, not a square. See landing.css. */
.sk-signin__mark { width: 32px; height: 26px;
                   background: url("/assets/sikai-mark-64ad84a4.png") center / contain no-repeat; }
/* An <img> now, not a word: these classes size the drawn wordmark instead
   of setting type. Height only, width auto, so the asset keeps its own
   proportions at whatever height each surface wants. */
.sk-signin__wordmark { height: 19px; width: auto; display: block; }
.sk-portal-tag { margin-left: auto; padding: 5px 9px; border-radius: 999px;
                 font-family: var(--sk-font-ui); font-weight: 600; font-size: 9px; }
.sk-portal-tag--internal { background: var(--sk-accent-subtle); color: var(--sk-accent); }
/* The other door in the same building: school staff rather than Sikai's own.
   Deliberately quieter than --internal -- a teacher signing in is the
   ordinary case, and the accent tint is what marks the platform screens. */
.sk-portal-tag--school { background: var(--sk-fill-3); color: var(--sk-text-2); }
.sk-signin__title { font-size: 20px; font-weight: 800; color: var(--sk-ink); margin: 22px 0 6px; }
/* --sk-text-2, not --sk-text-muted. Muted is #9A9EA6, which measures 2.7:1
   on the white card -- under the 4.5:1 floor for the 13px sentence that tells
   a member of staff where their account comes from, and for the 11px labels
   naming the fields. Used only by the three sign-in screens (staff, super
   admin, two-factor), so this raises all three. */
.sk-signin__note { font-size: 13px; color: var(--sk-text-2); margin: 0 0 22px; }
/* The failed-attempt count, which sits between the password field and the
   submit button (sessions/new.html.erb). It carried this modifier with no
   rule behind it, so it rendered as another grey paragraph identical to the
   standing note above the form -- two sentences saying different kinds of
   thing in the same voice.

   --sk-warning is #8A6D12, which measures 4.9:1 on the white card: over the
   4.5:1 floor for 13px, unlike --sk-warning-tint's ink or --sk-text-muted
   (see the note above). The margin is tighter than the base note's 22px
   because this one belongs to the fields above it, not to the form. */
.sk-signin__note--warn { color: var(--sk-warning); margin: -4px 0 16px; }
.sk-field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.sk-field__label { font-size: 11px; font-weight: 600; color: var(--sk-text-2); }
.sk-field__input { padding: 13px 14px; border-radius: 13px; border: 1.5px solid rgba(23, 24, 26, .12);
                   font-family: var(--sk-font-ui); font-size: 14.5px; color: var(--sk-ink); }
.sk-cta { width: 100%; padding: 17px; border-radius: 16px; border: none; cursor: pointer;
          background: var(--sk-accent); color: #fff; font-family: var(--sk-font-ui);
          font-weight: 700; font-size: 15.5px; }
.sk-cta:hover { background: var(--sk-accent-hover); }

/* ---------------------------------------------------------------------------
   Everything below is transcribed from the design source, not approximated.
   The first pass described these components in prose ("the dark header is
   ink") and the numbers were invented to fit; each one here now comes from
   the design's own style objects. Where a value looks arbitrary -- 9px
   labels, 68px chips, a 780px column -- it is arbitrary in the design too.
   Don't round it.
   --------------------------------------------------------------------------- */

/* App shell. The design centres a 1440px white panel on a page-grey field
   rather than running edge to edge; this deliberately does not implement
   that. .sk-shell__panel is full width with no max-width and no background
   of its own, so it stretches to the viewport rather than sitting as a
   bounded card on --sk-page -- a human choice made after the design was
   transcribed, not an oversight. The centred-column read the design wants
   comes from .sk-scroll's own 780px max-width instead (further down this
   file), which is real width capping, just narrower and un-panelled. */
.sk-shell { min-height: 100vh; display: flex; justify-content: center;
            background: var(--sk-page);
            /* The one column every platform screen lines up on. Declared here
               rather than in tokens.css because it is this surface's layout,
               not a design token, and tokens.css owns the only :root in the
               product (see its header, and stylesheet_isolation_spec). Every
               bar and every content block reads it, so the header, the
               per-screen bar and the scroll column cannot drift apart -- which
               is exactly what happened when each carried its own 780px or,
               worse, none at all. */
            --sk-column: 780px; }
.sk-shell__panel { width: 100%; min-height: 100vh;  display: flex; flex-direction: column; }

/* A full-bleed bar whose contents sit on --sk-column. The bar's own
   background and bottom rule still run edge to edge -- that is what makes it
   read as a bar rather than a floating card -- while everything inside it
   lines up with the cards below. */
.sk-bar__inner { width: 100%; max-width: var(--sk-column); margin: 0 auto;
                 box-sizing: border-box; }

/* Dark platform header (design: hdrDark). The bar is full width; its
   contents sit on --sk-column, so the brand lines up with the page title
   under it and with the cards under that. */
.sk-hdr { flex: none; font-family: var(--sk-font-ui); }
.sk-hdr .sk-bar__inner { display: flex; align-items: center; gap: 12px;
                         padding: 16px 34px; }
.sk-hdr__group { flex: 1; min-width: 0; }
.sk-hdr--dark { background: var(--sk-ink); }

/* The Sikai mark in the dark header, ON A LIGHT CHIP rather than bare.
 *
 * The mark is one colour, #185888, and .sk-hdr--dark is --sk-ink: that pair
 * measures 2.4:1, so dropped straight onto the bar it would be a dark smudge
 * on a dark bar. There is no reversed/knockout version of the logo in the
 * supplied set and inventing one is not this commit's call, so the chip gives
 * it the light ground it was drawn for.
 *
 * Only the mark goes here, never the wordmark: the words beside it are the
 * school's name (or "Super admin"), not Sikai's, and they are already white. */
.sk-hdr__mark { flex: none; display: flex; align-items: center; justify-content: center;
                width: 38px; height: 32px; border-radius: 9px;
                background: var(--sk-surface); }
.sk-hdr__mark::before { content: ""; width: 26px; height: 21px;
                        background: url("/assets/sikai-mark-64ad84a4.png") center / contain no-repeat; }
.sk-hdr__eyebrow { margin: 0; font: 500 11px/1 var(--sk-font-ui);
                   color: rgba(255, 255, 255, .5); }
/* Back link (sa-subject, back to sa-curriculum). Sits above the eyebrow in
   the same dark header rather than a separate bar, since this screen is one
   level deep and has nothing else to put in a nav row. */
.sk-hdr__back { display: inline-flex; align-items: center; gap: 5px;
                margin-bottom: 8px; font: 600 11px/1 var(--sk-font-ui);
                color: rgba(255, 255, 255, .65); text-decoration: none; }
.sk-hdr__title { margin: 2px 0 0; font: 700 16px/1.15 var(--sk-font-ui); color: #fff; }
.sk-hdr__signout { padding: 9px 14px; border-radius: 11px;
                   border: 1px solid rgba(255, 255, 255, .16);
                   background: rgba(255, 255, 255, .07); color: #fff;
                   font: 600 12px/1 var(--sk-font-ui); cursor: pointer;
                   /* Also worn by "Back to schools", which is an <a>: no
                      stylesheet on this surface clears the UA underline. */
                   text-decoration: none; }
.sk-hdr__signout:hover { color: #fff; }

/* Who is signed in and as what. The school portal's header carries an
   identity where /sa's carries only a label, because a school has several
   staff and a teacher sharing a staffroom computer needs to see whose
   session this is before they mark anything. */
.sk-hdr__who { display: flex; flex-direction: column; gap: 2px; text-align: right; }
.sk-hdr__name { font: 700 12.5px/1.2 var(--sk-font-ui); color: #fff; }
.sk-hdr__role { font: 500 10.5px/1 var(--sk-font-ui); color: rgba(255, 255, 255, .55);
                text-transform: uppercase; letter-spacing: .06em; }

/* Tab nav (design: tabsBar + sanav). A light bar of centred pills, each with
   a leading dot -- not dark underline tabs. The dot is a rounded square when
   the section is current and a circle otherwise. */
.sk-tabs { flex: none; background: var(--sk-surface);
           border-bottom: 1px solid rgba(23, 24, 26, .07); }
/* The strip scrolls inside itself rather than pushing the page wide. Without
   this the tabs are 594px of content in a 360px viewport, so EVERY school
   screen scrolled horizontally on the low-end Android this product is built
   for -- the dashboard included, and nothing in the suite could see it: a
   markup assertion has no viewport. Found by measuring at 360px.

   justify-content only centres while there is room to spare; once the strip
   overflows, `center` would clip the first tab out of reach at scroll 0,
   which is why it becomes flex-start at the width where that starts to
   happen. -webkit-overflow-scrolling for the WebViews Hotwire Native wraps
   this in. */
.sk-tabs .sk-bar__inner { display: flex; justify-content: center; gap: 10px;
                          padding: 8px 26px; overflow-x: auto;
                          -webkit-overflow-scrolling: touch;
                          scrollbar-width: none; }
.sk-tabs .sk-bar__inner::-webkit-scrollbar { display: none; }
.sk-tabs__item { flex: none; }

@media (max-width: 700px) {
  .sk-tabs .sk-bar__inner { justify-content: flex-start; }
}
/* text-decoration is reset explicitly: these are <a> elements but the design
   draws them as buttons, and no stylesheet on this surface clears the UA
   underline (application.css's reset is scoped to .app-legacy). */
.sk-tabs__item { display: flex; flex-direction: row; align-items: center; gap: 8px;
                 padding: 9px 15px; border-radius: 11px; border: none;
                 background: transparent; color: #71757E; text-decoration: none;
                 font-family: var(--sk-font-ui); font-weight: 700; font-size: 13px; }
.sk-tabs__item--on { background: var(--sk-accent-subtle); color: var(--sk-accent); }
.sk-tabs__dot { width: 12px; height: 12px; border-radius: 50%;
                background: currentColor; opacity: .4; }
.sk-tabs__item--on .sk-tabs__dot { border-radius: 4px; opacity: 1; }
/* Sections whose destination does not exist yet: dimmed, and never a link. */
.sk-tabs__item--pending { opacity: .55; cursor: default; }

/* Scroll column (design: scroll14). The 780px cap is why the page reads as a
   centred column instead of stretching across a wide monitor. */
.sk-scroll { flex: 1; overflow: auto; display: flex; flex-direction: column;
             gap: 16px; padding: 30px 34px 42px; width: 100%;
             max-width: var(--sk-column); margin: 0 auto; box-sizing: border-box;
             font-family: var(--sk-font-ui); }

/* Stat tiles (design: statGrid). Four columns, all four populated --
   questions-in-bank became a real count once the master curriculum landed in
   A2, and the fourth carries the tutor safeguarding queue's count rather
   than the awaiting-review concept that still does not exist (see
   Sa::DashboardsController#show). The design gives the lead tile a dark
   fill and each later tile its own number colour.
   .sk-stat--link is the one tile that is also a destination: an anchor
   needs `display: block` to lay out like the div every other tile is, since
   .sk-stat itself declares no display and would otherwise fall back to an
   inline anchor's default. */
.sk-stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.sk-stat { background: var(--sk-surface); border: 1px solid rgba(23, 24, 26, .08);
           border-radius: 16px; padding: 15px; }
.sk-stat--lead { background: var(--sk-ink); border-color: var(--sk-ink); }
.sk-stat--link { display: block; text-decoration: none; }
.sk-stat--link:hover { background: var(--sk-fill-1); }
.sk-stat__n { display: block; font: 600 20px/1 var(--sk-font-ui); color: var(--sk-ink); }
.sk-stat--lead .sk-stat__n { color: #fff; }
.sk-stat__l { display: block; margin-top: 6px; font: 700 9px/1.3 var(--sk-font-ui);
              letter-spacing: .1em; text-transform: uppercase; color: var(--sk-text-muted); }
.sk-stat--lead .sk-stat__l { color: rgba(255, 255, 255, .5); }

/* Cards (design: card) */
.sk-card { background: var(--sk-surface); border: 1px solid rgba(23, 24, 26, .08);
           border-radius: 18px; padding: 16px; display: flex; flex-direction: column;
           gap: 13px; }
.sk-card__title { margin: 0; font: 700 9.5px/1 var(--sk-font-ui); letter-spacing: .12em;
                  text-transform: uppercase; color: var(--sk-text-muted); }

/* The dashboard's named concerns (Schools::NeedsAttention).
 *
 * No coloured left rule any more, and no per-kind modifier. It used to draw
 * one in --sk-warning, --sk-error or --sk-text-muted depending on
 * Notice#kind, which encoded the kind of concern in a colour -- next to a
 * sentence that already said it in words. Schools::NeedsAttention's own
 * class comment is the argument against it: "A count is not a concern. '3
 * issues' tells an admin to go hunting; 'Class 7A has had no activity this
 * week' tells them who to ring." Every message it emits names the class or
 * the number and what is wrong with it, so the bar was telling a
 * colour-sighted reader something the row already told everyone.
 *
 * If a future kind ever needs distinguishing beyond its sentence, give it a
 * word, not a hue. */
.sk-concerns { list-style: none; margin: 0; padding: 0; display: flex;
               flex-direction: column; gap: 8px; }
.sk-concern { padding: 11px 13px; border-radius: 12px; background: var(--sk-fill-1); }
.sk-concern__link { font: 600 13px/1.5 var(--sk-font-ui); color: var(--sk-ink);
                    text-decoration: none; }
.sk-concern__link:hover { color: var(--sk-accent); }

/* Curriculum-flow explainer */
.sk-flow { display: flex; gap: 12px; align-items: flex-start; }
.sk-flow__chip { width: 68px; flex: none; text-align: center; padding: 5px 6px;
                 border-radius: 999px; font: 600 8.5px/1.4 var(--sk-font-ui);
                 background: var(--sk-accent-subtle); color: var(--sk-accent); }
.sk-flow__chip--sikai { background: var(--sk-ink); color: #fff; }
.sk-flow__what { flex: 1; font: 500 12.5px/1.55 var(--sk-font-ui); color: var(--sk-text-2); }

/* Grade picker (design: pillsRow). A row of small mono pills, one per grade
   -- selected is ink-filled, everything else is a light neutral chip. */
.sk-pills { display: flex; flex-wrap: wrap; gap: 8px; }
/* #5C6069 is a design value with no matching token (nearest token,
   --sk-text-2 #3D4149, is visibly darker) -- literal per .sk-hdr__back below. */
.sk-pill { padding: 9px 12px; border-radius: 11px; font: 600 11.5px/1 var(--sk-font-ui);
           background: var(--sk-fill-3); color: #5C6069; text-decoration: none; }
.sk-pill--on { background: var(--sk-ink); color: #fff; }

/* Subject rows (design: saSubjects). One row per subject: a rounded mark
   carrying its initials, the name with its counts under it, and its state.
   The mark is filled when the subject is published and neutral when it is
   not, so a grade's worth of them reads at a glance. */
.sk-subject-row { display: flex; align-items: center; gap: 12px; padding: 15px;
                  background: var(--sk-surface); border: 1px solid rgba(23, 24, 26, .08);
                  border-radius: 18px; text-decoration: none; }
.sk-subject-row:hover { border-color: rgba(24, 88, 136, .4); }
.sk-subject-row__mark { width: 36px; height: 36px; flex: none; border-radius: 12px;
                        display: flex; align-items: center; justify-content: center; }
.sk-subject-row__mark--on { background: var(--sk-accent-subtle); color: var(--sk-accent); }
.sk-subject-row__mark--off { background: var(--sk-fill-2); color: var(--sk-text-muted); }
.sk-subject-row__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.sk-subject-row__name { font: 700 14.5px/1.2 var(--sk-font-ui); color: var(--sk-ink); }
.sk-subject-row__counts { font: 500 10.5px/1 var(--sk-font-ui); color: var(--sk-text-muted); }

/* A name that is also a link, which this kit had no rule for. The convention
   everywhere else is that the WHOLE row is the anchor -- .sk-row--link, and
   admin/dashboards' link_to ... class: "sk-subject-row" -- so nothing ever
   needed one. teach/students/_row cannot follow it: those rows also carry
   Edit and Remove button_to forms, and interactive controls nested inside an
   anchor are invalid markup and unreachable by keyboard. So the name stays
   the link, and is styled to sit in the row rather than on top of it.

   Without this the roster, the class-detail roster and the all-students list
   drew every child's name in default browser blue, underlined, inside a
   design whose row colour is near-black. All three were green the whole
   time: a markup assertion cannot see a colour. Hover carries the affordance
   instead, the way .sk-concern__link already does. */
.sk-subject-row__name a,
.sk-subject-row__counts a,
.sk-row__name a,
.sk-row__meta a { color: inherit; text-decoration: none; }
.sk-subject-row__name a:hover,
.sk-subject-row__counts a:hover,
.sk-row__name a:hover,
.sk-row__meta a:hover { color: var(--sk-accent); text-decoration: underline; }

/* An empty slot, drawn as one: dashed rather than a solid card, so it reads
   as somewhere content goes instead of as content. */
.sk-empty { display: flex; flex-direction: column; gap: 8px; padding: 22px;
            border-radius: 18px; border: 1.5px dashed rgba(23, 24, 26, .16); }
.sk-empty__title { margin: 0; font: 700 14px/1.2 var(--sk-font-ui); color: var(--sk-ink); }
.sk-empty__body { margin: 0; font: 500 12.5px/1.55 var(--sk-font-ui); color: #71757E; }

/* "Add topic to this chapter", "Write the explanation" -- the design's dashed
   full-width row for adding to the thing above it. */
.sk-add-row { display: block; padding: 11px; border-radius: 12px; text-align: center;
              border: 1.5px dashed rgba(23, 24, 26, .16); background: transparent;
              color: #5C6069; font: 700 11.5px/1 var(--sk-font-ui); text-decoration: none; }
.sk-add-row:hover { border-color: var(--sk-accent); color: var(--sk-accent); }

/* A section label with something beside it. */
.sk-section-head { display: flex; align-items: baseline; justify-content: space-between;
                   gap: 12px; flex-wrap: wrap; }

/* A heading inside a card's own body, for prose. Every other heading in this
   kit belongs to a component -- .sk-card__title labels a card, .sk-row__name
   names a row, .sk-chapter__title titles a chapter -- because no staff screen
   rendered running text until the deep-lesson review did. Borrowing one of
   those would be the cross-family reach this kit has been picked up on
   before, and leaving the h3 bare gave it the browser's 21px, which is the
   page-title size and made a section inside a card shout louder than the card
   it sits in. Same 14.5px/700 as .sk-chapter__title: the kit's existing size
   for a short bold heading that is not a page title. */
.sk-prose-head { margin: 12px 0 0; font: 700 14.5px/1.2 var(--sk-font-ui); color: var(--sk-ink); }

/* Chapter groups (design: saUnits). One card per chapter: a one-line head
   carrying the number, the name and what is inside it, then a row per topic,
   then the dashed add. */
.sk-chapter { background: var(--sk-surface); border: 1px solid rgba(23, 24, 26, .08);
              border-radius: 18px; padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.sk-chapter__head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.sk-chapter__no { font: 600 11px/1 var(--sk-font-ui); color: var(--sk-accent); }
.sk-chapter__title { flex: 1; min-width: 0; margin: 0;
                     font: 700 14.5px/1.2 var(--sk-font-ui); color: var(--sk-ink); }
.sk-chapter__meta { font: 500 10.5px/1 var(--sk-font-ui); color: var(--sk-text-muted); }
.sk-chapter__edit { font: 700 11px/1 var(--sk-font-ui); color: var(--sk-text-muted);
                    text-decoration: none; }
.sk-chapter__edit:hover { color: var(--sk-accent); }

/* Topic rows (design: chRow). Filled rather than ruled: inside a chapter card
   they are the things you tap, and a fill says that better than a border. */
.sk-topic-row { display: flex; align-items: center; gap: 12px; padding: 12px 13px;
                border-radius: 13px; background: var(--sk-fill-1); text-decoration: none; }
.sk-topic-row:hover { background: var(--sk-fill-2); }
.sk-topic-row__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.sk-topic-row__name { font: 600 13px/1.25 var(--sk-font-ui); color: var(--sk-ink); }
.sk-topic-row__meta { font: 500 10.5px/1 var(--sk-font-ui); color: var(--sk-text-muted); }

/* School register rows (design: rowBase) */
.sk-row { display: flex; align-items: center; gap: 11px; padding: 11px 0;
          border-bottom: 1px solid rgba(23, 24, 26, .06); }
.sk-row:last-child { border-bottom: none; }
.sk-row__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.sk-row__name { font: 700 13.5px/1.2 var(--sk-font-ui); color: var(--sk-ink); }
.sk-row__meta { font: 600 9px/1.3 var(--sk-font-ui); letter-spacing: .08em;
                text-transform: uppercase; color: var(--sk-text-muted); }
.sk-row__code { font: 600 11.5px/1 var(--sk-font-ui); color: var(--sk-text-muted); }
.sk-note { margin: 0; font: 500 12.5px/1.55 var(--sk-font-ui); color: var(--sk-text-2); }
/* The muted variant _form.html.erb already writes onto its grade/leaderboard
   hints (and now the class detail screen's design-copy paragraph) -- never
   defined until this task, so both were falling back to plain .sk-note's
   darker color with no visible effect from the modifier. Muted, not a
   second font size: this is aside text next to a fact the reader already
   has, not a smaller version of the same note. */
.sk-note--quiet { color: var(--sk-text-muted); }
/* The consequence stated before the PIN-slips print button acts, not
   discovered after: --sk-warning is the same ink .sk-signin__note--warn
   already uses for the same reason (contrast checked against the white card
   there), so a warning reads as a warning everywhere it appears. */
.sk-note--warn { color: var(--sk-warning); }

/* Per-screen bar, directly under the nav (see sa/_subhead). Everything that
   changes as you navigate lives here -- the title, the way back up one level,
   and the screen's own actions -- so the dark header above stays identical on
   every platform screen. */
.sk-subhead { flex: none; border-bottom: 1px solid rgba(23, 24, 26, .07);
              background: var(--sk-surface); font-family: var(--sk-font-ui); }
.sk-subhead .sk-bar__inner { display: flex; align-items: flex-end; gap: 16px;
                             flex-wrap: wrap; padding: 18px 34px 16px; }
.sk-subhead__group { flex: 1; min-width: 0; }
.sk-subhead__back { display: inline-flex; align-items: center; gap: 5px;
                    margin-bottom: 8px; font: 600 11px/1 var(--sk-font-ui);
                    color: var(--sk-text-muted); text-decoration: none; }
.sk-subhead__back:hover { color: var(--sk-accent); }
.sk-subhead__eyebrow { margin: 0 0 4px; font: 700 9.5px/1 var(--sk-font-ui);
                       letter-spacing: .12em; text-transform: uppercase;
                       color: var(--sk-text-muted); }
.sk-subhead__title { margin: 0; font: 800 21px/1.15 var(--sk-font-ui); color: var(--sk-ink); }
.sk-subhead__actions { flex: none; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* Fact list (sa-school's licence and profile blocks). A <dl>, because that is
   what it is: a term and the one value the platform holds for it. Two
   columns on anything wider than a phone, stacked below that. */
.sk-facts { margin: 0; display: flex; flex-direction: column; }
.sk-facts__row { display: flex; align-items: baseline; gap: 16px; padding: 9px 0;
                 border-bottom: 1px solid rgba(23, 24, 26, .06); }
.sk-facts__row:last-child { border-bottom: none; }
.sk-facts dt { flex: none; width: 190px; margin: 0; font: 600 11px/1.4 var(--sk-font-ui);
               letter-spacing: .04em; color: var(--sk-text-muted); }
.sk-facts dd { flex: 1; min-width: 0; margin: 0; font: 600 13px/1.4 var(--sk-font-ui);
               color: var(--sk-ink); }
.sk-facts__mono { font-family: var(--sk-font-ui); }
/* A value the platform does not hold. Named as absent rather than rendered
   as an empty cell, which reads as a bug. */
.sk-facts__empty { font-weight: 500; color: var(--sk-text-muted); }

@media (max-width: 560px) {
  .sk-facts__row { flex-direction: column; gap: 2px; }
  .sk-facts dt { width: auto; }
}

/* A table, which this kit deliberately did not have -- .sk-row and
   .sk-subject-row exist precisely because most staff screens are "a list to
   read, not a table to scan", and forcing a list into columns was the wrong
   default. Two surfaces genuinely are tables and were left on admin.css for
   that reason (Ruling B9 kept the sign-in history full-bleed rather than
   capping it to the 780px column, because six narrow columns need the room):
   the sign-in history, where an admin scans down Who and Outcome hunting a
   pattern across fifty rows, and the curriculum screens, where the same eye
   runs down a pack's items. A card per row would be six lines each and
   unreadable at either.

   So the kit gains a table rather than six screens being contorted into card
   lists. Kept to what those screens need and no more: no zebra striping, no
   sort affordance, no sticky head -- none of which any of them use.

   .sk-scroll already gives it a horizontal scroll container on a phone, which
   is what makes a six-column table survive a 360px screen at all. */
.sk-table { width: 100%; border-collapse: collapse; }
.sk-table th { text-align: left; padding: 8px 10px; white-space: nowrap;
               border-bottom: 1px solid rgba(23, 24, 26, .08);
               font: 700 9.5px/1 var(--sk-font-ui); letter-spacing: .12em;
               text-transform: uppercase; color: var(--sk-text-muted); }
.sk-table td { padding: 9px 10px; vertical-align: top;
               border-bottom: 1px solid rgba(23, 24, 26, .08);
               font: 500 12.5px/1.45 var(--sk-font-ui); color: var(--sk-text-2); }
.sk-table tr:last-child td { border-bottom: 0; }
/* Same reset the row components carry, and for the same reason: without it a
   linked cell is default browser blue inside a near-black table. */
.sk-table a { color: var(--sk-ink); text-decoration: none; }
.sk-table a:hover { color: var(--sk-accent); text-decoration: underline; }
/* A cell holding an identifier rather than prose -- an IP, a username, a
   device string. Mono, so a column of them lines up and a transposed digit
   is visible. */
.sk-table__code { font: 500 11px/1.4 var(--sk-font-ui); color: var(--sk-text-muted); }
/* The coverage-ribbon column. Given a share of the width rather than left to
   the content, because the ribbon is a bar whose LENGTH is the information --
   a column that resized per row would make two lessons' coverage
   incomparable, which is the one thing this table exists to let an operator
   do. */
.sk-table__ribbon { width: 40%; }
.sk-table__ribbon .ribbon { height: 12px; margin: 0; }

/* A row of filter controls above a table. Wraps rather than scrolls, because
   unlike the table itself these are five independent choices and a hidden
   one is a filter an operator does not know is set. */
.sk-filters { display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
              margin-bottom: 12px; }
.sk-filters .sk-input { width: auto; }
/* A row worth noticing. Amber rather than red: a failed sign-in is a thing to
   look at, not a thing that has gone wrong with the product. */
.sk-table tr.sk-table__row--flag td { background: var(--sk-warning-tint); }

/* Header action (design: the blue "Onboard a school" button in hdrDark).
   Distinct from .sk-hdr__signout, which is the translucent outline treatment
   every screen carries -- this is the one filled control on a dark bar, and
   only appears where the header has something to start rather than end. */
.sk-hdr__action { flex: none; padding: 10px 14px; border-radius: 11px;
                  background: var(--sk-accent); color: #fff; text-decoration: none;
                  font: 700 11.5px/1 var(--sk-font-ui); }
.sk-hdr__action:hover { background: var(--sk-accent-hover); color: #fff; }

/* Status badge on a school register row (design: statusStyle). LIVE, TRIAL
   and PAUSED only -- see School#status for why the design's fourth value,
   BEHIND, has no state here. */
.sk-badge { min-width: 48px; text-align: center; padding: 4px 8px; border-radius: 999px;
            font: 600 8.5px/1.4 var(--sk-font-ui); }
.sk-badge--live      { background: var(--sk-success-tint); color: var(--sk-success); }
.sk-badge--published { background: var(--sk-success-tint); color: var(--sk-success); }
.sk-badge--trial     { background: var(--sk-accent-subtle); color: var(--sk-accent); }
.sk-badge--paused    { background: var(--sk-warning-tint); color: var(--sk-warning); }
.sk-badge--draft     { background: var(--sk-warning-tint); color: var(--sk-warning); }
/* Red is allowed here: this is a staff surface, unrestricted either way.
   tokens.css only narrows red away from a PRIMARY child-facing one (D-02,
   narrowed by D-A) -- .sikai-student--secondary is allowed it too. A
   withdrawn row is the one state worth flagging hardest. */
.sk-badge--retired   { background: var(--sk-error-tint); color: var(--sk-error); }

/* A register row that is a link. .sk-row is a plain flex row shared with
   read-only listings, so the hover and the reset of the UA underline live
   here rather than on it. */
.sk-row--link { text-decoration: none; }
.sk-row--link:hover { background: var(--sk-fill-1); }

/* ---------------------------------------------------------------------------
   School onboarding (design: sa-add-school)
   --------------------------------------------------------------------------- */

/* The design lays the form out as auto-fitting columns of at least 320px, so
   it is three cards side by side on a wide monitor and one column on a
   laptop -- not a fixed three-up grid. */
/* One card per row, full width of the column. The design's own question
   editor is a single scrolling column and its chapter and topic forms did not
   exist to copy, so a side-by-side grid was a choice rather than a
   transcription -- and the wrong one for a form: reading order stopped
   matching tab order, a card that grew (a repeater with six rows in it) left
   a ragged hole beside it, and "the answer" sat off to the right of the
   question it answers.

   --split is the exception, not the default: see below. */
.sk-form { display: flex; flex-direction: column; gap: 16px; }

/* Three short, independent groups that genuinely read better side by side,
   and the one place the design actually specifies the grid (sa-add-school's
   own layout is repeat(auto-fit, minmax(320px, 1fr))). Nothing in it grows,
   so none of the reasons above apply. */
.sk-form--split { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
                  align-content: start; }
/* Cards in the grid size to their own content rather than stretching to match
   the tallest in the row. Only meaningful under --split; a single column has
   nothing to stretch against. */
.sk-form--split > .sk-card { align-self: start; }
/* The two-up pairs inside a card (district/ward, seats/credits, code/username). */
.sk-form__pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; }
.sk-form__group { display: flex; flex-direction: column; gap: 7px; }

/* Repeatable rows for a jsonb list (vocabulary, misconceptions, experiments,
   worked examples). One card per list; each row is its own bordered block so
   an editor can see where one entry ends and the next begins. */
.sk-repeater { display: flex; flex-direction: column; gap: 12px; }
/* Fields inside a row flow into as many columns as fit, which is three for a
   vocabulary entry and two for a misconception at this width. Cards stay one
   per row (see .sk-form) -- this is the fields within one, and stacking three
   one-line inputs vertically made a chapter with six vocabulary terms a page
   nobody would scroll to the end of. */
.sk-repeater__row { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
                    gap: 10px 12px; align-items: start;
                    padding: 14px; border-radius: 14px; background: #FAFAF8;
                    border: 1px solid rgba(23, 24, 26, .07); }
/* A sentence, a one-per-line list, and the row's own control take the full
   width: none of them is one short field among several. Marked by the view
   rather than inferred from the control, because a definition and a term are
   both single-line inputs and only one of them is prose. */
.sk-label--wide,
.sk-repeater__remove { grid-column: 1 / -1; }
.sk-repeater__remove { justify-self: start; padding: 7px 11px; border-radius: 10px;
                       border: 1px solid rgba(23, 24, 26, .14); background: var(--sk-surface);
                       color: var(--sk-text-muted); cursor: pointer;
                       font: 700 10.5px/1 var(--sk-font-ui); }
.sk-repeater__remove:hover { color: var(--sk-error); border-color: rgba(192, 57, 43, .4); }

.sk-label { display: flex; flex-direction: column; gap: 6px; }
.sk-label__text { font: 600 11px/1 var(--sk-font-ui); color: #71757E; }
.sk-input { padding: 12px 13px; border-radius: 12px; border: 1px solid rgba(23, 24, 26, .14);
            background: #FAFAF8; color: var(--sk-ink); outline: none;
            font: 600 13px/1.2 var(--sk-font-ui); width: 100%; }
.sk-input:focus { border-color: var(--sk-accent); }
/* Numbers, codes and usernames are mono in every screen of this design. */
.sk-input--mono { font-family: var(--sk-font-ui); }
.sk-input--code { text-transform: uppercase; }
/* A field holding a small integer -- marks, an order, a count of minutes.
   Full width was fine while these sat in a 320px grid column; in a single
   780px column a one-digit box a third of the page wide reads as though a lot
   more is expected in it. */
.sk-input--narrow { max-width: 160px; }
.sk-textarea { resize: vertical; font: 500 12.5px/1.5 var(--sk-font-ui); }

/* Chips (design: the grade toggles, medium picker and plan picker). The input
   itself is the state -- it stays in the accessibility tree and keeps
   keyboard focus, and the visible chip is its adjacent sibling, so this needs
   no :has() and no JS. */
.sk-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.sk-chip { display: inline-flex; }
.sk-chip__input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.sk-chip__face { display: block; padding: 9px 13px; border-radius: 11px; cursor: pointer;
                 border: 1px solid rgba(23, 24, 26, .14); background: var(--sk-surface);
                 color: #71757E; font: 700 11.5px/1 var(--sk-font-ui); }
.sk-chip__input:checked + .sk-chip__face { border-color: var(--sk-accent);
                                           background: var(--sk-accent-subtle);
                                           color: var(--sk-accent); }
.sk-chip__input:focus-visible + .sk-chip__face { outline: 2px solid var(--sk-accent);
                                                 outline-offset: 2px; }

/* An explanatory panel inside a card (design: the note under the licence
   fields). Neutral, not a warning -- it states how the licence behaves. */
.sk-hint { padding: 13px; border-radius: 13px; background: #FAFAF8;
           border: 1px solid rgba(23, 24, 26, .07);
           font: 500 12px/1.55 var(--sk-font-ui); color: var(--sk-text-2); margin: 0; }

/* Validation failures. Red is allowed here: this is a staff surface,
   unrestricted either way. The ban in tokens.css only narrows red away from
   a PRIMARY child-facing one (D-02, narrowed by D-A) --
   .sikai-student--secondary is allowed it too. */
.sk-errors { padding: 11px 13px; border-radius: 12px; background: var(--sk-error-tint);
             border: 1px solid rgba(214, 74, 45, .25); color: #B23A1B;
             font: 600 11.5px/1.45 var(--sk-font-ui); margin: 0; list-style: none; }
.sk-errors li + li { margin-top: 4px; }

/* The action bar. Sticky rather than the design's fixed footer: this form
   scrolls inside .sk-scroll, and a fixed bar would sit over the last card on
   a short window. */
.sk-formbar { position: sticky; bottom: 0; display: flex; align-items: center; gap: 12px;
              flex-wrap: wrap; padding: 14px 0 0; margin-top: 4px;
              border-top: 1px solid rgba(23, 24, 26, .08); background: var(--sk-page); }
.sk-formbar__summary { flex: 1; min-width: 180px; font: 500 11.5px/1.4 var(--sk-font-ui);
                       color: #71757E; margin: 0; }
.sk-btn { padding: 12px 18px; border-radius: 12px; border: none; cursor: pointer;
          text-decoration: none; font: 700 12px/1 var(--sk-font-ui); }
.sk-btn--primary { background: var(--sk-accent); color: #fff; }
.sk-btn--primary:hover { background: var(--sk-accent-hover); color: #fff; }
.sk-btn--quiet { background: #F0EFEC; color: var(--sk-text-2); }
.sk-btn--quiet:hover { color: var(--sk-ink); }

/* Confirmation screen (design: the saved state of sa-add-school). */
.sk-done { display: flex; flex-direction: column; gap: 14px; }
.sk-done__tick { width: 46px; height: 46px; border-radius: 14px; display: flex;
                 align-items: center; justify-content: center;
                 background: var(--sk-success-tint); color: #1E8A54;
                 font: 800 20px/1 var(--sk-font-ui); }
.sk-done__title { margin: 0; font: 800 20px/1.2 var(--sk-font-ui); color: var(--sk-ink); }
.sk-done__body { margin: 0; font: 500 13px/1.6 var(--sk-font-ui); color: var(--sk-text-2); }
.sk-done__facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
                  gap: 10px; width: 100%; }
.sk-done__fact { padding: 13px; border-radius: 13px; background: #FAFAF8;
                 border: 1px solid rgba(23, 24, 26, .07); }
.sk-done__fact-label { display: block; font: 700 9.5px/1 var(--sk-font-ui); letter-spacing: .12em;
                       text-transform: uppercase; color: var(--sk-text-muted); }
.sk-done__fact-value { display: block; margin-top: 6px; font: 600 15px/1.2 var(--sk-font-ui);
                       color: var(--sk-ink); }
/* The one place the temporary password is ever rendered. */
.sk-credentials { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
                  padding: 13px; border-radius: 13px; background: #FAFAF8;
                  border: 1px solid rgba(23, 24, 26, .07); }
.sk-credentials__who { flex: 1; min-width: 120px; display: flex; flex-direction: column; gap: 2px; }
.sk-credentials__name { font: 600 13px/1.2 var(--sk-font-ui); color: var(--sk-ink); }
.sk-credentials__phone { font: 500 10.5px/1 var(--sk-font-ui); color: var(--sk-text-muted); }
.sk-credentials__user { font: 600 13px/1 var(--sk-font-ui); color: var(--sk-accent); }
.sk-credentials__pwd { font: 600 13px/1 var(--sk-font-ui); letter-spacing: .06em; color: #71757E; }
.sk-steps { display: flex; flex-direction: column; gap: 11px; margin: 0; padding: 0; list-style: none;
            counter-reset: sk-step; }
.sk-steps li { display: flex; gap: 10px; align-items: flex-start; counter-increment: sk-step;
               font: 500 12.5px/1.55 var(--sk-font-ui); color: var(--sk-text-2); }
/* Flex-centred, not `line-height: <box height>; text-align: center`.
   That pair centres a glyph only when the face's ascent and descent are
   balanced around it -- true of the IBM Plex Mono these boxes used to be
   set in, and not a property any replacement face is obliged to share.
   Flex centres the box whatever the metrics inside it. */
.sk-steps li::before { content: counter(sk-step); flex: none; width: 20px; height: 20px;
                       display: flex; align-items: center; justify-content: center;
                       border-radius: 7px; background: var(--sk-accent-subtle);
                       color: var(--sk-accent);
                       font: 700 11px/1 var(--sk-font-ui); }
.sk-done__actions { display: flex; gap: 10px; flex-wrap: wrap; }

/* ---------------------------------------------------------------------------
   Question composer (design: sa-question)
   --------------------------------------------------------------------------- */

/* A form that is one block inside a shared scroll column rather than the
   column itself -- the composer puts cards after it (availability, history)
   that carry their own forms, and nesting those inside this one would be
   invalid HTML. */
.sk-form-page { display: flex; flex-direction: column; gap: 16px; }
/* and its action bar does not stick: the page continues below the form (the
   availability card, the history), so a bar pinned to the bottom of the
   viewport would sit on top of them rather than under the fields it saves. */
.sk-form-page .sk-formbar { position: static; }

/* One mcq option: the radio that marks it correct, and the text of it. The
   input itself carries the state -- it stays in the accessibility tree and
   keeps keyboard focus -- and the visible dot is its sibling, the same shape
   .sk-chip uses. */
.sk-option { display: flex; align-items: center; gap: 12px; padding: 12px 13px;
             border-radius: 14px; background: #FAFAF8;
             border: 1.5px solid rgba(23, 24, 26, .07); }
.sk-option__pick { display: flex; align-items: center; cursor: pointer; }
.sk-option__input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.sk-option__dot { width: 20px; height: 20px; flex: none; border-radius: 50%;
                  border: 1.5px solid rgba(23, 24, 26, .2); display: block;
                  box-sizing: border-box; }
/* Green, not blue: on this surface green means "this is the right one",
   matching the correct-answer treatment a child sees. */
.sk-option__input:checked + .sk-option__dot { border-color: var(--sk-success);
                                              border-width: 6px; }
.sk-option__input:focus-visible + .sk-option__dot { outline: 2px solid var(--sk-accent);
                                                    outline-offset: 2px; }
.sk-option:has(.sk-option__input:checked) { background: var(--sk-success-tint);
                                            border-color: var(--sk-success); }
.sk-option .sk-input { flex: 1; min-width: 0; }
/* Compact, because it sits on the row rather than under it -- the shared
   repeater's "Clear" is a full control below a block of fields, and an option
   is one line. */
.sk-option__remove { flex: none; width: 28px; height: 28px; border-radius: 9px;
                     border: 1px solid rgba(23, 24, 26, .12); background: var(--sk-surface);
                     color: var(--sk-text-muted); cursor: pointer;
                     font: 600 15px/1 var(--sk-font-ui); }
.sk-option__remove:hover { color: var(--sk-error); border-color: rgba(192, 57, 43, .4); }

.sk-visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden;
                      clip-path: inset(50%); white-space: nowrap; }

/* A card that is telling the editor something rather than holding fields --
   today, only the pack-disagreement banner. */
.sk-card--notice { border-color: rgba(201, 162, 39, .4); background: var(--sk-warning-tint); }

/* Revision history. Nothing reviews an edit made here, so this log is the
   only record there is -- it is a list to read, not a table to scan. */
.sk-revisions { display: flex; flex-direction: column; gap: 12px; }
.sk-revision { padding: 12px 13px; border-radius: 13px; background: #FAFAF8;
               border: 1px solid rgba(23, 24, 26, .07); }
.sk-revision__head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin: 0; }
.sk-revision__what { font: 700 11px/1.4 var(--sk-font-ui); color: var(--sk-ink); }
.sk-revision__who { font: 500 11.5px/1.4 var(--sk-font-ui); color: var(--sk-text-2); }
.sk-revision__when { margin-left: auto; font: 500 10.5px/1.4 var(--sk-font-ui);
                     color: var(--sk-text-muted); }
.sk-revision__field { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
                      margin: 8px 0 0; font: 500 12px/1.5 var(--sk-font-ui);
                      color: var(--sk-text-2); }
.sk-revision__name { font: 700 9px/1.4 var(--sk-font-ui); letter-spacing: .1em;
                     text-transform: uppercase; color: var(--sk-text-muted); }
.sk-revision__before { color: var(--sk-text-muted); text-decoration: line-through; }
.sk-revision__after { font-weight: 700; color: var(--sk-ink); }

/* Card header row (sa-topic's "Question bank" title + difficulty pills on
   one line). .sk-card itself stays a plain flex column since every other
   card on the platform is title-then-content with nothing beside the
   title. */
.sk-card__head { display: flex; align-items: center; justify-content: space-between;
                 flex-wrap: wrap; gap: 10px; }

/* Study material blocks (design: blocks). Derived by Sa::TopicMaterial from
   explanation/worked_examples/assets -- never stored as rows -- so a number,
   a name, its kind (CONCEPT, WORKED SOLUTION, STUDY MATERIAL) and its
   rendered size is all a row shows. */
.sk-material { display: flex; flex-direction: column; gap: 8px; }
.sk-material__row { display: flex; align-items: center; gap: 12px; padding: 12px 13px;
                    border-radius: 13px; background: var(--sk-fill-1); }
.sk-material__no { width: 24px; height: 24px; flex: none; border-radius: 8px;
                   display: flex; align-items: center; justify-content: center;
                   background: var(--sk-accent-subtle); color: var(--sk-accent);
                   font: 600 10.5px/1 var(--sk-font-ui); }
.sk-material__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.sk-material__name { font: 600 13px/1.2 var(--sk-font-ui); color: var(--sk-ink); }
.sk-material__kind { font: 500 10.5px/1 var(--sk-font-ui); color: var(--sk-text-muted); }
.sk-material__size { font: 500 11px/1 var(--sk-font-ui); color: #71757E; }

/* The tutor switch (design: chTutorTrack/chTutorKnob), inside the study
   material card where the design puts it. A real track and knob rather than a
   labelled button: it is a state, not an action. button_to wraps it in a
   form, so the <button> is the track and the knob is its only child. */
.sk-switch { display: flex; align-items: center; gap: 14px; padding: 13px 14px;
             border-radius: 14px; background: var(--sk-fill-1); }
.sk-switch__copy { flex: 1; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.sk-switch__label { font: 600 13px/1.2 var(--sk-font-ui); color: var(--sk-ink); }
.sk-switch__note { font: 500 11px/1.45 var(--sk-font-ui); color: #71757E; }
.sk-switch__track { width: 44px; height: 26px; flex: none; border-radius: 13px; border: none;
                    cursor: pointer; background: var(--sk-fill-5); display: flex;
                    align-items: center; justify-content: flex-start; padding: 3px;
                    box-sizing: border-box; }
.sk-switch__track--on { background: var(--sk-accent); justify-content: flex-end; }
.sk-switch__knob { width: 20px; height: 20px; border-radius: 50%; background: #fff; display: block; }

/* Question bank rows (design: bank). The stem on top, then the tags that say
   what kind of question it is -- no answer or solution text, since this is
   the list an editor scans rather than one question's composer. */
.sk-questions { display: flex; flex-direction: column; gap: 8px; }
.sk-question-row { display: flex; align-items: center; gap: 12px; padding: 12px 13px;
                   border-radius: 13px; background: var(--sk-fill-1); text-decoration: none; }
.sk-question-row:hover { background: var(--sk-fill-2); }
.sk-question-row__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.sk-question-row__stem { font: 500 12.5px/1.45 var(--sk-font-ui); color: var(--sk-ink); }
.sk-question-row__tags { display: flex; gap: 6px; flex-wrap: wrap; }
.sk-question-row__go { flex: none; font: 600 15px/1 var(--sk-font-ui); color: var(--sk-fill-6); }
.sk-tag { padding: 4px 8px; border-radius: 999px; background: var(--sk-surface);
          border: 1px solid rgba(23, 24, 26, .08);
          font: 600 8.5px/1.4 var(--sk-font-ui); letter-spacing: .04em;
          text-transform: uppercase; color: #71757E; }
/* Where the question came from, which is the one tag worth telling apart from
   the three that only describe it. */
.sk-tag--source { background: var(--sk-accent-subtle); border-color: transparent;
                  color: var(--sk-accent); }

/* The two-step reset disclosure on a family or school page.

   A <details> rather than a turbo_confirm, because the form inside must
   carry data-turbo="false": Sa::ParentPinResetsController and its siblings
   RENDER the new credential instead of redirecting (it must not travel in
   the flash), and Turbo Drive discards a 200 HTML response to a form POST
   outright -- "Form responses must redirect to another location". Opting out
   of Turbo also opts out of turbo_confirm, so the deliberate second action
   moves into the markup, where it needs no JavaScript at all and states the
   consequence in place rather than in a dialog that is dismissed. */
.sk-reset { display: grid; gap: 10px; }

.sk-reset__toggle {
  display: inline-flex; align-items: center; min-height: 40px;
  font: 600 13px/1.5 var(--sk-font-ui); color: var(--sk-text-2);
  text-decoration: underline; text-underline-offset: 3px; cursor: pointer;
}

.sk-reset__toggle:focus-visible {
  outline: 2px solid var(--sk-accent); outline-offset: 2px; border-radius: 6px;
}

/* Only once open. A shut disclosure is one line and should not reserve the
   space its body will need. */
.sk-reset[open] { padding: 12px 0 4px; }

/* Under the sign-in card, not inside it: the card is the task, and the way
   out of a forgotten password is a footnote to it. Only the staff sign-in
   has one -- a super admin's password reset is a support call, not a link. */
.sk-signin__aside { margin: 16px 0 0; text-align: center; font-size: 13px; }
.sk-link { color: var(--sk-accent); font-weight: 600; text-decoration: none; }
.sk-link:hover { text-decoration: underline; }

/* The logo in both sign-in doors is a link to the landing page now.

   `a.` rather than the bare class: these screens render in the plain
   application layout, whose .app-legacy a rule is (0,2,0) and would
   otherwise paint the wordmark link-blue. The element selector takes this
   to (0,1,1)+(0,1,0) and settles it without an !important. */
a.sk-signin__home { display: flex; align-items: center; gap: 10px;
                    color: inherit; text-decoration: none; }
a.sk-signin__home:focus-visible { outline: 2px solid var(--sk-accent);
                                  outline-offset: 4px; border-radius: 8px; }

/* PIN slips. There is no PDF gem in this app and none is wanted: a print
   stylesheet prints from whatever machine a school has, and a school office
   printer is the only consumer. */
.sk-slips { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.sk-slip { padding: 16px; border: 1px dashed var(--sk-fill-6); border-radius: 12px; }
.sk-slip__who { font: 700 15px/1.2 var(--sk-font-ui); color: var(--sk-ink); }
.sk-slip__field { display: flex; justify-content: space-between; margin-top: 8px;
                  font: 600 13px/1 var(--sk-font-ui); }
.sk-slip__label { color: var(--sk-text-2); }

/* Scoped to body.sk-print-slips, which only teach/pin_slips/create sets (via
   content_for :body_class -- see layouts/school.html.erb). Unscoped, this
   block reached every screen in the product that links this bundle: /sa,
   /school and /parents all call stylesheet_link_tag :app, so printing any of
   them lost its header, nav, subhead, every .sk-btn and every .sk-note --
   including notes those screens are specified to carry, like the licence
   line and the roster's never-signed-in count. A body class rather than a
   wrapper element because .sk-hdr and .sk-tabs render in the layout, outside
   <main>, where nothing a screen renders can reach them. */
@media print {
  /* Everything that is not a slip. A teacher printing a class does not want
     the nav, the header or the warning they have already read. */
  body.sk-print-slips .sk-hdr,
  body.sk-print-slips .sk-tabs,
  body.sk-print-slips .sk-subhead,
  body.sk-print-slips .sk-note,
  body.sk-print-slips .sk-btn { display: none !important; }
  /* .sk-scroll's own overflow: auto and 780px column cap (further up this
     file) are screen-only concerns -- some print engines clip an
     overflow:auto box's content instead of paginating it, and the cap would
     waste half of every printed sheet on margin the slips could use. */
  body.sk-print-slips .sk-scroll { overflow: visible; max-width: none; }
  body.sk-print-slips .sk-slips { grid-template-columns: repeat(2, 1fr); gap: 0; }
  body.sk-print-slips .sk-slip { break-inside: avoid; border-style: solid; }
}

/* Tabular figures, which the mono used to supply by construction -- see the
   longer note in parents.css. Every count, code, size, date and credential
   on these screens sits in a column beside another one, and Manrope's
   numerals are proportional.

   .sk-credentials__* is an operator's list, not a child's: the username and
   generated password shown once on sa/schools/created, sa/schools/edit and
   sa/parents/created, read down a column by whoever is setting the account
   up. A password whose characters do not line up is one that gets read out
   wrong over a phone.

   NOT the printed PIN slips, which is what an earlier draft of this note
   claimed. Those are .sk-slip__*, they have always been set in
   --sk-font-ui, and nothing in the move off IBM Plex Mono touched them. */
.sk-stat__n,
.sk-subject-row__counts,
.sk-chapter__no,
.sk-chapter__meta,
.sk-topic-row__meta,
.sk-revision__when,
.sk-material__size,
.sk-row__code,
.sk-table__code,
.sk-facts__mono,
.sk-input--mono,
.sk-done__fact-value,
.sk-gate__url,
.sk-credentials__user,
.sk-credentials__pwd,
.sk-credentials__phone {
  font-variant-numeric: tabular-nums;
}
