/* ==========================================================================
   Academy pages: landing, login, dashboard, courses
   ========================================================================== */

/* ---------------- Hero ---------------- */
.hero {
  position: relative; color: #fff; text-align: center;
  /* The forest with its baked-in fireflies removed - those are now the animated
     canvas layer in js/fireflies.js. Two sets of fireflies, one of them frozen,
     looked exactly as odd as it sounds. */
  background: var(--body-bg) url('../assets/hero-woods.webp') center / cover no-repeat;
  /* Matches the marketing hero's proportions. The source is 1600x900, so a
     short wide box crops hard and upscales; more height keeps the forest
     legible instead of looking soft. */
  padding: 110px 0 124px;
  overflow: hidden;               /* halos are wide; do not let them bleed out */
}
.hero::before {
  content: ''; position: absolute; inset: 0;
  /* Same overlay values as the marketing hero. The previous .35/.7 crushed an
     already dark image and read as low resolution. */
  background: linear-gradient(180deg, rgba(16,25,35,.25), rgba(16,25,35,.45));
}
/* Above the darkening overlay, or it mutes the glows; below .container, so
   nothing competes with the headline. The canvas is appended after ::before, so
   at the same stacking level it paints on top. pointer-events off because this
   sits over the CTA buttons. */
.hero .firefly-layer {
  position: absolute; inset: 0; z-index: 0;
  pointer-events: none;
}
.hero .container { position: relative; z-index: 1; max-width: 900px; }
.hero .kick {
  font-family: var(--font-label); font-size: 17px; font-weight: 500;
  letter-spacing: 5px; text-transform: uppercase; color: var(--yellow);
  margin-bottom: 20px;
}
.hero h1 { font-size: clamp(32px, 4.6vw, 54px); color: #fff; letter-spacing: -0.04em; margin-bottom: 18px; }
.hero p { font-family: var(--font-head); font-weight: 600; font-size: 18px;
  letter-spacing: -0.04em; max-width: 700px; margin: 0 auto 28px; }
.hero .btn-row { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }

/* ---------------- Sections ---------------- */
.section { padding: 72px 0; }
.section.tint { background: var(--accent-soft); }
.section.pale { background: #F7FAFD; }
.section h2 { font-size: clamp(26px, 3.2vw, 38px); color: var(--ink); }
.section .lede { color: var(--text-mid); max-width: 720px; margin-top: 10px; }
.center { text-align: center; }
.center .lede { margin-left: auto; margin-right: auto; }

.grid { display: grid; gap: 24px; margin-top: 40px; }
.grid.g3 { grid-template-columns: repeat(3, 1fr); }
.grid.g4 { grid-template-columns: repeat(4, 1fr); }

.card {
  background: #fff; border: 1px solid var(--line); border-radius: 12px;
  padding: 26px 24px;
  /* Two shadows: a tight one for the edge, a soft one for the float. See the
     shared card block in shell.css. */
  box-shadow: 0 1px 2px rgba(16,24,40,.06), 0 8px 24px -4px rgba(16,24,40,.08);
}
.card h3 { color: var(--ink); font-size: 18px; margin-bottom: 8px; }
.card p { font-size: 15px; color: var(--text-mid); }
/* Four across, one of these headings wraps to two lines and the others do
   not, which drops that card's body copy a line below its neighbours.
   Reserve two lines for all of them so the paragraphs share a baseline.
   Released at 720px, where the cards stack and it stops mattering. */
.grid.g4 .card h3 { min-height: 2.3em; }

/* Line icon in a blue disc, matching the marketing site's format cards.
   Deliberately not emoji: the brand uses those sparingly, and a row of them
   reads as clip art rather than as a product. */
.ico-circle {
  width: 46px; height: 46px; border-radius: 50%; background: var(--accent);
  display: grid; place-items: center; margin-bottom: 16px;
}
.center .ico-circle, .grid.g4 .ico-circle { margin-left: auto; margin-right: auto; }
.ico-circle svg { width: 23px; height: 23px; stroke: #fff; fill: none;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* ---------------- Course cards ---------------- */
.course-card {
  background: #fff; border: 1px solid var(--line); border-radius: 14px;
  overflow: hidden; box-shadow: 0 6px 24px rgba(16,24,40,.06);
  display: flex; flex-direction: column;
}
.course-card .cc-top {
  background: linear-gradient(135deg, #00128D 0%, #0635CB 45%, #1046DC 70%, #2F78ED 100%);
  padding: 26px 24px; color: #fff;
}
.course-card .cc-top .kick {
  font-family: var(--font-label); font-size: 11px; letter-spacing: 2px;
  text-transform: uppercase; color: #66DEF9; margin-bottom: 6px;
}
.course-card .cc-top h3 { color: #fff; font-size: 23px; }
.course-card .cc-body { padding: 22px 24px; flex: 1; display: flex; flex-direction: column; }
.course-card .cc-body p { font-size: 15px; color: var(--text-mid); margin-bottom: 16px; }
.course-card .cc-stats {
  display: flex; gap: 18px; font-family: var(--font-label); font-size: 12.5px;
  color: var(--text-mid); margin-bottom: 18px; flex-wrap: wrap;
}
.course-card .cc-foot {
  margin-top: auto; display: flex; align-items: center; gap: 12px;
  /* A price plus two buttons does not fit a three-up card at every width. Let
     the actions drop to their own line rather than squeezing the buttons or
     letting the price collide with them. */
  flex-wrap: wrap; row-gap: 12px;
}
/* The CTA is always the last child, and it always sits right. Without this, a
   card with a progress bar right-aligned its button (the bar flexes and pushes
   it) while a card with a lone button left-aligned it, so the two cards in the
   grid disagreed with each other. */
.course-card .cc-foot > :last-child { margin-left: auto; }
/* Two buttons, wrapped so the rule above still has ONE last child to push
   right. Unwrapped, that auto margin would land between View course and Add to
   cart and split the pair across the width of the card. */
.cc-actions { display: flex; align-items: center; gap: 8px; }
.cc-price { font-family: var(--font-label); font-size: 14px; font-weight: 700;
  color: var(--text-strong, #142A40); }
.cc-pct { font-family: var(--font-label); font-size: 12.5px; color: var(--text-mid); }
.badge-done { background: #E8F5E9; color: #2E7D32; border: 1px solid #C3E6C6;
  font-family: var(--font-label); font-size: 11.5px; letter-spacing: 1px;
  text-transform: uppercase; padding: 4px 9px; border-radius: 4px; font-weight: 700; }

.mini-progress { flex: 1; height: 7px; background: #EDF1F6; border-radius: 5px; overflow: hidden; }
.mini-progress span { display: block; height: 100%; background: linear-gradient(90deg, #2B64F8, #66DEF9); border-radius: 5px; }

/* ---------------- Auth ---------------- */
.auth-wrap { display: grid; place-items: center; padding: 60px 24px; flex: 1; background: #F7FAFD; }
.auth-card {
  background: #fff; border: 1px solid var(--line); border-radius: 14px;
  padding: 38px 34px; width: 100%; max-width: 440px;
  box-shadow: 0 10px 34px rgba(16,24,40,.08);
}
.auth-card h1 { font-size: 27px; color: var(--ink); margin-bottom: 6px; }
.auth-card .sub { color: var(--text-mid); font-size: 15px; margin-bottom: 24px; }
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
.field label {
  font-family: var(--font-label); font-size: 12px; font-weight: 600;
  letter-spacing: 1.4px; text-transform: uppercase; color: var(--text-mid);
}
.field input, .field select, .field textarea {
  font-family: var(--font-body); font-size: 15px; color: var(--ink);
  padding: 12px 13px; border: 1px solid #C9D6E4; border-radius: var(--radius);
  background: #fff; outline: none; transition: border-color .2s, box-shadow .2s;
}
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--accent); box-shadow: 0 0 0 3px rgba(43,100,248,.15);
}
/* Helper text under an input. Was three copies of an inline style; a note
   that explains why a field is read-only is part of the form, not decoration. */
.field-note { font-size: 13px; color: var(--text-mid); line-height: 1.5; }
.field-note strong { color: var(--text-strong, #142A40); }
.field input:disabled, .field textarea:disabled {
  background: #F4F7FB; color: #5B7186; cursor: not-allowed; }

.form-msg { font-size: 14px; margin-top: 12px; }
.form-msg.err { color: var(--warn); }
.form-msg.ok { color: var(--ok); }
.auth-alt { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--line);
  font-size: 14px; color: var(--text-mid); }
.hint-box {
  background: #FFF8E1; border: 1px solid #F0E0A0; border-radius: 8px;
  padding: 12px 14px; font-size: 13px; color: #7A5C00; margin-bottom: 20px;
}
.hint-box code { font-family: Consolas, monospace; background: rgba(0,0,0,.06); padding: 1px 5px; border-radius: 3px; }

/* ---------------- Dashboard ---------------- */
.dash-head { background: var(--panel-dark); color: #fff; padding: 40px 0 64px; }
.dash-head .container { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.dash-head h1 { color: #fff; font-size: 30px; }
.dash-head .sub { color: rgba(255,255,255,.6); font-family: var(--font-label); font-size: 13.5px; }
/* -44px against 64px of header padding, so the cards straddle the boundary
   deliberately instead of dangling off the edge of it */
.stat-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; margin-top: -44px; }
.stat {
  background: #fff; border: 1px solid var(--line); border-radius: 12px; padding: 20px;
  box-shadow: 0 6px 20px rgba(16,24,40,.07);
}
.stat .n { font-family: var(--font-head); font-weight: 600; font-size: 30px; color: var(--ink); line-height: 1; }
.stat .l { font-family: var(--font-label); font-size: 11.5px; letter-spacing: 1.2px;
  text-transform: uppercase; color: var(--text-mid); margin-top: 6px; }

.table { width: 100%; border-collapse: collapse; background: #fff; }
.table th, .table td { text-align: left; padding: 13px 14px; border-bottom: 1px solid var(--line); font-size: 14.5px; }
.table th {
  font-family: var(--font-label); font-size: 11.5px; letter-spacing: 1.2px;
  text-transform: uppercase; color: var(--text-mid); background: #F7FAFD;
}
.table tbody tr:hover { background: #FAFCFE; }
/* overflow-x, not hidden. A hidden overflow does not crop a wide table
   gracefully on a phone: it makes the right-hand columns unreachable, with
   no scroll to get at them. Every admin table sits in one of these. */
.table-wrap { border: 1px solid var(--line); border-radius: 12px;
  overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; }

@media (max-width: 1000px) {
  .grid.g4 { grid-template-columns: repeat(2, 1fr); }
  .stat-row { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 720px) {
  .grid.g3, .grid.g4 { grid-template-columns: 1fr; }
  .grid.g4 .card h3 { min-height: 0; }
}

/* ---------------- Admin tables on a phone ----------------
   Tables marked .table-cards stop being tables and become one card per
   record: the header row is dropped and every cell carries its own label
   from data-label. Nothing is off-screen, so nothing needs a sideways
   scroll to reach - which matters most for the row actions, the whole point
   of opening this page on a phone.
   Rows keep their <tr>/<td> structure, so the inline editor still inserts
   itself as a full-width row underneath the record it belongs to.

   Two triggers, because width alone misses the case that prompted this: a
   phone in LANDSCAPE is wide (~800px) but only ~375px tall, so it would get
   the desktop table and push the actions off the right edge again. The
   short-and-landscape query catches it; a real tablet or a narrow desktop
   window is taller than 500px and keeps the table. */
@media (max-width: 760px), (orientation: landscape) and (max-height: 500px) {
  .table-cards { border-collapse: separate; border-spacing: 0; }
  .table-cards thead { display: none; }
  .table-cards tbody, .table-cards tr, .table-cards td { display: block; width: auto; }
  .table-cards tbody tr {
    padding: 14px 14px 10px; border-bottom: 8px solid #F1F5FA; position: relative;
  }
  .table-cards tbody tr:last-child { border-bottom: 0; }
  .table-cards tbody tr:hover { background: transparent; }
  .table-cards td {
    border: 0; padding: 5px 0; font-size: 15px;
    display: flex; align-items: baseline; gap: 12px;
    /* a long unbroken email or code cannot shrink a flex item on its own
       (min-width defaults to auto), so it pushes the card wider than the
       screen. Both halves of this fix are needed. */
    overflow-wrap: anywhere;
  }
  .table-cards td > * { min-width: 0; max-width: 100%; }
  /* label column, from data-label */
  .table-cards td::before {
    content: attr(data-label);
    flex: 0 0 40%; max-width: 40%;
    font-family: var(--font-label); font-size: 10.5px; letter-spacing: 1.1px;
    text-transform: uppercase; color: var(--text-mid);
  }
  /* the identity cell leads the card: no label, full width, bigger */
  .table-cards td[data-label=""] { display: block; padding: 0 0 8px; }
  .table-cards td[data-label=""]::before { content: none; }
  .table-cards td[data-label=""] strong { font-size: 17px; }
  /* a cell can opt out of the card entirely (noise on a small screen) */
  .table-cards td[data-mobile="hide"] { display: none; }
  /* a cell that truncates to one line on desktop (a message preview) gets
     the card's full width and wraps instead - reading it is the point */
  .table-cards td.cell-wrap {
    display: block; max-width: none !important;
    white-space: normal !important; overflow: visible !important;
  }
  .table-cards td.cell-wrap::before { display: block; margin-bottom: 2px; max-width: none; }
  /* buttons inside an actions cell stretch too, whatever their class */
  .table-cards td[data-label="Actions"] .btn { flex: 1 1 0; min-height: 42px; }
  /* actions become real tap targets, side by side, full width */
  .table-cards td[data-label="Actions"] { display: flex; gap: 10px; padding-top: 10px; }
  .table-cards td[data-label="Actions"]::before { content: none; }
  /* every action reads as a button, whatever it was written as: some rows
     use .linkish, some a .btn, some a bare <a> with a middot between */
  .table-cards td[data-label="Actions"] .linkish,
  .table-cards td[data-label="Actions"] > a {
    flex: 1 1 0; min-height: 42px; display: inline-flex; align-items: center;
    justify-content: center; border: 1px solid #C9D6E4; border-radius: var(--radius);
    background: #fff; font-size: 15px; text-decoration: none; color: var(--accent);
  }
  .table-cards td[data-label="Actions"] .linkish:hover,
  .table-cards td[data-label="Actions"] > a:hover { background: #F5F8FF; }
  /* the separators between bare links are noise once they are buttons */
  .table-cards td[data-label="Actions"] { font-size: 0; }
  .table-cards td[data-label="Actions"] > * { font-size: 15px; }
  /* The editor row spans the card, not a 7-column grid. Its cell must opt
     out of BOTH the flex layout and the label pseudo-element above: with
     them it inherits a 40% label gutter it has no label for, and the panel
     is shoved off the right edge. */
  .table-cards tr.ue-row { padding: 0; border-bottom: 8px solid #F1F5FA; }
  .table-cards tr.ue-row td { display: block; padding: 0; }
  .table-cards tr.ue-row td::before { content: none; }
  .table-cards tr.ue-row .user-editor { margin: 0; border-radius: 0; }
  .table-cards tr.editing { background: #F5F8FF; }
  /* the wrap no longer scrolls sideways - there is nothing off to the side */
  .table-wrap.cards-on-mobile { overflow-x: visible; }

  /* toolbar stacks: full-width search, then count, then the action */
  .admin-toolbar { flex-wrap: wrap; gap: 10px; }
  .admin-toolbar input[type="search"] { flex: 1 1 100%; min-height: 44px; }
  .admin-toolbar .btn { margin-left: 0 !important; min-height: 44px; }
  .admin-toolbar #userCount, .admin-toolbar .field-note { flex: 1 1 auto; }

  /* The chat launcher is fixed to the bottom-right and sat on top of the
     last row's actions. It is not hidden here: the same widget's panel is
     what the Chat and Open buttons open, so removing it would break them.
     Instead every admin panel ends with enough room to scroll clear of it. */
  .admin-panel { padding-bottom: 92px; }
}

/* ---------------- Course detail + cart ---------------- */
.back-link { font-family: var(--font-label); font-size: 13px; color: var(--link-blue, #2B64F8);
  text-decoration: none; display: inline-block; margin-bottom: 18px; }
.back-link:hover { text-decoration: underline; }
.container.narrow { max-width: 760px; }

.course-detail { display: grid; grid-template-columns: 1fr 320px; gap: 40px; align-items: start; }
.course-detail h1 { font-size: clamp(28px, 3.4vw, 40px); letter-spacing: -0.03em; margin: 6px 0 14px; }
.course-detail h3 { margin: 34px 0 12px; font-size: 19px; }

.cd-stats { display: flex; flex-wrap: wrap; gap: 26px; margin: 24px 0 6px;
  padding: 18px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.cd-stats div { display: flex; flex-direction: column; }
.cd-stats b { font-family: var(--font-head); font-size: 22px; color: var(--text-strong, #142A40); }
.cd-stats span { font-family: var(--font-label); font-size: 11.5px; letter-spacing: 1px;
  text-transform: uppercase; color: var(--text-mid); margin-top: 2px; }

.cd-list { margin: 0; padding-left: 20px; }
.cd-list li { margin: 7px 0; }

.cd-mods { display: flex; flex-direction: column; gap: 8px; }
.cd-mod { border: 1px solid var(--line); border-radius: 9px; background: #fff; overflow: hidden; }
.cd-mod summary { cursor: pointer; padding: 13px 16px; display: flex; align-items: center;
  gap: 12px; list-style: none; }
.cd-mod summary::-webkit-details-marker { display: none; }
.cd-mod summary::after { content: '+'; margin-left: auto; font-family: var(--font-label);
  color: var(--text-mid); font-size: 17px; line-height: 1; }
.cd-mod[open] summary::after { content: '\2212'; }
.cd-mod .cm-t { font-weight: 700; }
.cd-mod .cm-m { font-family: var(--font-label); font-size: 11.5px; color: var(--text-mid);
  margin-left: 10px; white-space: nowrap; }
.cd-mod ul { margin: 0; padding: 0 16px 14px 16px; list-style: none; }
.cd-mod li { display: flex; align-items: center; gap: 10px; padding: 6px 0;
  font-size: 14.5px; border-top: 1px solid #F1F5F9; }
.cu-type { font-family: var(--font-label); font-size: 10px; letter-spacing: .6px;
  text-transform: uppercase; padding: 2px 7px; border-radius: 3px; flex: none;
  min-width: 74px; text-align: center; background: #EEF3FA; color: #5B7186; }
.cu-type.t-lab { background: #FFF3E9; color: #D95F1A; }
.cu-type.t-quiz { background: #EAF1FE; color: #1046DC; }
.cu-type.t-challenge { background: #FDECEF; color: #C62838; }
.cu-type.t-cinematic { background: #142A40; color: #66DEF9; }

/* Sticky so the price and the button stay reachable through a long curriculum. */
.cd-side { position: sticky; top: calc(var(--header-h, 76px) + 20px); }
.action-panel { border: 1px solid var(--line); border-radius: 12px; padding: 22px;
  background: #fff; box-shadow: 0 8px 26px rgba(20,42,64,.07); }
.action-panel .ap-price { font-family: var(--font-head); font-size: 34px; font-weight: 700;
  color: var(--text-strong, #142A40); letter-spacing: -0.03em; }
.action-panel .ap-note { font-size: 13.5px; color: var(--text-mid); margin: 8px 0 16px; }
.action-panel .ap-fine { font-size: 12.5px; color: var(--text-mid); margin: 12px 0 0; }
.action-panel .btn { width: 100%; justify-content: center; }
.action-panel .btn + .btn { margin-top: 9px; }
.action-panel .mini-progress { margin-bottom: 10px; }
.btn-lg { padding: 13px 22px; font-size: 15px; }
.btn-block { width: 100%; justify-content: center; }

.cart-table { width: 100%; border-collapse: collapse; }
.cart-table td { padding: 15px 0; border-bottom: 1px solid var(--line); vertical-align: middle; }
.cart-table td b { display: block; }
.cart-table td span { font-family: var(--font-label); font-size: 12px; color: var(--text-mid); }
.cart-table .ct-price { text-align: right; font-family: var(--font-head); font-weight: 700;
  white-space: nowrap; }
.cart-table .ct-rm { text-align: right; width: 84px; }
.linkish { background: none; border: 0; padding: 0; cursor: pointer; font: inherit;
  font-size: 13px; color: var(--text-mid); text-decoration: underline; }
.linkish:hover { color: #C62838; }

.cart-coupon { margin: 26px 0 8px; }
.cart-coupon label { display: block; font-family: var(--font-label); font-size: 11.5px;
  letter-spacing: 1px; text-transform: uppercase; color: var(--text-mid); margin-bottom: 7px; }
.cart-coupon .cc-row { display: flex; gap: 10px; }
.cart-coupon input { flex: 1; padding: 11px 13px; border: 1px solid var(--line);
  border-radius: 7px; font: inherit; font-size: 15px; text-transform: uppercase; }
.cc-msg { font-size: 13px; margin-top: 8px; min-height: 1em; }
.cc-msg.bad { color: #C62838; }

.cart-totals { margin: 22px 0; border-top: 1px solid var(--line); padding-top: 14px; }
.cart-totals div { display: flex; justify-content: space-between; padding: 5px 0; font-size: 14.5px; }
.cart-totals .ct-off { color: #2E7D32; }
.cart-totals .ct-net { border-top: 1px solid var(--line); margin-top: 8px; padding-top: 12px;
  font-family: var(--font-head); font-size: 19px; font-weight: 700; }

.empty-state { text-align: center; padding: 50px 0; }
.empty-state p { color: var(--text-mid); margin-bottom: 18px; }

.nav-cart .cart-count { display: inline-block; min-width: 18px; height: 18px; line-height: 18px;
  border-radius: 9px; background: #F37934; color: #fff; font-family: var(--font-label);
  font-size: 11px; font-weight: 700; text-align: center; margin-left: 6px; padding: 0 5px; }

@media (max-width: 900px) {
  .course-detail { grid-template-columns: 1fr; }
  .cd-side { position: static; }
}

/* ---------------- Admin: users ---------------- */
.admin-toolbar { display: flex; align-items: center; gap: 14px; margin-top: 16px; }
.admin-toolbar input[type="search"] {
  flex: 0 1 320px; padding: 10px 13px; border: 1px solid #C9D6E4;
  border-radius: var(--radius); font: inherit; font-size: 15px; outline: none;
}
.admin-toolbar input[type="search"]:focus {
  border-color: var(--accent); box-shadow: 0 0 0 3px rgba(43,100,248,.15);
}

.user-editor { margin-top: 22px; border-left: 4px solid var(--accent); }
.user-editor .ue-head { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 18px; }
.user-editor .ue-head h3 { margin: 0 0 2px; }
.user-editor .ue-head button { margin-left: auto; }
.user-editor .ue-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.user-editor .ue-check { display: flex; align-items: center; gap: 9px; cursor: pointer;
  font-family: var(--font-body); font-size: 15px; text-transform: none;
  letter-spacing: 0; color: var(--ink); font-weight: 400; }
.user-editor .ue-check input { width: 17px; height: 17px; cursor: pointer; }
.user-editor .ue-actions { display: flex; gap: 10px; margin-top: 20px; flex-wrap: wrap; }

@media (max-width: 760px) { .user-editor .ue-grid { grid-template-columns: 1fr; } }

/* Course access rows in the admin user editor. Not checkboxes: access has
   state (active until a date, ended on a date, never granted) that a tick box
   cannot express, and instant-apply ticks sat oddly beside fields that need
   Save. Buttons read as "this happens now". */
/* The student's rail, as the admin sees it. Scrolls rather than running to
   sixty-four rows down the page: this sits inside a form the admin is also
   using for other things, and a control that pushes Save off the screen stops
   being a control. */
.ue-rail {
  margin-top: 8px; max-height: 320px; overflow-y: auto;
  border: 1px solid var(--line); border-radius: 9px; background: #fff;
}
.ue-railrow {
  display: flex; align-items: center; gap: 12px;
  padding: 7px 12px; border-bottom: 1px solid var(--line-soft, #EEF1F5);
}
.ue-railrow:last-child { border-bottom: 0; }
.ue-railrow.done { background: #F6FBF7; }
.ue-railrow .ue-check { flex: 1; min-width: 0; gap: 11px; }
.ue-railno {
  font-family: Consolas, monospace; font-size: 12px; color: var(--text-mid);
  min-width: 26px; text-align: right;
}
.ue-railtitle {
  font-size: 14px; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ue-railtype {
  font-size: 11px; letter-spacing: 1.2px; text-transform: uppercase;
  color: var(--text-mid); flex: 0 0 82px;
}
.ue-railnote { font-size: 11.5px; color: var(--text-mid); font-style: italic; }
.ue-railjump {
  font-size: 12px; padding: 4px 10px; border-radius: 6px; cursor: pointer;
  border: 1px solid var(--line); background: #fff; color: var(--text-mid);
}
.ue-railjump:hover { border-color: var(--blue, #2B64F8); color: var(--blue, #2B64F8); }
.ue-railjump:disabled { opacity: .5; cursor: default; }

.ue-courses { display: flex; flex-direction: column; gap: 10px; margin-top: 6px; }
.ue-course { display: flex; align-items: center; gap: 16px; padding: 13px 15px;
  border: 1px solid var(--line); border-radius: 9px; background: #fff; }
.ue-course .uc-main { flex: 1; min-width: 0; }
.ue-course .uc-t { font-weight: 600; color: var(--ink); font-size: 15px; }
.ue-course .uc-s { font-size: 13px; color: var(--text-mid); margin-top: 3px;
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ue-course .uc-s b { color: var(--ink); font-weight: 600; }
.ue-course .uc-a { display: flex; gap: 8px; flex: none; }
.cs-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.cs-dot.ok { background: #2E7D32; }
.cs-dot.off { background: #C9A227; }
.cs-dot.none { background: #C9D6E4; }
.cs-warn { color: #C62838; font-weight: 600; }
.cs-none { color: #9AA7B6; }
.btn-sm { padding: 7px 13px; font-size: 13px; }
.btn-ghost.danger { color: #C62838; }
.btn-ghost.danger:hover { background: #FDECEF; }
.user-editor select { padding: 11px 13px; border: 1px solid #C9D6E4;
  border-radius: var(--radius); font: inherit; font-size: 15px; background: #fff; }

/* Destructive action. Deliberately not the same blue as everything else - a
   delete button that looks like a save button gets pressed by accident. */
.btn-danger { background: #C62838; color: #fff; border: 1px solid #C62838; }
.btn-danger:hover { background: #A81F2D; border-color: #A81F2D; }

/* ==========================================================================
   Course window countdown
   Rendered by Academy.shell.paintCountdowns into any [data-expires] element.
   Three tones because "60 days left" and "3 hours left" are not the same
   message and should not look the same.
   ========================================================================== */
.countdown {
  display: inline-block; font-family: var(--font-label); font-size: 11.5px;
  letter-spacing: .6px; padding: 4px 9px; border-radius: 999px;
  border: 1px solid transparent; white-space: nowrap;
}
.countdown.ok     { background: #EDF4FF; color: #2B5FCC; border-color: #D6E4FB; }
.countdown.warn   { background: #FFF6E6; color: #9A6412; border-color: #F6E3C0; }
/* Red, and the only one that ticks. It has to look different from "getting on
   with it" or the last two days read the same as the first eighty-eight. */
.countdown.urgent { background: #FDECEE; color: #B4232F; border-color: #F6CDD2; }
.countdown.over   { background: #F1F4F8; color: #5B7186; border-color: #E1E9F2; }

/* On a course card the title and the chip share a row: the chip must not push
   a long course title into a second line. */
.course-card .cc-top { display: flex; align-items: flex-start; gap: 10px;
  flex-wrap: wrap; }
.course-card .cc-top .kick { flex: 1 0 100%; }
.course-card .cc-top h3 { flex: 1 1 auto; margin: 0; }
.course-card .cc-top .countdown { flex: 0 0 auto; margin-top: 2px; }

.rail-head .countdown { margin-top: 10px; }

/* Admin course-control widgets (the player-side lock and maintenance styles
   live in player.css - learn.html does not load this file). */
/* Slide toggle for the admin course controls. */
.switch { position: relative; display: inline-block; width: 46px; height: 26px;
  flex: 0 0 auto; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch .slider { position: absolute; inset: 0; cursor: pointer;
  background: #C9D6E4; border-radius: 999px; transition: background .15s; }
.switch .slider::before { content: ''; position: absolute; width: 20px; height: 20px;
  left: 3px; top: 3px; background: #fff; border-radius: 50%; transition: transform .15s;
  box-shadow: 0 1px 3px rgba(16,24,40,.3); }
.switch input:checked + .slider { background: var(--accent); }
.switch input:checked + .slider::before { transform: translateX(20px); }
.switch input:disabled + .slider { opacity: .5; cursor: wait; }

.ctl-row { display: flex; align-items: center; gap: 14px; padding: 13px 0;
  border-bottom: 1px solid var(--line); }
.ctl-row:last-child { border-bottom: 0; }
.ctl-row .ctl-name { flex: 1 1 auto; font-weight: 600; color: var(--ink); }
.ctl-row .ctl-name small { display: block; font-weight: 400; font-size: 12.5px;
  color: var(--text-mid); }
.ctl-row label.ctl { display: flex; align-items: center; gap: 8px;
  font-family: var(--font-label); font-size: 11.5px; letter-spacing: 1px;
  text-transform: uppercase; color: var(--text-mid); }

/* Presence: the green "online now" dot in the admin users list. */
.live-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%;
  background: #2E7D32; margin-right: 7px; vertical-align: 1px;
  box-shadow: 0 0 0 3px rgba(46,125,50,.18); }

/* Course-completion feedback card on the dashboard. */
.fb-card { border-left: 4px solid var(--accent); }
.fb-stars { display: flex; gap: 6px; margin: 12px 0; }
.fb-stars button { font-size: 26px; line-height: 1; background: none; border: 0;
  cursor: pointer; color: #C9D6E4; padding: 2px; transition: transform .1s; }
.fb-stars button:hover { transform: scale(1.15); }
.fb-stars button.on { color: #F5A623; }
.fb-card textarea { width: 100%; min-height: 74px; font: inherit; font-size: 14.5px;
  padding: 10px 12px; border: 1px solid #C9D6E4; border-radius: 8px; resize: vertical; }
.fb-actions { display: flex; gap: 10px; margin-top: 12px; align-items: center; }

/* ---------------- Chat: who is online right now (admin) ---------------- */
/* An arrival is only useful if reaching out is one click away, so every row
   here is a button that opens a thread with that student. */
.chatw-online { border-bottom: 1px solid var(--line); padding: 10px 12px 12px;
  background: var(--accent-soft); }
.chatw-on-h { font-family: var(--font-label); font-size: 10.5px; letter-spacing: 1.4px;
  text-transform: uppercase; color: var(--accent-ink); font-weight: 700; margin-bottom: 8px; }
.chatw-on { display: grid; grid-template-columns: 10px 1fr; gap: 2px 9px; width: 100%;
  text-align: left; background: #fff; border: 1px solid var(--line); border-radius: 8px;
  padding: 9px 11px; margin-bottom: 6px; cursor: pointer; }
.chatw-on:hover { border-color: var(--accent); }
.chatw-on-dot { grid-row: 1 / span 2; width: 9px; height: 9px; border-radius: 50%;
  background: var(--ok); margin-top: 5px; }
.chatw-on-name { font-weight: 600; font-size: 14px; color: var(--ink);
  display: flex; align-items: center; gap: 7px; }
.chatw-on-where { font-size: 12.5px; color: var(--text-mid); }
.chatw-on-stuck { font-style: normal; font-size: 10.5px; font-weight: 700;
  letter-spacing: .6px; text-transform: uppercase; color: #B8123C;
  background: #FDEFF1; border-radius: 99px; padding: 2px 7px; }
.chatw-alerts { font-family: var(--font-label); font-size: 11px; letter-spacing: .6px;
  background: transparent; color: #fff; border: 1px solid rgba(255,255,255,.45);
  border-radius: 99px; padding: 4px 10px; cursor: pointer; margin-right: 8px; }
.chatw-alerts:hover { border-color: #fff; }
.chatw-alerts.on { background: rgba(255,255,255,.18); border-color: #fff; }
.chatw-alerts:disabled { opacity: .5; cursor: default; }
