/* Aiman portal surfaces: the student home (/me/) and the staff console
   (/console/).

   Style D, REUSED from templates/landing/base.html (and, before that, from
   the retired templates/tracking/progress_dashboard.html): warm paper
   #F7F4EE, white cards, hairline #E5E3DC, green-800 #00562D headings,
   gold #E0A820 rules.
   Mobile-first - the base rules are the 390px phone layout; the only media
   query widens the reading column. No external fonts, no JavaScript. */

:root {
  --paper: #F7F4EE;
  --card: #ffffff;
  --green-950: #00371E;
  --green-800: #00562D;
  --green-600: #006838;
  --green-100: #E8F3EE;
  --gold-500: #E0A820;
  --gold-700: #B7791F;
  --ink: #101840;
  --muted: #5B6472;
  --line: #E5E3DC;
  --serif: Georgia, 'Times New Roman', serif;
  --sans: 'Segoe UI', system-ui, -apple-system, Roboto, Arial, sans-serif;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body.portal-body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-size: clamp(16px, 15.3px + 0.2vw, 18px);
  line-height: 1.6;
  overflow-wrap: break-word;
}
a { color: var(--green-600); }
a:hover, a:focus { color: var(--green-800); }
:focus-visible { outline: 2px solid var(--green-600); outline-offset: 2px; }
.skip { position: absolute; left: -9999px; top: 0; background: var(--green-800); color: #fff; padding: .6rem 1rem; z-index: 10; }
.skip:focus { left: 0; color: #fff; }

/* ---- head band (deep green, closed by a gold rule) ------------------- */
.portal-head {
  background: linear-gradient(180deg, var(--green-800) 0%, var(--green-950) 100%);
  color: #fff;
  border-bottom: 4px double var(--gold-500);
}
.portal-head-inner { padding: 1.4rem 1rem 1.3rem; }
/* the AIMAN wordmark - THE canonical definition of the mark:
 * 0.72rem / .28em / 700 / uppercase / gold.
 * The landing page's own .kicker (templates/landing/base.html) and the
 * learner app's wordmark chip (docker/gateway-redesign.css) use the same
 * values; the admin header (templates/admin/base_site.html) repeats them
 * because it loads a different stylesheet.
 * lms_portal/tests/test_brand_palette.py parses all three and fails if
 * they ever drift apart. */
.portal-kicker {
  font-family: var(--sans); font-size: .72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .28em; color: var(--gold-500);
}
.portal-title {
  margin: .4rem 0 0; font-family: var(--serif); color: #fff;
  font-size: clamp(1.5rem, 1.2rem + 1.4vw, 2.1rem); line-height: 1.2;
}
.portal-head .portal-sub { margin: .5rem 0 0; color: rgba(255,255,255,.82); font-size: .95rem; }

/* ---- page body -------------------------------------------------------- */
.portal-wrap { max-width: 68rem; margin: 0 auto; padding: 0 1rem; }
.portal-main { padding: 1.6rem 0 2.5rem; }
.portal-foot { border-top: 1px solid var(--line); padding: 1.2rem 0 1.8rem; }
.portal-foot p { margin: 0; color: var(--muted); font-size: .85rem; }

/* ---- cards ------------------------------------------------------------ */
.portal-card {
  background: var(--card); border: 1px solid var(--line); border-radius: 8px;
  padding: 1rem 1.1rem; margin: 0 0 1rem;
}
.portal-card > h2 {
  color: var(--green-800); font-family: var(--serif);
  font-size: clamp(1.15rem, 1.05rem + .5vw, 1.4rem); line-height: 1.3;
  margin: 0 0 .7rem;
}
.portal-card > h2::before {
  content: ""; display: block; width: 40px; height: 3px; border-radius: 2px;
  background: var(--gold-500); margin-bottom: .5rem;
}
.portal-card h3 { color: var(--green-800); font-size: 1.05rem; margin: 0 0 .35rem; }
.muted { color: var(--muted); font-size: .92rem; }
.alert {
  border: 1px solid #d9a0a0; background: #fdf3f2; color: #8c2f2f;
  border-radius: 6px; padding: .6rem .8rem; margin: 0 0 .8rem; font-size: .9rem;
}
.alert-warn { border-color: var(--gold-500); background: #fdf8ee; color: #7a5210; }

/* ---- buttons ---------------------------------------------------------- */
.btn {
  display: inline-block; font-family: var(--sans); font-weight: 700;
  font-size: 1rem; line-height: 1.2; text-decoration: none;
  min-height: 48px; padding: .8rem 1.4rem; border-radius: 8px;
  border: 2px solid transparent; cursor: pointer;
}
.btn-primary { background: var(--green-600); color: #fff; }
.btn-primary:hover, .btn-primary:focus { background: var(--green-800); color: #fff; }
.btn-outline { border-color: var(--green-600); color: var(--green-600); background: transparent; }
.btn-outline:hover, .btn-outline:focus { background: var(--green-100); color: var(--green-800); }
.btn-small { min-height: 34px; padding: .3rem .7rem; font-size: .82rem; border-radius: 5px; }

/* ---- forms ------------------------------------------------------------ */
.portal-form { display: block; }
.portal-form label {
  display: block; font-family: var(--sans); font-size: .85rem; font-weight: 600;
  color: var(--muted); margin: .6rem 0 .2rem;
}
.portal-form input[type="text"], .portal-form input[type="password"],
.portal-form input[type="number"], .portal-form select, .portal-form textarea {
  width: 100%; padding: .65rem .7rem; font-size: 1rem; font-family: var(--sans);
  border: 1px solid var(--line); border-radius: 6px; background: #fff; color: var(--ink);
}
.portal-form textarea { min-height: 8rem; resize: vertical; }
.portal-form .btn { margin-top: .9rem; }

/* ---- progress + milestones -------------------------------------------- */
.progress {
  position: relative; background: var(--paper); border: 1px solid var(--line);
  height: 1.3rem; border-radius: 4px; overflow: hidden; margin: 0 0 .8rem;
}
.progress-fill { position: absolute; inset: 0 auto 0 0; background: var(--green-800); }
.progress span {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-family: var(--sans); font-size: .78rem; font-weight: 600; color: var(--ink);
}
ul.milestone-list { list-style: none; margin: 0; padding: 0; }
ul.milestone-list li {
  position: relative; padding: .35rem 0 .35rem 1.6rem; font-size: .98rem;
  border-bottom: 1px solid var(--line);
}
ul.milestone-list li:last-child { border-bottom: none; }
ul.milestone-list li::before {
  content: "\25CB"; position: absolute; left: .3rem; top: .38rem; color: var(--muted);
}
ul.milestone-list li.is-done::before { content: "\2713"; color: var(--green-600); font-weight: 700; }
ul.milestone-list li.is-done { color: var(--green-800); }
ul.plain-list { list-style: none; margin: .4rem 0 0; padding: 0; }
ul.plain-list li { font-size: .88rem; color: var(--muted); padding: .15rem 0; }

/* ---- staff console ---------------------------------------------------- */
.portal-nav { display: flex; flex-wrap: wrap; gap: .5rem; margin: 0 0 1.1rem; }
.portal-nav a {
  font-family: var(--sans); font-size: .88rem; text-decoration: none;
  border: 1px solid var(--line); border-radius: 999px; padding: .35rem .85rem;
  background: var(--card); color: var(--green-800);
}
.portal-nav a.is-current { background: var(--green-100); border-color: var(--green-600); font-weight: 700; }
table.portal-table { width: 100%; border-collapse: collapse; font-family: var(--sans); font-size: .86rem; background: var(--card); }
table.portal-table th, table.portal-table td {
  text-align: left; padding: .4rem .55rem; border-bottom: 1px solid var(--line); vertical-align: top;
}
table.portal-table th {
  color: var(--muted); font-weight: 600; font-size: .74rem;
  text-transform: uppercase; letter-spacing: .04em; white-space: nowrap;
}
table.portal-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.table-scroll { overflow: auto; border: 1px solid var(--line); border-radius: 6px; }
.pill {
  display: inline-block; padding: .05rem .45rem; border-radius: 3px;
  border: 1px solid var(--line); background: #fffdf8; color: var(--ink);
  font-family: var(--sans); font-size: .76rem; margin: .05rem .1rem .05rem 0;
  white-space: nowrap;
}
.pill-done { border-color: var(--green-600); color: var(--green-800); background: var(--green-100); font-weight: 600; }
.pill-open { border-color: var(--gold-500); color: var(--gold-700); background: #fdf8ee; font-weight: 600; }
.pill-bad { border-color: #d9a0a0; color: #8c2f2f; background: #fdf3f2; font-weight: 600; }
.queue-row { border-bottom: 1px solid var(--line); padding: .6rem 0; }
.queue-row:last-child { border-bottom: none; }
.queue-kind { font-family: var(--sans); font-size: .72rem; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.empty-state {
  color: var(--muted); font-size: .88rem; background: #fbfaf6;
  border: 1px dashed var(--line); border-radius: 6px; padding: .7rem .85rem;
}

/* ---- wider screens ---------------------------------------------------- */
@media (min-width: 760px) {
  .portal-wrap { padding: 0 1.5rem; }
  .portal-head-inner { padding: 2rem 1.5rem 1.8rem; }
}

/* ---- module medallion + per-module hue ---------------------------------
 * The DISTINCT VISUAL IDENTITY of a module, shared by EVERY Aiman surface:
 * the student home, the staff console AND the public landing page (which
 * links this stylesheet rather than carrying its own copy of the rules).
 * The learner app's own medallion (.aiman-mod, docker/gateway-redesign.css)
 * is the same treatment, served by the gateway.
 *
 * THE MEDALLION stands in place of the visible "Module N - " prefix of the
 * module's title: a 30px circle in the module's own hue, the module number
 * in white Georgia 15px bold, 10px from the title, vertically centred. It is
 * aria-hidden, and the "Module N - " prefix stays in the DOM as
 * screen-reader-only text, so the row's accessible name is unchanged.
 *
 * THE SEVEN HUES ARE OWNER-FIXED and are defined HERE, ONCE: --mod-hue is
 * the single source for BOTH the medallion's background and the row's top
 * edge rule, so no surface can drift and no surface may repeat the values
 * in its own markup. Module 2's hue is the DARKENED brand gold, picked so
 * that the white numeral clears WCAG AA (4.5:1) - the lighter brand gold
 * does not.
 */
ul.module-map { list-style: none; margin: 0; padding: 0; }
ul.module-map > li { padding: .55rem 0 .55rem .15rem; }
.mod-head { display: flex; align-items: center; gap: 10px; }
.mod-badge {
  flex: 0 0 30px; width: 30px; height: 30px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--mod-hue, var(--green-800)); color: #fff;
  font-family: var(--serif); font-weight: 700; font-size: 15px; line-height: 1;
}
.mod-title { color: var(--green-800); font-weight: 700; flex: 1 1 auto; min-width: 0; }
.mod-line { margin: .15rem 0 0; font-size: .88rem; color: var(--muted); }
.mod-row.is-done .mod-line { color: var(--green-600); }
.mod-tick { font-weight: 700; }
/* the module block's top edge rule, in the module's own hue */
.mod-row, .mod-cell { border-top: 3px solid var(--mod-hue, transparent); }
.mod-row[data-mod="1"], .mod-cell[data-mod="1"], .mod-badge[data-mod="1"] { --mod-hue: #00562D; }
.mod-row[data-mod="2"], .mod-cell[data-mod="2"], .mod-badge[data-mod="2"] { --mod-hue: #96601A; }
.mod-row[data-mod="3"], .mod-cell[data-mod="3"], .mod-badge[data-mod="3"] { --mod-hue: #A64B2A; }
.mod-row[data-mod="4"], .mod-cell[data-mod="4"], .mod-badge[data-mod="4"] { --mod-hue: #1F6F6B; }
.mod-row[data-mod="5"], .mod-cell[data-mod="5"], .mod-badge[data-mod="5"] { --mod-hue: #6B3A62; }
.mod-row[data-mod="6"], .mod-cell[data-mod="6"], .mod-badge[data-mod="6"] { --mod-hue: #5E6B2E; }
.mod-row[data-mod="7"], .mod-cell[data-mod="7"], .mod-badge[data-mod="7"] { --mod-hue: #33427A; }

/* Screen-reader-only text: the module's number prefix stays in the
   accessible name of the row even though the visible title drops it. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

/* ---- staff console: the queue's action row + the cohort matrix header ---
 * The console shares this stylesheet with the student home (there is no
 * second one). These rules only LAY OUT what the console adds; the module
 * medallion and its seven hues are the shared rules above and are NOT
 * repeated here.
 */

/* The success variant of .alert (the queue's one-time credential hand-out
   and the inbox's "marked answered"). */
.alert-ok { border-color: var(--green-600); background: var(--green-100); color: var(--green-950); }
.console-messages { margin: 0 0 1rem; }

/* The academy's REPLY to a learner's help request: the staff console's
   answer on the inbox, and the SAME answer on the learner's own home. One
   rule for both, so the two read as one voice. */
.reply-block,
.academy-message {
  border-left: 3px solid var(--green-600);
  padding: .15rem 0 .15rem .7rem;
  margin: .45rem 0;
}
.reply-block p,
.academy-message p { margin: .2rem 0; }

/* A queue row's single action: the button (and, where the action needs a
   program, the program picker) sit on one line. */
.queue-action {
  display: flex; flex-wrap: wrap; align-items: center; gap: .45rem;
  margin: .35rem 0 0;
}
.queue-action select {
  width: auto; max-width: 16rem; padding: .3rem .45rem; font-size: .85rem;
  font-family: var(--sans); border: 1px solid var(--line); border-radius: 5px;
  background: #fff; color: var(--ink);
}

/* The cohort matrix's module column header: the shared medallion sits in
   the header cell, so the cell wraps its title instead of nowrap. */
th.mod-cell { white-space: normal; vertical-align: bottom; min-width: 7rem; }
th.mod-cell .mod-head { gap: 8px; }
th.mod-cell .mod-title { font-size: .8rem; line-height: 1.25; }

/* ---- the certificate (spec [S8]) ---------------------------------------
 * The printable certificate: the learner prints it to PDF from the browser
 * (no PDF library, no new dependency). The Aiman wordmark is IN the
 * certificate, not only in the page's head band - the head band is hidden
 * when printing, so the wordmark has to travel with the certificate.
 */
.certificate { text-align: center; padding: 1.6rem 1rem; }
.certificate .cert-brand { margin: 0 0 1rem; }
.certificate .cert-wordmark { display: block; margin: 0 auto .4rem; max-width: 110px; }
.certificate .cert-brand-name {
  display: block; font-family: var(--serif); font-weight: 700;
  font-size: 1.1rem; letter-spacing: .22em; text-transform: uppercase;
  color: var(--green-800);
}
.certificate .cert-name {
  font-family: var(--serif); color: var(--green-800);
  font-size: clamp(1.4rem, 1.2rem + 1.2vw, 2rem); margin: .6rem 0 .2rem;
}
.certificate .cert-course { font-size: 1.05rem; margin: .3rem 0; }
.certificate .cert-code {
  font-family: var(--sans); font-size: .88rem; color: var(--muted);
  margin-top: 1.4rem;
}

/* ---- the admin INDEX, in the console's Style D --------------------------
 * The Django admin is the BACK OFFICE (correcting records); the staff
 * console is the FRONT DOOR for staff work. The admin index now says so,
 * and it says it in the console's own visual language - warm paper, white
 * cards, green headings, gold rules - instead of the stock dark-blue
 * Django admin look.
 *
 * EVERY admin link still works: the stock app list (each model, its "Add"
 * link and its "Change"/"View" link) is rendered by Django's own
 * template, under the "Back office" heading, and the recent-actions
 * sidebar is untouched.
 *
 * The rules are scoped to the INDEX page (the body class the index
 * template sets): the admin's own changelist pages keep the stock look -
 * restyling them is out of scope.
 */
body.admin-index-style-d {
  --body-bg: var(--paper);
  --body-fg: var(--ink);
  --body-quiet-color: var(--muted);
  --body-medium-color: var(--ink);
  --body-loud-color: var(--green-950);
  --link-fg: var(--green-600);
  --link-hover-color: var(--green-800);
  --secondary: var(--green-950);
  --primary: var(--gold-500);
  --header-bg: var(--green-800);
  --header-color: #fff;
  --header-branding-color: var(--gold-500);
  --breadcrumbs-bg: var(--green-950);
  --breadcrumbs-fg: rgba(255, 255, 255, .72);
  --breadcrumbs-link-fg: #fff;
  --hairline-color: var(--line);
  --border-color: var(--line);
  --darkened-bg: var(--card);
  --selected-bg: var(--green-100);
  --selected-row: var(--green-100);
  --button-bg: var(--green-600);
  --button-hover-bg: var(--green-800);
  --default-button-bg: var(--green-600);
  --default-button-hover-bg: var(--green-800);
  font-family: var(--serif);
  font-size: clamp(16px, 15.3px + 0.2vw, 18px);
  line-height: 1.6;
  color: var(--ink);
  background: var(--paper);
}
/* the console door's primary button.
 * Django's own admin stylesheet declares `a:link, a:visited { color:
 * var(--link-fg); }` - specificity (0,1,1) - which BEATS a bare
 * `.btn-primary { color: #fff }` (0,1,0). The index sets --link-fg to the
 * same green as the button's background, so the label painted green on
 * green and was invisible. This rule is scoped to the index and carries
 * enough specificity (0,2,1 / 0,3,1 on hover) to keep the label white. */
body.admin-index-style-d .btn-primary,
body.admin-index-style-d .btn-primary:hover,
body.admin-index-style-d .btn-primary:focus { color: #fff; }
/* the head band: the console's deep green, closed by the gold rule */
body.admin-index-style-d #header {
  background: linear-gradient(180deg, var(--green-800) 0%, var(--green-950) 100%);
  border-bottom: 4px double var(--gold-500);
}
body.admin-index-style-d #branding h1 a,
body.admin-index-style-d #user-tools a,
body.admin-index-style-d #user-tools strong { color: #fff; }
body.admin-index-style-d ol.breadcrumbs { background: var(--green-950); }
/* the index column: the console's reading width, not the admin's 600px */
body.admin-index-style-d.dashboard #content {
  width: auto;
  max-width: 68rem;
  margin: 0 auto;
  padding: 1.4rem 1rem 2.4rem;
}
/* the recent-actions sidebar, INSIDE the column.
 * Django floats #content-related with `margin-right: -300px`: the sidebar
 * deliberately overhangs its container by ~300px, which the stock admin can
 * afford because its container is full width. The centred 68rem column
 * cannot - the overhang landed outside the viewport (the sidebar's right
 * edge measured 1548 on a 1440 viewport), so the sidebar was clipped and
 * the page scrolled sideways. Django's own idiom for a sidebar beside a
 * column (.colMS) is a 300px right column: the content gives up 300px and
 * the sidebar sits inside it. Below 768px Django stacks the sidebar under
 * the list, so the two-column arrangement stops there. */
body.admin-index-style-d #content-related { margin-right: 0; }
@media (min-width: 768px) {
  body.admin-index-style-d.dashboard #content-main {
    width: calc(100% - 300px);
  }
}
body.admin-index-style-d #content-main.app-list a { text-decoration: none; }
body.admin-index-style-d #content-main.app-list .module caption a { text-decoration: none; }
body.admin-index-style-d #content-main.app-list .module th a:hover,
body.admin-index-style-d #content-main.app-list .module td a:hover { text-decoration: underline; }
/* the back office: the stock app list, as sub-cards under one heading */
body.admin-index-style-d .admin-back-office .module {
  background: transparent;
  border: none;
  border-top: 1px solid var(--line);
  margin: 0;
  padding: .1rem 0 .5rem;
}
body.admin-index-style-d .admin-back-office .module:first-of-type { border-top: none; }
body.admin-index-style-d .admin-back-office .module caption {
  background: none;
  color: var(--green-800);
  font-family: var(--serif);
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  text-align: left;
  padding: .6rem 0 .25rem;
  border-bottom: 1px solid var(--line);
}
body.admin-index-style-d .admin-back-office .module caption a { color: var(--green-800); }
body.admin-index-style-d .admin-back-office .module table { width: 100%; }
body.admin-index-style-d .admin-back-office .module th,
body.admin-index-style-d .admin-back-office .module td {
  padding: .28rem .5rem .28rem 0;
  text-align: left;
  border: none;
  font-family: var(--sans);
  font-size: .88rem;
}
body.admin-index-style-d .admin-back-office .module th a { color: var(--green-800); font-weight: 600; }
body.admin-index-style-d .admin-back-office .module td a { color: var(--green-600); font-size: .82rem; }
/* the recent-actions sidebar: one more white card */
body.admin-index-style-d #content-related .module {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: .2rem .9rem .8rem;
}
body.admin-index-style-d #content-related h2 {
  color: var(--green-800);
  font-family: var(--serif);
  font-size: 1.05rem;
  margin: .6rem 0 .2rem;
}
body.admin-index-style-d #content-related h3 {
  color: var(--muted);
  font-family: var(--sans);
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  margin: .5rem 0 .2rem;
}
body.admin-index-style-d #content-related .actionlist li { font-family: var(--sans); font-size: .85rem; }

/* ---- printing (the learner prints the certificate) --------------------
 * A printed page carries the certificate and nothing else: no head band,
 * no navigation, no footer, no buttons.
 */
@media print {
  .portal-head, .portal-foot, .portal-nav, .no-print { display: none !important; }
  body.portal-body { background: #fff; }
  .portal-card { border: none; padding: 0; }
  .certificate { border: 2px solid var(--green-800); padding: 1.5rem; }
}

/* ---- the legal pages: ONE way back to the course ----------------------
 * The legal pages (privacy / terms / usage / contact) are DOCUMENTS a
 * learner reaches FROM the course app - or by typing the address - so they
 * carry one obvious way out: a way back to the course, ABOVE the title
 * (the first thing on the page on a phone) and again as the first item of
 * the link row.
 *
 * THE ARROW ABOVE THE TITLE IS BARE. The owner's word: "instead of an ugly
 * back to course tab just use an arrow that would be more aesthetic than the
 * ugly button". So it is a glyph in the BRAND GOLD (the same gold as the
 * AIMAN.ACADEMY wordmark on that band), with NO background, NO border and
 * NO box of any kind - not in its resting state and not on hover. What the
 * glyph cannot show is carried on the link itself (aria-label + title).
 *
 * THE TAP TARGET IS STILL A THUMB: 44px of padding around the glyph, so a
 * learner hits it with a finger, not with a pin.
 *
 * These rules live HERE, in the stylesheet every surface already loads:
 * the landing page travels in ONE request and does not load this file, so
 * it carries none of them.
 */
.back-course {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px;
  padding: .5rem .8rem; margin: 0 0 .4rem;
  font-family: var(--sans); font-size: 1.3rem; line-height: 1;
  color: var(--gold-500); text-decoration: none;
  /* NOT A BUTTON: no background, no border, no rounded box - ever */
  background: none; border: 0; border-radius: 0;
}
.back-course:hover, .back-course:focus {
  /* the gold STAYS the gold: the global a:hover would turn the arrow
     dark green on the deep-green band (and a green arrow is invisible) */
  color: var(--gold-500); text-decoration: underline;
}
/* the focus ring has to be legible ON the deep-green band (the global one
   is green on green) */
.back-course:focus-visible {
  outline: 2px solid var(--gold-500); outline-offset: 2px;
}
/* the legal link row: the way back first, then the three policies */
.foot-nav { align-items: center; }
.foot-nav .foot-back {
  display: inline-flex; align-items: center; gap: .35rem;
  min-height: 44px; font-weight: 700; color: var(--green-800);
  text-decoration: none;
}
.foot-nav .foot-back:hover, .foot-nav .foot-back:focus { color: var(--green-600); }
