/* Auctus Portal — built on the Kureos design system.

   Source of truth: ~/kureos/04-systems/web/DESIGN-SYSTEM.md and its
   packages/system/src/styles/tokens.css. Token names are kept identical
   (--k-*) so the two can be diffed. Do not invent a second palette here.

   **Light by default, and that is deliberate.** The Kureos system is
   dark-first because it was built for a marketing site somebody visits once
   and leaves. This is a tool faculty sit inside for hours, and a near-black
   field at that contrast is tiring over a working day. So the field flips and
   the identity does not: the ink is the brand near-black, gold stays the only
   signal colour, the faces and the motion law are unchanged. The landing page
   stays dark, because that is the surface the marketing register was for.

   The whole theme is these two token blocks. Components below reference
   tokens only, never a literal colour, so nothing else changes with the
   theme. If you find a hex outside this block, it is a bug.

   Gold is darkened in the light theme. #d4af37 on white is roughly 2:1 and
   unreadable; the ramp shifts to the --k-gold-lo end to clear 4.5:1. Same
   colour, more of it.

   One signal is added that the marketing system never needed: --a-risk, for
   states that are genuinely wrong (consent missing, overdue, not clear to
   graduate). Everything else is ink at three opacities. Two signals, not five.

   The craft is the message: built, not decorated.
*/

/* ------------------------------------------------------------------ face
   One typeface. Instrument Sans, self-hosted, zero external requests.

   Joseph ruled this on 13 Sep 2026 and it overrides every earlier file:
   Kureos sets Instrument Sans and nothing else. This portal shipped six
   sprints on three faces that are all on the banned list, because the
   work predated the rule and nobody re-ran
   fontguard. It does now, in CI, so it cannot drift back.

   Variable on both axes the roles need: wdth 75 to 100, wght 400 to 700.
   The 75% width is not decoration. It is what the rule specifies for hero
   words, labels and figures, and it is the thing that stops the portal
   reading like every other dashboard.                                     */
@font-face {
  font-family: "Instrument Sans";
  src: url("../fonts/instrument-sans.woff2") format("woff2-variations");
  font-weight: 400 700; font-stretch: 75% 100%; font-display: swap;
}

:root {
  /* ============================================================== LIGHT
     The working theme. Ink is the Kureos brand near-black, which the system
     already reserves for "logo/ink contexts, not the field" — so this is the
     brand used as intended rather than inverted. */
  --k-near-black:  #231f20;

  --k-gold:        #7e611a;   /* 5.06:1 on the paper field, 5.72:1 on raised */

  /* ───────────────────────────────────────── phase colour, as a code
     Three phases, three hues, and the hue is the only thing that says which
     phase you are looking at. This is colour carrying information, which is
     the only kind the design guard permits: a fourth hue would need a fourth
     thing to mean.

     THE RAMP IS THE TREE, not a temperature (5 Oct). It used to run teal to
     gold to coral: cool for observation, gold for the middle of the work,
     warm for the pressure end. That is a real idea and it was carried by two
     colours Kureos does not own, and teal #4ecdc4 beside coral #e8734a is one
     of the most recognisable default pairings there is, which the house rule
     on design tells covers.
     It runs green to gold to purple now, which is the Auctus tree read from
     the ground up: green is the wood, gold is the work, purple is the leaf.
     Three hues still, each carrying one phase, and every one of them a colour
     this school already owns.

     Every value clears 4.5:1 on the paper field and on the stage, measured
     against the per-phase stage rather than the base one, which is where the
     brand purple itself fails: #b357f6 on the Phase 3 stage is 3.84, so the
     stage cut is a tint of it at 5.12.

     --k-gold used to sit at #8a6a1c, which is 4.40:1 on this field. The note
     here said so, used it to justify darkening --ph2, and then left the
     failing token in place. It is the colour of every link in the light
     theme, so every hyperlink on paper failed AA. Now #7e611a at 5.06:1. */
  --ph1:      #2c6e1b;   /* 5.52:1 on the paper field */
  --ph2:      #8f630c;   /* 4.68:1, brand gold darkened for paper */
  --ph3:      #6d2aa8;   /* 7.27:1 */
  --ph1-wash: rgba(44, 110, 27, .10);
  --ph2-wash: rgba(143, 99, 12, .10);
  --ph3-wash: rgba(109, 42, 168, .10);
  --a-met:    #2c6e49;

  /* THE THREE-LEVEL SCALE, ONE COLOUR EACH (5 Oct).
     Meets Standard, Developing and Not Yet Met are the Institute's canonical
     performance scale, and they were coloured eight different ways across
     this file. Level 3 was --k-gold on the radar, on the competency chips, on
     the eight dots, on the step bars and on the evidenced tiles, and --a-met
     green on the gauges and on the tiles AGAIN, lower down: the same rule
     written twice with two different answers, the second one winning. So a
     student read "met" as green on her competency map and as gold on her
     portfolio, which is the same fact in two colours.
     Gold goes back to being the brand accent alone: links, hover, headings
     and the gates. Met is green, developing is amber, not met is red, and
     each is stated once here.
     Every value measured against the field it lands on, and the stage cuts
     against the lightest of the five stage grounds. */
  --lv3: #2c6e49;   /* 5.39:1 on the field, 5.83 on raised */
  --lv2: #8f630c;   /* 4.68:1 on the field, 5.06 on raised */
  --lv1: #b23a26;   /* 5.25:1 on the field, 5.68 on raised */
  --lv3-stage: #7fc98f;   /* 7.29:1 at worst */
  --lv2-stage: #d4af37;   /* 6.83:1 at worst */
  --lv1-stage: #ef9080;   /* 6.14:1 at worst; --a-risk reaches only 3.68 */

  /* THE SEASON. Every one of these is somewhere on the Route, so the portal
     and the road she walks are the same place rather than two palettes that
     happen to share a gold. Used for meaning, never as wallpaper: moss and
     leaf for what is standing, bark for what is still growing, clay for the
     thing somebody is waiting on. */
  --s-deep:   #223526;
  --s-moss:   #3d6b45;
  --s-leaf:   #4f7a34;
  --s-bark:   #6b4f2e;
  --s-clay:   #a84a28;
  --s-ochre:  #8a6512;
  --s-wash:   #e7ecdf;
  --s-wash-b: #efe7d8;
  --k-gold-hi:     #6b5114;   /* hover goes darker here, not lighter */
  --k-gold-lo:     #a88530;   /* bar fills only: 3.02:1, WCAG 1.4.11 */

  /* The field. Cream #f2efe8 went because it is a named marker of the
     AI-generated look: the second-order default a generator reaches for when
     told to make something premium. Tailwind's zinc-50 #fafafa went for the
     same reason from the other direction, since that is what Plausible ships
     unmodified and it reads as nothing decided.

     This is a near-neutral with 2 RGB units of green between its channels,
     biased toward the brand green rather than toward warmth, so the gold
     accent reads as chosen against it rather than as of a piece with it.

     The elevation step is also tighter. Raised used to sit 17 RGB units above
     the field; serious tools collapse their surfaces (Linear moves about 7 per
     level, Datadog gives two surfaces the same value) and generic ones
     multiply them, which is where floating cards come from. Now 9. */
  --k-field:        #eff1f0;
  --k-field-raised: #f8faf9;
  --k-field-edge:   #e3e6e5;

  /* The stage: a warm near-black used for the one band per screen that is
     allowed atmosphere. Not --k-field-dark, because it is not a field; it is
     a surface you look at rather than read on. */
  --stage:      #1d2c20;
  --stage-2:    #2a3d2c;
  --stage-ink:  #f6f2ea;
  --stage-gold: #d4af37;      /* full brand gold: it is on dark here */
  /* LATE AND OVERDUE ON THE STAGE, and it needs a token of its own.
     Three rules took this from --ph3-stage, which was coral and read as a
     warning by accident of Phase 3 being the warm end of the old ramp. The
     ramp is green to gold to purple now, and a purple "3 WEEKS LATE" says
     Phase 3, not late. Clay at 6.14:1 against the lightest of the three
     phase stages, where --a-risk reaches only 3.68. */
  --stage-late: #f0907a;
  --ph1-stage:  #6fe03c;   /* 10.51:1 on the Phase 1 stage */
  --ph2-stage:  #d4af37;   /*  7.41:1 on the Phase 2 stage */
  --ph3-stage:  #c07cf8;   /*  5.12:1 on the Phase 3 stage */

  --k-ink:        #231f20;
  /* Both of these were too weak, and this is the default theme: the one faculty
     sit in for hours and the one every screenshot in this project was taken on.
     Faint ran at 2.95:1 and carries every caption, every attribution, every
     competency code and every axis label on the paper field. Muted ran at
     4.55:1, which passes and leaves nothing in hand.
     Now 7.26:1 and 4.70:1, with a visible step between them so the two still
     mean different things. The same token in the dark theme was 2.54:1 and is
     fixed in that block too; the two halves had drifted apart separately. */
  --k-ink-muted:  rgba(35, 31, 32, .78);
  --k-ink-faint:  rgba(35, 31, 32, .66);

  --k-line:       rgba(35, 31, 32, .13);
  --k-line-gold:  rgba(138, 106, 28, .38);

  --a-risk:    #b23a26;
  --a-risk-lo: rgba(178, 58, 38, .09);

  --line-soft:  rgba(35, 31, 32, .07);
  --hover:      rgba(35, 31, 32, .03);
  --line-firm:  rgba(35, 31, 32, .24);
  --gold-wash:  rgba(138, 106, 28, .07);
  --gold-wash-2:rgba(138, 106, 28, .13);
  --risk-line:  rgba(178, 58, 38, .34);
  --bar:        rgba(35, 31, 32, .15);

  --shadow: 0 1px 2px rgba(35,31,32,.05), 0 10px 30px -20px rgba(35,31,32,.45);
  --shadow-lift: 0 2px 4px rgba(35,31,32,.05), 0 20px 50px -28px rgba(35,31,32,.5);
  --scheme: light;

  /* --- theme-independent --------------------------------------------- */
  /* Mirrors 04-systems/web/packages/system/src/styles/tokens.css exactly, so
     the two diff clean. Five role tokens, one face. --k-font-mono is kept as
     a NAME ONLY: there is no monospace face in this product any more, and the
     rule says labels are never mono. Figures get tabular-nums instead, which
     is what a monospace face was being used to fake. */
  --k-font-display: "Instrument Sans", system-ui, sans-serif;
  --k-font-body:    "Instrument Sans", system-ui, sans-serif;
  --k-font-label:   "Instrument Sans", system-ui, sans-serif;
  --k-font-hero:    "Instrument Sans", system-ui, sans-serif;
  --k-font-mono:    "Instrument Sans", system-ui, sans-serif;

  --k-ease-out:    cubic-bezier(.16, 1, .3, 1);
  --k-ease-severe: cubic-bezier(.83, 0, .17, 1);
  --k-dur-fast: .25s; --k-dur-base: .7s; --k-dur-slow: 1.2s;

  --r: 4px;                 /* square-ish. Rounded corners read as decorated. */
}

/* ========================================================== THE PUBLIC GROUND
   The six pages anybody can reach carry one ground: the landing, the door,
   the programme, the application, its receipt, and the policies.

   They used to carry three. The landing and the Route's shell sat on #050505,
   a cold black; the door and the .pol pages on a green-black that reads as the
   same colour until you put the two screens side by side, which is exactly
   what a prospect does when they move from the landing to the programme.

   And all three were too dark to work in. The ground measured L* 1.6 to 7.4,
   which is a cave: a form field filled at 4 per cent ink over it has an edge
   nobody can find, and the falling leaves had nothing to fall against. Raised
   to L* 16 so the ground reads as a colour rather than as an absence. The
   wood on the door and the forest on the Route are what carry the dark now,
   and they are painted rather than left. */
:root {
  --pub-sky:   #233c33;   /* L* 22, the lightest band, at the horizon */
  --pub-air:   #1a2e27;   /* L* 16, the resting ground */
  --pub-deep:  #1d322b;   /* L* 18, closing at the foot of the frame */
  --pub-fill:  rgba(247, 245, 240, .07);   /* a field, not a hole */
  /* .34 was 2.84:1 on --pub-air, and 1.4.11 asks 3:1 of the boundary of
     a control somebody has to find. The edge of a form field on a public
     page is exactly that, and it was raised on 7 October because the
     field had no findable edge; it was still 5 per cent short. */
  --pub-edge:  rgba(247, 245, 240, .36);
}

:root[data-theme="dark"] {
  /* =============================================================== DARK
     The Kureos marketing tokens, mirrored exactly. The landing page is
     always this; the app is this only when someone chooses it. */
  --k-gold:        #d4af37;
  --k-gold-hi:     #f7e59a;
  --k-gold-lo:     #9c7a1e;

  --k-field:        #050505;
  --k-field-raised: #0b0b0b;
  --k-field-edge:   #141414;

  --k-ink:        #f4f1ec;
  --k-ink-muted:  rgba(244, 241, 236, .6);    /* 9.09:1 on this field */
  /* .32 was 2.95:1, and it is the colour of every caption, every attribution,
     every competency code and every axis label in the dark theme. These tokens
     were mirrored from the marketing system, where faint ink sits under a
     headline nobody has to read twice; here it carries who scored a session
     and which competency a row is. The stage block below already measured its
     own faint ink at 6.00:1, so the two halves of the dark theme disagreed
     about what was readable. Now 4.74:1. */
  --k-ink-faint:  rgba(244, 241, 236, .50);

  --k-line:       rgba(244, 241, 236, .1);
  --k-line-gold:  rgba(212, 175, 55, .28);

  /* The same season, lifted for the dark field. */
  --s-deep:   #d7e0cc;
  --s-moss:   #8fc29a;
  --s-leaf:   #a8ca7a;
  --s-bark:   #c8a473;
  --s-clay:   #f0907a;
  --s-ochre:  #dcc264;
  --s-wash:   rgba(143, 194, 154, .12);
  --s-wash-b: rgba(220, 194, 100, .10);


  --a-risk:    #e0503a;
  --a-risk-lo: rgba(224, 80, 58, .12);

  --line-soft:  rgba(244, 241, 236, .05);
  --hover:      rgba(244, 241, 236, .02);
  --line-firm:  rgba(244, 241, 236, .2);
  --gold-wash:  rgba(212, 175, 55, .07);
  --gold-wash-2:rgba(212, 175, 55, .13);
  --risk-line:  rgba(224, 80, 58, .32);
  --bar:        rgba(244, 241, 236, .14);

  --stage:      #16211a;
  --stage-2:    #1f2e23;
  --stage-ink:  #f4f1ec;
  --stage-gold: #d4af37;
  --stage-late: #f0907a;
  --lv3: #7fc98f;
  --lv2: #d4af37;
  --lv1: #ef9080;
  --lv3-stage: #7fc98f;
  --lv2-stage: #d4af37;
  --lv1-stage: #ef9080;

  --shadow: none;
  --shadow-lift: none;
  --scheme: dark;
}

* { box-sizing: border-box; }

html { background: var(--k-field); color-scheme: var(--scheme); }

html { overflow-x: clip; }

body {
  margin: 0;
  /* THE FULL-BLEED BANDS COUNT THE SCROLLBAR AND THE VIEWPORT DOES NOT.
     A stage band escapes `main` with `calc(50% - 50vw)`, and `vw` includes
     the classic scrollbar while the client area excludes it, so every page
     with a band overflowed by half a scrollbar each side: two pixels on this
     machine's overlay scrollbars and about seventeen on a browser with real
     ones, which is a horizontal scrollbar on every screen in the product.
     `clip`, not `hidden`: hidden makes this a scroll container and would
     break the sticky header. It goes on `html` as well as here, because the
     scroll container for the page is the document element and clipping only
     the body leaves the overflow where it was. */
  overflow-x: clip;
  background: var(--k-field);
  color: var(--k-ink);
  font-family: var(--k-font-body);
  font-size: 15px; line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

::selection { background: var(--gold-wash-2); color: var(--k-ink); }
::-webkit-scrollbar { width: 4px; }
::-webkit-scrollbar-track { background: var(--k-field); }
::-webkit-scrollbar-thumb { background: var(--line-firm); }

/* ---------------------------------------------------------------- chrome */
.top {
  background: var(--k-field);
  border-bottom: 1px solid var(--k-line);
  padding: 9px 30px;
  display: flex; align-items: center; gap: 30px;
  /* It grows rather than overflowing. `.nav` wraps and the bar was pinned at a
     flat 60px, so on any width where eleven links need a second row that row
     was drawn outside the bar, on top of the page. Invisible against a quiet
     dashboard and obvious the moment the first screen had a picture in it. */
  min-height: 60px; flex-wrap: wrap;
  position: sticky; top: 0; z-index: 40;
}
/* A page that locks its own theme is not offering a choice, so it does not
   show the control for one. */
.brand { display: inline-flex; align-items: center; gap: 10px; }
/* THE MARK AS A MASK, NOT AN IMAGE.
   The file carries `fill="currentColor"` so that it inks itself wherever it
   is placed, and an `<img>` is an independent document: currentColor
   resolves inside it, to black, and the mark came out dark on the dark
   header. Masked, the colour is the box's own, so one file serves the dark
   header, a light document and a printed page. */
.brand-tree {
  flex: 0 0 auto; display: block; width: 30px; height: 34px;
  /* IN COLOUR, not a mask. It was one flat fill, and a tree of life
     rendered as a silhouette is a shape rather than a tree: the wood,
     the three leaf ranks and the mirrored roots all read as one blob.

     BROWN WOOD, GREEN LEAVES, on both grounds. The first dark cut took
     the deck palette, green wood into a violet crown, and a mark of a
     tree that is neither the colour of wood nor the colour of leaves
     is a diagram. Two cuts only because the student tree's own values
     disappear on near-black: bark at #584531 is 2.0:1 there. The dark
     cut is the same palette lifted until it reads. */
  /* The URL comes from `--mark` on <html>, which carries the asset stamp.
     A literal here is a mark that never updates in a browser that has
     seen the old one. The fallback keeps the mark visible if the
     attribute is ever missing. */
  background: var(--tree, url("/static/img/auctus-tree-small-colour.svg"))
              center / contain no-repeat;
}
/* THE HEADER IS ALWAYS DARK. `.top` paints #1d2c20 whatever the theme is,
   which is why the first version of this swapped on `data-theme` and was
   wrong on every page: the light cut's #584531 bark is 1.6:1 there and the
   mark read as mud. The swap belongs on the element that paints the
   ground, not on the theme. */
.top .brand-tree {
  background-image: var(--tree-dark,
                        url("/static/img/auctus-tree-small-night.svg"));
}
.brand {
  font-family: var(--k-font-display); font-variation-settings: "wdth" 75;
  font-weight: 680; text-transform: uppercase; letter-spacing: .02em;
  font-size: 17px; color: var(--k-ink); text-decoration: none; white-space: nowrap;
}
.brand span {
  font-family: var(--k-font-mono); font-weight: 400; font-size: 10px;
  letter-spacing: .14em; color: var(--k-ink-faint); margin-left: 10px;
}
.nav { display: flex; gap: 24px; margin-left: 12px; flex-wrap: wrap; }
.nav a {
  font-family: var(--k-font-mono); font-size: 11px; text-transform: uppercase;
  letter-spacing: .14em; color: var(--k-ink-muted); text-decoration: none;
  padding: 4px 0; border-bottom: 1px solid transparent; white-space: nowrap;
  transition: color var(--k-dur-fast) var(--k-ease-out);
}
.nav a:hover { color: var(--k-ink); }
.nav a.on { color: var(--k-gold); border-bottom-color: var(--k-gold); }
.who {
  margin-left: auto; display: flex; align-items: center; gap: 18px;
  font-family: var(--k-font-mono); font-size: 11px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--k-ink-faint);
}

main { max-width: 1180px; margin: 0 auto; padding: 44px 30px 120px; }
/* A screen that is a place rather than a page takes the whole width. */
main.bleed { max-width: none; margin: 0; padding: 0; }

/* ------------------------------------------------------------- typography */
h1 {
  font-family: var(--k-font-display); font-variation-settings: "wdth" 75;
  font-weight: 680; text-transform: uppercase; letter-spacing: -.01em;
  line-height: .94; font-size: clamp(2rem, 1.2rem + 2.4vw, 3.25rem);
  margin: 0 0 10px;
}
h2 {
  font-family: var(--k-font-mono); font-size: 11px; font-weight: 500;
  text-transform: uppercase; letter-spacing: .18em; color: var(--k-ink-faint);
  margin: 52px 0 16px; display: flex; align-items: center; gap: 14px;
}
h2::after { content: ""; flex: 1; height: 1px; background: var(--k-line); }
h3 { font-size: 16px; margin: 0 0 4px; font-weight: 600; letter-spacing: -.01em; }
.lede { color: var(--k-ink-muted); margin: 0 0 30px; font-size: 15px; max-width: 68ch; }
.src  { font-family: var(--k-font-mono); font-size: 10px; letter-spacing: .1em;
        text-transform: uppercase; color: var(--k-ink-faint); }
.note { font-size: 13px; color: var(--k-ink-muted); line-height: 1.65; }
a { color: var(--k-gold); text-decoration-color: var(--k-line-gold); }
a:hover { color: var(--k-gold-hi); }

.k-label { font-family: var(--k-font-mono); font-size: 10px; text-transform: uppercase;
           letter-spacing: .18em; color: var(--k-ink-faint); }
.gold { color: var(--k-gold); }

/* ------------------------------------------------------------------ cards */
.card {
  background: var(--k-field-raised);
  border: 1px solid var(--k-line);
  border-radius: var(--r);
  padding: 20px 22px;
}
.card.lit { border-color: var(--k-line-gold);
             }
.grid { display: grid; gap: 12px; }
.g2 { grid-template-columns: repeat(2, 1fr); }
.g3 { grid-template-columns: repeat(3, 1fr); }
.g4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) { .g2, .g3, .g4 { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------- stat tiles */
.stat { display: flex; flex-direction: column; gap: 5px; }
.stat .k { font-family: var(--k-font-mono); font-size: 10px; text-transform: uppercase;
           letter-spacing: .16em; color: var(--k-ink-faint); }
.stat .v { font-family: var(--k-font-display); font-variation-settings: "wdth" 75;
           font-weight: 680; font-size: 34px; line-height: 1; letter-spacing: -.01em;
           font-variant-numeric: tabular-nums; }
.stat .v small { font-size: 15px; color: var(--k-ink-faint); font-weight: 400; }
.stat .s { font-size: 12px; color: var(--k-ink-muted); }
/* --a-risk is tuned for the paper field. On the stage it drops to 2.94:1, and
   the overdue count is the one figure on that header that must not be the
   hardest to read. The stage gets the lighter end of the same ramp. */
.stat.warn .v, .stat .v.bad { color: var(--a-risk); }
.stage .stat.warn .v, .stage .stat .v.bad,
.stage .hero-stats .v.bad { color: var(--a-risk-stage, #ff8e7e); }
.stat.good .v, .stat .v.good { color: var(--k-gold); }

/* ------------------------------------------------------ competency cards */
.comp {
  display: grid; grid-template-columns: 46px 1fr auto; gap: 16px; align-items: start;
  padding: 16px 20px; border: 1px solid var(--k-line); border-radius: var(--r);
  background: var(--k-field-raised);
  transition: border-color var(--k-dur-fast) var(--k-ease-out);
}
.comp + .comp { margin-top: 8px; }
.comp .code {
  font-family: var(--k-font-mono); font-size: 11px; font-weight: 700; letter-spacing: .08em;
  color: var(--k-ink-faint); background: var(--k-field-edge);
  border-radius: 3px; padding: 8px 0; text-align: center;
}
.comp .name { font-weight: 600; font-size: 15px; }
.comp .meta { font-size: 12.5px; color: var(--k-ink-muted); margin-top: 3px; }
.comp .right { text-align: right; display: flex; flex-direction: column;
               align-items: flex-end; gap: 8px; }
.comp.lv3 { border-color: color-mix(in srgb, var(--lv3) 38%, transparent); }
.comp.lv3 .code { background: color-mix(in srgb, var(--lv3) 13%, transparent); color: var(--lv3); }
.comp.lv2 .code { color: var(--lv2); }
.comp.lv1 .code { background: color-mix(in srgb, var(--lv1) 13%, transparent); color: var(--lv1); }
.comp.lv0 { border-style: dashed; background: transparent; }
.comp.lv0 .name { color: var(--k-ink-muted); }

/* ------------------------------------------------------------------ level */
.level { display: inline-flex; align-items: center; gap: 8px;
         font-family: var(--k-font-mono); font-size: 10px; font-weight: 600;
         text-transform: uppercase; letter-spacing: .12em;
         padding: 5px 11px; border-radius: 2px; white-space: nowrap;
         border: 1px solid var(--k-line); color: var(--k-ink-muted); }
.level i { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
/* The last gold on this chip was its own background, which left green type
   sitting on a gold tint. */
.level.l3 { color: var(--lv3); border-color: color-mix(in srgb, var(--lv3) 38%, transparent);
            background: color-mix(in srgb, var(--lv3) 9%, transparent); }
.level.l2 { color: var(--lv2); }
.level.l1 { color: var(--lv1); border-color: color-mix(in srgb, var(--lv1) 38%, transparent); background: color-mix(in srgb, var(--lv1) 11%, transparent); }
.level.l0 { color: var(--k-ink-faint); }

.tag { font-family: var(--k-font-mono); font-size: 9px; text-transform: uppercase;
       letter-spacing: .14em; font-weight: 700; color: var(--k-gold);
       border: 1px solid var(--k-line-gold); border-radius: 2px; padding: 2px 6px; }

/* ------------------------------------------------------------------ steps */
.steps { display: flex; gap: 3px; align-items: center; }
.steps b { width: 22px; height: 3px; background: var(--k-line); display: block; }
.steps b.l3 { background: var(--lv3); }
.steps b.l2 { background: var(--lv2); }
.steps b.l1 { background: var(--lv1); }
.trend { font-family: var(--k-font-mono); font-size: 10px; letter-spacing: .1em;
         text-transform: uppercase; color: var(--k-ink-faint);
         display: inline-flex; gap: 4px; align-items: center; }
.trend.up { color: var(--k-gold); }
.trend.down { color: var(--a-risk); }

/* ------------------------------------------------------------------ meter */
.meter { height: 3px; background: var(--k-field-edge); overflow: hidden; width: 100%; }
.meter i { display: block; height: 100%; background: var(--k-ink-muted);
           transition: width var(--k-dur-slow) var(--k-ease-out); }
/* FLAT, AND GREEN (6 Oct). This was a 135-degree metallic ramp: a light
   sweep, which the house rule has banned since 30 September. It survived
   because aiguard reads prose and cannot see a CSS gradient, and the
   stylesheet's own gradient guard could not see it either: the declaration
   says `var(--k-gold-gradient)`, which contains no `gradient(` to match on.
   A meter that is done is a threshold that is met, so it takes the met
   colour. */
.meter.done i { background: var(--lv3); }
.meter.idle { background: repeating-linear-gradient(90deg,
              var(--k-field-edge) 0 5px, transparent 5px 10px); }
.mrow { display: grid; grid-template-columns: 1fr 110px; gap: 18px; align-items: center;
        padding: 14px 0; }
.mrow + .mrow { border-top: 1px solid var(--k-line); }
.mrow .lab { font-size: 14px; }
.mrow .num { text-align: right; font-family: var(--k-font-mono);
             font-variant-numeric: tabular-nums; font-size: 13px; color: var(--k-ink-muted); }
.mrow .num b { color: var(--k-ink); font-weight: 600; }

/* ---------------------------------------------------------------- verdict */
.verdict { border-radius: var(--r); padding: 20px 22px; border: 1px solid; display: flex; gap: 15px; }
.verdict .ic { font-size: 15px; line-height: 1.4; }
.verdict.no  { background: var(--a-risk-lo); border-color: var(--risk-line); color: var(--k-ink); }
.verdict.no .ic { color: var(--a-risk); }
.verdict.yes { background: var(--gold-wash); border-color: var(--k-line-gold); }
.verdict.yes .ic { color: var(--k-gold); }
.verdict h3 { margin: 0 0 6px; font-size: 15px; }
.verdict ul { margin: 10px 0 0; padding-left: 18px; }
.verdict li { margin: 4px 0; font-size: 14px; color: var(--k-ink-muted); }

/* ----------------------------------------------------------------- tables */
table { border-collapse: collapse; width: 100%; font-size: 14px;
        background: var(--k-field-raised); border: 1px solid var(--k-line);
        border-radius: var(--r); overflow: hidden; }
th { background: var(--k-field-edge); font-family: var(--k-font-mono); font-weight: 500;
     font-size: 10px; text-transform: uppercase; letter-spacing: .16em;
     color: var(--k-ink-faint); text-align: left; padding: 11px 15px;
     border-bottom: 1px solid var(--k-line); }
td { padding: 12px 15px; border-bottom: 1px solid var(--line-soft); vertical-align: top; }
tr:last-child td { border-bottom: 0; }
table tr:hover { background: var(--hover); }
.num-cell { font-family: var(--k-font-mono); font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------- journey */
.journey { display: flex; gap: 2px; align-items: flex-end; height: 56px; }
.journey b { flex: 1; background: var(--line-soft); display: block; min-height: 3px;
             transition: background var(--k-dur-fast) var(--k-ease-out); }
.journey b.has { background: var(--bar); }
.journey b.gate { background: var(--k-gold); }
.journey b:hover { background: var(--k-gold-hi); }
.jlabels { display: flex; justify-content: space-between; font-family: var(--k-font-mono);
           font-size: 9.5px; letter-spacing: .12em; text-transform: uppercase;
           color: var(--k-ink-faint); margin-top: 8px; }
.phases { display: flex; gap: 2px; margin-bottom: 8px; }
.phases .ph { flex: 1; text-align: center; font-family: var(--k-font-mono); font-size: 9.5px;
              text-transform: uppercase; letter-spacing: .16em; color: var(--k-ink-faint);
              border-bottom: 1px solid var(--k-line); padding: 5px 0; }

/* ------------------------------------------------------------------ misc */
.ok  { color: var(--k-gold); font-weight: 600; }
.bad { color: var(--a-risk); font-weight: 600; }
.dim { color: var(--k-ink-faint); }
details summary { cursor: pointer; font-family: var(--k-font-mono); font-size: 10px;
                  letter-spacing: .14em; text-transform: uppercase;
                  color: var(--k-ink-faint); padding: 6px 0; }
details summary:hover { color: var(--k-gold); }
details[open] summary { margin-bottom: 8px; }
.ev { border-left: 1px solid var(--k-line-gold); padding: 10px 0 10px 16px; margin: 10px 0; }
.ev .q { font-size: 13.5px; color: var(--k-ink-muted); font-style: italic; }
.ev .by { font-family: var(--k-font-mono); font-size: 10px; letter-spacing: .1em;
          text-transform: uppercase; color: var(--k-ink-faint); margin-top: 6px; }
.rowlink { text-decoration: none; color: inherit; display: block; }
.rowlink:hover { border-color: var(--k-line-gold); color: inherit; }
.pill { display: inline-block; padding: 3px 9px; border-radius: 2px;
        font-family: var(--k-font-mono); font-size: 10px; letter-spacing: .1em;
        text-transform: uppercase; border: 1px solid var(--k-line); color: var(--k-ink-muted); }
.pill.pass { border-color: var(--k-line-gold); color: var(--k-gold); }
.pill.fail { border-color: var(--risk-line); color: var(--a-risk); }
.sep { height: 1px; background: var(--k-line); margin: 40px 0; }

.btn { display: inline-block; background: transparent; color: var(--k-gold);
       border: 1px solid var(--k-line-gold); text-decoration: none;
       padding: 11px 20px; border-radius: 2px;
       font-family: var(--k-font-mono); font-size: 11px; text-transform: uppercase;
       letter-spacing: .16em; cursor: pointer; white-space: nowrap;
       transition: background var(--k-dur-fast) var(--k-ease-out),
                   color var(--k-dur-fast) var(--k-ease-out); }
.btn:hover { background: var(--k-gold); color: var(--k-field); }
.btn.ghost { color: var(--k-ink-muted); border-color: var(--k-line); }
.btn.ghost:hover { background: transparent; color: var(--k-gold); border-color: var(--k-line-gold); }

/* ============================================================== the policies
   Published in full on the dark ground the landing and the door use, because
   this is the public face rather than a working surface. Measured against
   #101e1a: cream 15.76:1, muted 10.69, faint 6.33.
   A long read by design. Nothing is summarised and nothing is behind a
   disclosure, because the whole ICF requirement is that somebody who has never
   heard of Auctus can read the refund policy before deciding anything. */
.pol {
  min-height: 100vh;
  background: linear-gradient(180deg, var(--pub-air), var(--pub-sky) 40%, var(--pub-deep));
}
.pol-top {
  max-width: 1180px; margin: 0 auto; padding: 26px 30px; width: 100%;
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
}
.pol-top .brand { color: #f7f5f0; text-decoration: none; }
.pol-top .brand span {
  margin-left: 12px; font-size: 10px; letter-spacing: .18em;
  text-transform: uppercase; color: #93a09a;
}
.pol-in { max-width: 760px; margin: 0 auto; padding: clamp(30px, 6vh, 70px) 30px 90px; }

.pol-k {
  display: block; font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 10.5px; letter-spacing: .18em; text-transform: uppercase;
  color: #93a09a; margin-bottom: 16px;
}
.pol h1 {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: clamp(2.2rem, 1.4rem + 3vw, 3.6rem); line-height: .95;
  letter-spacing: -.025em; text-transform: uppercase;
  color: #f7f5f0; margin: 0 0 22px;
}
.pol-lede {
  margin: 0 0 44px; font-size: 16px; line-height: 1.64; color: #c7cec6;
}

/* The contents. A reader usually arrives wanting one section. */
.pol-toc {
  border-top: 1px solid rgba(247, 245, 240, .16);
  border-bottom: 1px solid rgba(247, 245, 240, .16);
  padding: 22px 0; margin: 0 0 54px;
}
.pol-toc ol {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px 30px;
}
@media (max-width: 620px) { .pol-toc ol { grid-template-columns: 1fr; } }
.pol-toc a {
  display: flex; gap: 12px; font-size: 14px; color: #c7cec6;
  text-decoration: none; line-height: 1.4;
}
.pol-toc a:hover { color: #f7f5f0; }
.pol-toc b {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75, "tnum" 1;
  font-variant-numeric: tabular-nums;
  font-size: 11px; letter-spacing: .1em; color: #6fe03c;
  min-width: 16px; padding-top: 3px;
}

.pol-sec { margin: 0 0 54px; scroll-margin-top: 24px; }
.pol-sec h2 {
  display: flex; gap: 16px; align-items: baseline;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 1.22rem; letter-spacing: -.012em; text-transform: uppercase;
  color: #f7f5f0; margin: 0 0 18px;
  padding-bottom: 14px; border-bottom: 1px solid rgba(247, 245, 240, .16);
}
.pol-sec h2 span {
  font-variation-settings: "wdth" 75, "tnum" 1;
  font-variant-numeric: tabular-nums; font-size: 12px;
  letter-spacing: .1em; color: #6fe03c;
}
.pol-sec p {
  margin: 0 0 14px; font-size: 15.5px; line-height: 1.66; color: #c7cec6;
  max-width: 68ch;
}
.pol-sec h3 {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 10.5px; letter-spacing: .18em; text-transform: uppercase;
  color: #93a09a; margin: 30px 0 12px;
}
/* One <li> per <ul>, because the document gives them to us one paragraph at a
   time and grouping them would mean guessing where a list ends. The spacing is
   collapsed so consecutive ones read as one list, which is what they are. */
.pol-li { list-style: none; margin: 0; padding: 0; }
.pol-li + .pol-li li { padding-top: 0; }
.pol-li li {
  position: relative; margin: 0 0 9px; padding-left: 20px;
  font-size: 15.5px; line-height: 1.6; color: #c7cec6; max-width: 66ch;
}
.pol-li li::before {
  content: ""; position: absolute; left: 2px; top: .62em;
  width: 5px; height: 1px; background: #6fe03c;
}
.pol-table {
  width: 100%; border-collapse: collapse; margin: 6px 0 22px;
  font-size: 14.5px; color: #c7cec6;
}
.pol-table th {
  text-align: left; padding: 0 16px 10px 0;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 10px; letter-spacing: .16em; text-transform: uppercase;
  color: #93a09a; border-bottom: 1px solid rgba(247, 245, 240, .22);
}
.pol-table td {
  padding: 13px 16px 13px 0; vertical-align: top; line-height: 1.5;
  border-bottom: 1px solid rgba(247, 245, 240, .10);
}
.pol-table tr td:last-child { color: #f7f5f0; }
/* The programme and apply pages share the policies' ground and type. What
   they add is the cohort block and a narrower measure for the form. */
.pol-narrow { max-width: 560px; }
.pg-tag {
  display: block; font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 10px; letter-spacing: .18em; text-transform: uppercase;
  color: #6fe03c; margin-bottom: 12px;
}
.pg-cohort {
  border: 1px solid rgba(247, 245, 240, .20); border-radius: 2px;
  padding: 30px 32px; margin: 0 0 54px;
  background: rgba(247, 245, 240, .03);
}
.pg-cohort h2 {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 1.5rem; letter-spacing: -.018em; color: #f7f5f0; margin: 0 0 22px;
}
.pg-cohort p { font-size: 15px; line-height: 1.62; color: #c7cec6; margin: 0 0 16px; }
.pg-facts {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px; margin: 0 0 22px; padding: 0 0 20px;
  border-bottom: 1px solid rgba(247, 245, 240, .14);
}
@media (max-width: 620px) { .pg-facts { grid-template-columns: repeat(2, 1fr); } }
.pg-facts dt {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 9.5px; letter-spacing: .16em; text-transform: uppercase;
  color: #93a09a; margin-bottom: 6px;
}
.pg-facts dd {
  margin: 0; font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75, "tnum" 1;
  font-variant-numeric: tabular-nums; font-size: 15px; color: #f7f5f0;
}
.pg .pol-sec p a { color: #c7cec6; }
.pg .btn { color: #f7f5f0; border-color: rgba(247, 245, 240, .34); }
.pg .btn:hover { background: #f7f5f0; color: #0b1614; }
/* The form's help text and checkboxes on this ground. */
.pg-form .fg-help { font-size: 13px; color: #93a09a; margin: 6px 0 0; }
.pg-form .fg-err { font-size: 13px; color: #ef9080; margin: 6px 0 0; }
.pg-form .fg-check label { display: flex; gap: 11px; align-items: flex-start;
                           font-size: 14.5px; line-height: 1.5; color: #c7cec6;
                           cursor: pointer; }
.pg-form .fg-check input { margin-top: 3px; accent-color: #6fe03c; }
.pg-form textarea {
  width: 100%; padding: 10px 12px; background: var(--pub-fill);
  border: 1px solid var(--pub-edge); border-radius: 2px;
  color: #f7f5f0; font-family: var(--k-font-body); font-size: 15px;
  line-height: 1.55; outline: none; resize: vertical;
}
.pg-form textarea:focus { border-color: #6fe03c; }
.pg-form .fg + .fg { margin-top: 24px; }

.pol-foot {
  margin: 70px 0 0; padding-top: 24px;
  border-top: 1px solid rgba(247, 245, 240, .16);
  font-size: 13px; line-height: 1.6; color: #93a09a;
}
.pol-foot a { color: #c7cec6; }

/* ================================================================== the door
   The sign-in screen. Locked dark like the landing and the Route, because the
   landing handed the reader straight to a white card and the product looked
   like two products at the one moment somebody decides whether it is serious.

   Everything here is measured against #101e1a, the lightest the painted ground
   reaches behind the copy column: cream 15.76:1, muted 10.69, faint 6.33,
   green 10.14, the error 7.34. */
.door {
  position: relative; min-height: 100vh; min-height: 100svh;
  display: flex; flex-direction: column;
  /* The resting ground, so the screen is composed before a pixel of canvas
     arrives and stays composed if none ever does. */
  background: linear-gradient(180deg, var(--pub-air), var(--pub-sky) 52%, var(--pub-deep));
  overflow: hidden;
}
.door-field {
  position: absolute; inset: 0; width: 100%; height: 100%;
  display: block; pointer-events: none; z-index: 0;
}
.door-in {
  position: relative; z-index: 1; flex: 1;
  display: flex; align-items: center;
  width: 100%; max-width: 1180px; margin: 0 auto; padding: 48px 30px;
}
.door-say { width: 100%; max-width: 420px; }

.door-k {
  display: block; font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 10.5px; letter-spacing: .18em; text-transform: uppercase;
  color: #93a09a; margin-bottom: 18px;
}
/* The name at the size of a door, and set the way the house sets a hero:
   700, 75% width, capitals, tight. Nothing enters letter by letter. */
.door h1 {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: clamp(3rem, 1.6rem + 5.4vw, 5.6rem); line-height: .88;
  letter-spacing: -.028em; text-transform: uppercase;
  color: #f7f5f0; margin: 0;
}
/* The second line of the lockup. Subordinate by size and tone, not by weight:
   it is set in the same face at the same 700 and 75% width, so the two lines
   read as one mark rather than as a name with a caption under it. */
.door h1 span {
  display: block; margin-top: 14px;
  font-size: clamp(13px, 7px + .55vw, 17px);
  letter-spacing: .22em; line-height: 1;
  color: #93a09a;
}
.door-lede {
  margin: 20px 0 0; font-size: 15.5px; line-height: 1.62;
  color: #c7cec6; max-width: 40ch;
}

/* The form as an instrument: hairlines, no boxes, no fill. A field that looks
   like a card on a screen like this reads as a component somebody imported. */
.door-form { margin-top: 38px; }
.door-form .fg + .fg { margin-top: 22px; }
.door-form label {
  display: block; font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 10px; letter-spacing: .18em; text-transform: uppercase;
  color: #93a09a; margin-bottom: 8px;
  transition: color var(--k-dur-fast) var(--k-ease-out);
}
.door-form input {
  width: 100%; padding: 9px 0 11px; border: 0;
  border-bottom: 1px solid var(--pub-edge);
  background: transparent; color: #f7f5f0;
  font-family: var(--k-font-body); font-size: 16px;
  border-radius: 0; outline: none;
  transition: border-color var(--k-dur-fast) var(--k-ease-out);
}
.door-form .fg:focus-within label { color: #6fe03c; }
.door-form input:focus { border-bottom-color: #6fe03c; }
/* The focus ring the outline above removed, put back as something visible on
   this ground. A keyboard reader has to be able to see where they are. */
.door-form input:focus-visible { box-shadow: 0 1px 0 0 #6fe03c; }

.door-go {
  display: block; width: 100%; margin-top: 34px;
  background: transparent; color: #f7f5f0;
  border: 1px solid rgba(247, 245, 240, .30);
  border-radius: 2px; padding: 14px 20px; cursor: pointer;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 11px; letter-spacing: .18em; text-transform: uppercase;
  transition: background var(--k-dur-fast) var(--k-ease-out),
              color var(--k-dur-fast) var(--k-ease-out),
              border-color var(--k-dur-fast) var(--k-ease-out);
}
.door-go:hover, .door-go:focus-visible {
  background: #f7f5f0; color: #0b1614; border-color: #f7f5f0;
}
.door-lost {
  display: inline-block; margin-top: 20px; font-size: 12.5px;
  color: #93a09a; text-decoration: none;
  border-bottom: 1px solid rgba(147, 160, 154, .34);
}
.door-lost:hover { color: #f7f5f0; border-bottom-color: #f7f5f0; }
.door-err {
  margin: 0 0 20px; padding-left: 14px; font-size: 13.5px;
  color: #ef9080; border-left: 2px solid #ef9080;
}

.door-foot a { color: rgba(199, 206, 198, .9); text-decoration: none;
               border-bottom: 1px solid rgba(147, 160, 154, .34); }
.door-foot a:hover { color: #f7f5f0; border-bottom-color: #f7f5f0; }
.door-foot {
  position: relative; z-index: 1; margin: 0;
  width: 100%; max-width: 1180px; padding: 0 30px 26px;
  margin-left: auto; margin-right: auto;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 9.5px; letter-spacing: .18em; text-transform: uppercase;
  color: rgba(147, 160, 154, .72);
}

@media (max-width: 1000px) {
  /* Under a thousand the tree drops below the frame and only its crown shows,
     so the copy runs full width and the footer is lifted clear of the crown
     rather than sitting in it. */
  .door-in { align-items: flex-start; padding-top: 9vh; }
  .door-say { max-width: 100%; }
  .door-lede { max-width: 34ch; }
  .door-foot { padding-bottom: 150px; }
}

/* ------------------------------------------------------------------ auth */
.auth { max-width: 400px; margin: 12vh auto; }
.auth .card { padding: 34px 32px; }
.auth h1 { font-size: 26px; }
.auth label { display: block; font-family: var(--k-font-mono); font-size: 10px;
              text-transform: uppercase; letter-spacing: .18em;
              color: var(--k-ink-faint); margin: 20px 0 6px;
              transition: color var(--k-dur-fast) var(--k-ease-out); }
.auth .fg:focus-within label { color: var(--k-gold); }
.auth input { width: 100%; padding: 10px 0 11px; border: 0;
              border-bottom: 1px solid var(--k-line); background: transparent;
              color: var(--k-ink); font-family: var(--k-font-body); font-size: 15px;
              border-radius: 0; outline: none;
              transition: border-color var(--k-dur-fast) var(--k-ease-out); }
.auth input:focus { border-bottom-color: var(--k-gold); }
.auth .btn { width: 100%; margin-top: 28px; text-align: center; }
.auth .errorlist { color: var(--a-risk); font-size: 13px; padding-left: 16px; margin: 12px 0 0; }

/* =============================================================== hero + radar */
.hero { display: grid; grid-template-columns: 1fr 360px; gap: 44px; align-items: center;
        margin-bottom: 16px; }
@media (max-width: 900px) { .hero { grid-template-columns: 1fr; } }
.hero-text h1 { font-size: clamp(2.2rem, 1.2rem + 3vw, 3.75rem); }
.hero-stats { display: flex; gap: 40px; flex-wrap: wrap; margin-top: 28px; }
.hero-stats > div,
.hero-stats > a { display: flex; flex-direction: column-reverse; gap: 5px; }
.hero-stats .v { font-family: var(--k-font-display); font-variation-settings: "wdth" 75;
                 font-weight: 680; font-size: 38px; line-height: 1;
                 font-variant-numeric: tabular-nums; }
.hero-stats .v small { font-size: 16px; color: var(--k-ink-faint); font-weight: 400; }
.hero-stats .v.bad { color: var(--a-risk); }
.hero-stats .v.good { color: var(--k-gold); }
.hero-stats .k { font-family: var(--k-font-mono); font-size: 10px; text-transform: uppercase;
                 letter-spacing: .16em; color: var(--k-ink-faint); }
/* THE LABEL HAS TO BE ABLE TO BREAK.
   `flex-wrap` on the row cannot save a row whose own item is wider than the
   viewport, and a tracked uppercase label is one unbreakable word as far as
   the layout is concerned. On a 375px phone "Competencies unevidenced" pushed
   the band five pixels past the edge and the whole page scrolled sideways,
   on every screen that carries this row. */
@media (max-width: 560px) {
  .hero-stats { gap: 22px 26px; }
  .hero-stats > div, .hero-stats > a { max-width: 46%; min-width: 0; }
  .hero-stats .k { letter-spacing: .1em; overflow-wrap: anywhere; }
  .hero-stats .v { font-size: 32px; }
}
.hero-stats .k a { color: var(--k-ink-faint); text-decoration: none; }
.hero-stats .k a:hover { color: var(--k-gold); }

.radar { margin: 0; }
.radar svg { width: 100%; height: auto; display: block; overflow: visible; }
.radar .rg { fill: none; stroke: var(--k-line); stroke-width: 1; }
.radar .rg:last-of-type { stroke: var(--line-firm); }
.radar .ax { stroke: var(--k-line); stroke-width: 1; }
/* The shape is the standing, so it takes the standing's colour and not the
   brand's. Gold here said "met" in the same breath as every link on the
   page. */
.radar .shape { fill: color-mix(in srgb, var(--lv3) 12%, transparent);
                stroke: var(--lv3); stroke-width: 1.5;
                stroke-linejoin: round; }
.radar .dot { stroke: var(--k-field); stroke-width: 2; }
.radar .dot.l3 { fill: var(--lv3); }
.radar .dot.l2 { fill: var(--lv2); }
.radar .dot.l1 { fill: var(--lv1); }
.radar .lbl { font-family: var(--k-font-mono); font-size: 10px; letter-spacing: .1em;
              fill: var(--k-ink-muted); }
.radar .lbl.off  { fill: var(--k-ink-faint); }
.radar .lbl.crit { fill: var(--lv1); }
.radar figcaption { display: flex; gap: 20px; justify-content: center; margin-top: 14px;
                    flex-wrap: wrap; }
.key { font-family: var(--k-font-mono); font-size: 9.5px; letter-spacing: .12em;
       text-transform: uppercase; color: var(--k-ink-faint);
       display: inline-flex; align-items: center; gap: 7px; }
.key i { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }
/* The legend has to be the thing it is a legend FOR. */
.key .k3 { background: var(--lv3); } .key .k2 { background: var(--lv2); }
.key .k1 { background: var(--lv1); }

/* ------------------------------------------------------------ progress rings */
.ringcard { display: flex; align-items: center; gap: 16px; }
.ring { width: 66px; height: 66px; flex: 0 0 66px; }
.ring .track { fill: none; stroke: var(--k-field-edge); }
.ring .fill { fill: none; stroke: var(--k-ink-muted); stroke-linecap: butt; }
/* A ring that has reached its threshold is MET, and met is green. Gold here
   said the same thing the portfolio's radar was saying in gold while the
   competency map said it in green: one fact, two colours, three screens. */
.ring .fill.done { stroke: var(--lv3); }
.ring .rt { font-family: var(--k-font-mono); font-size: 12px; font-weight: 600; fill: var(--k-ink); }
.rl { font-size: 13.5px; font-weight: 600; line-height: 1.35; }
.rn { font-family: var(--k-font-mono); font-size: 12px; color: var(--k-ink-muted);
      font-variant-numeric: tabular-nums; margin: 3px 0 2px; }
.rn b { color: var(--k-ink); }

/* ================================================================ key/value */
.kv > div { display: grid; grid-template-columns: 220px 1fr; gap: 18px; padding: 13px 0; }
.kv > div + div { border-top: 1px solid var(--k-line); }
.kv > div:first-child { padding-top: 0; }
.kv > div:last-child { padding-bottom: 0; }
.kv .k { font-family: var(--k-font-mono); font-size: 10px; text-transform: uppercase;
         letter-spacing: .14em; color: var(--k-ink-faint); padding-top: 2px; }
.kv .v { font-size: 14px; }
.kv .v .src { display: block; margin-top: 4px; }
@media (max-width: 700px) { .kv > div { grid-template-columns: 1fr; gap: 4px; } }

/* ------------------------------------------------------------ people cards */
.person { display: block; text-decoration: none; color: inherit;
          transition: border-color var(--k-dur-fast) var(--k-ease-out); }
.person:hover { border-color: var(--k-line-gold); color: inherit; }
.person .ph { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.person .nm { font-weight: 600; font-size: 15.5px; }
.person .co { font-family: var(--k-font-mono); font-size: 10px; letter-spacing: .1em;
              text-transform: uppercase; color: var(--k-ink-faint); margin-top: 4px; }
.person .foot { display: flex; align-items: center; justify-content: space-between;
                gap: 10px; margin-top: 15px; padding-top: 14px; border-top: 1px solid var(--k-line); }
.person .n { font-family: var(--k-font-mono); font-size: 11px; color: var(--k-ink-muted);
             font-variant-numeric: tabular-nums; letter-spacing: .06em; }
.person .n b { color: var(--k-ink); }

.dots8 { display: flex; gap: 5px; margin: 15px 0 0; }
.dots8 i { width: 9px; height: 9px; border-radius: 50%; background: transparent;
           border: 1px solid var(--k-line); display: block; }
.dots8 i.l3 { background: var(--lv3); border-color: var(--lv3); }
.dots8 i.l2 { background: var(--lv2); border-color: var(--lv2); }
.dots8 i.l1 { background: var(--lv1); border-color: var(--lv1); }

/* ------------------------------------------------------------------ chips */
.chip { display: inline-flex; align-items: center; gap: 5px;
        font-family: var(--k-font-mono); font-size: 9.5px; font-weight: 500;
        text-transform: uppercase; letter-spacing: .12em;
        padding: 4px 9px; border-radius: 2px; white-space: nowrap;
        border: 1px solid var(--k-line); color: var(--k-ink-faint); }
/* The competency is the only canonical vocabulary on most of these pages, so
   it is the only thing wearing a colour. A page where everything is chipped in
   grey is a page where nothing is being said. */
.chip.good { border-color: var(--s-moss); color: var(--s-moss); }
.chip.comp { border-color: transparent; background: var(--s-moss); color: #f4f3ea; }
.chip.comp.c7, .chip.comp.c8 { background: var(--s-bark); }
.chip.comp.c3, .chip.comp.c4 { background: var(--s-ochre); }
[data-theme="dark"] .chip.comp { color: #16180f; }
.chip.warn { border-color: var(--line-firm); color: var(--k-ink); }
.chip.link { color: var(--k-gold); border-color: var(--k-line-gold); text-decoration: none; }
.chip.link:hover { border-color: var(--k-gold); }
.chip.bad  { border-color: var(--risk-line); color: var(--a-risk); background: var(--a-risk-lo); }

/* --------------------------------------------------------------- timeline */
.tl { position: relative; margin: 0; padding: 2px 0 2px 32px; }
.tl::before { content: ""; position: absolute; left: 4px; top: 14px; bottom: 14px;
              width: 1px; background: var(--a-made); }
.tli { position: relative; padding: 14px 0; display: grid;
       grid-template-columns: 1fr auto; gap: 16px; align-items: center; }
.tli + .tli { border-top: 1px solid var(--line-soft); }
.tli::before { content: ""; position: absolute; left: -32px; top: 50%; margin-top: -3.5px;
               width: 7px; height: 7px; border-radius: 50%;
               background: var(--k-field); border: 1px solid var(--k-line); }
/* The same three surfaces as the tape and the road. A session she uploaded
   inside the window is made ground; one uploaded late is there, but hollow;
   one she owes is a gap, drawn with the broken ends the record strip uses for
   a week she lost. Three states, three forms, so the row reads without colour.
   It was three filled circles in three colours, which is a palette. */
.tli.dot-ok::before   { background: var(--k-gold);  border-color: var(--k-gold); }
.tli.dot-warn::before { background: transparent;    border-color: var(--k-ink-muted);
                        border-width: 2px; }
.tli.dot-bad::before  { background: transparent; border-color: transparent;
                        border-radius: 0; width: 9px; margin-left: -1px;
                        border-left: 2px solid var(--a-risk);
                        border-right: 2px solid var(--a-risk); }
.tl:has(.tli:only-child)::before { display: none; }
.tli .t { font-weight: 600; font-size: 14.5px; }
.tli .m { font-size: 12.5px; color: var(--k-ink-muted); margin-top: 3px; }
.tli .r { text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 7px; }
/* A week written inline inside a line of text ("Week 3 . Practicum"). It is a
   label, not a cell, and it used to be called .wk like the two grids below.
   Three components answering to one class name in one stylesheet is a cascade
   collision waiting for whichever rule is written last to win, and one did:
   the week board's .wk, added after the record page's, overrode every state
   colour on the record page's strip, so complete, deferred, missed and future
   all drew in the same grey under a legend promising four colours. Nothing was
   wrong with either component on its own. */
.wkref { font-family: var(--k-font-mono); font-size: 10px; font-weight: 600;
      letter-spacing: .14em; text-transform: uppercase; color: var(--k-ink-faint); }

/* ------------------------------------------------------------- queue rows */
.qrow { display: grid; grid-template-columns: 58px 1fr auto auto; gap: 18px; align-items: center;
        padding: 16px 20px; border: 1px solid var(--k-line); border-radius: var(--r);
        background: var(--k-field-raised);
        transition: border-color var(--k-dur-fast) var(--k-ease-out); }
.qrow + .qrow { margin-top: 8px; }
.qrow:hover { border-color: var(--line-firm); }
.qrow.blocked { border-color: var(--risk-line); background: var(--a-risk-lo); }
.qrow .w { text-align: center; border: 1px solid var(--k-line); border-radius: 3px;
           padding: 7px 0; font-family: var(--k-font-mono); font-size: 14px;
           font-weight: 600; color: var(--k-ink); line-height: 1.2; }
.qrow .w small { display: block; font-size: 8.5px; font-weight: 500; letter-spacing: .16em;
                 text-transform: uppercase; color: var(--k-ink-faint); }
.qrow .nm { font-weight: 600; font-size: 15px; }
.qrow .m { font-size: 12.5px; color: var(--k-ink-muted); margin-top: 3px; }
.qrow .flags { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }

/* ------------------------------------------------------------ empty state */
.empty { border: 1px dashed var(--k-line); border-radius: var(--r); padding: 34px 20px;
         text-align: center; color: var(--k-ink-faint); font-size: 13.5px; }

/* ----------------------------------------------------- section + page head */
.shead { display: flex; align-items: center; justify-content: space-between; gap: 16px;
         margin: 52px 0 16px; }
.shead h2 { margin: 0; flex: 1; }
.phead { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px;
         flex-wrap: wrap; margin-bottom: 28px; }
.phead .lede { margin: 0; }
/* `flex: 0 0 auto` is "never shrink", so this row kept its max-content width
   of 470px inside a 375px phone and the whole page scrolled sideways. It may
   keep its own width while there is room for it and give way when there is
   not, which is what the basis-auto half was for and the zero-shrink half
   prevented. */
.phead .hero-stats { flex: 0 1 auto; min-width: 0; margin-top: 0; }
@media (max-width: 560px) { .phead .hero-stats { flex: 1 1 100%; } }

/* Django 5 requires POST to log out, so the control is a button styled as a
   link. A GET link silently does nothing. */
.signout { display: inline; margin: 0; }
.signout button { background: none; border: 0; padding: 0; cursor: pointer;
                  color: var(--k-ink-faint); font: inherit; letter-spacing: .1em; }
.signout button:hover { color: var(--k-gold); }

/* ================================================================== motion
   One motion law: heavy ease-out arrivals, no bounce, no springs. Content is
   visible without JS and under prefers-reduced-motion, so the reveal only
   arms itself once the script has run. */
html.k-motion [data-reveal] { opacity: 0; transform: translateY(14px); }
html.k-motion [data-reveal].shown {
  opacity: 1; transform: none;
  transition: opacity var(--k-dur-base) var(--k-ease-out),
              transform var(--k-dur-base) var(--k-ease-out);
}
@media (prefers-reduced-motion: reduce) {
  html.k-motion [data-reveal] { opacity: 1; transform: none; transition: none; }
}

/* ============================================================ progression
   The game layer. Gold is earned, never decorative: a rung lights only when
   the underlying evidence exists. Nothing here appears on an ICF surface. */

.rankhero { display: grid; grid-template-columns: 132px 1fr; gap: 34px; align-items: center;
            padding: 34px 0 30px; border-bottom: 1px solid var(--k-line); margin-bottom: 30px; }
@media (max-width: 700px) { .rankhero { grid-template-columns: 1fr; gap: 20px; } }
.rankmark { position: relative; aspect-ratio: 1; display: grid; place-items: center;
            border: 1px solid var(--k-line-gold); border-radius: 50%;
            background: none; }
.rankmark::before { content: ""; position: absolute; inset: 9px; border-radius: 50%;
                    border: 1px solid var(--k-line); }
.rankmark .num { font-family: var(--k-font-display); font-variation-settings: "wdth" 75;
                 font-weight: 680; font-size: 46px; line-height: 1;
                 color: var(--k-gold); }
.rankmark .of { position: absolute; bottom: 22px; font-family: var(--k-font-mono);
                font-size: 8.5px; letter-spacing: .18em; text-transform: uppercase;
                color: var(--k-ink-faint); }
.rankbody h1 { margin: 8px 0 8px; }
.rankbody .lede { margin: 0; }

.ladder { display: flex; gap: 4px; margin-top: 24px; max-width: 560px; }
.rung { flex: 1; }
.rung b { display: block; height: 3px; background: var(--k-field-edge); }
.rung span { display: block; margin-top: 8px; font-family: var(--k-font-mono);
             font-size: 9.5px; letter-spacing: .14em; text-transform: uppercase;
             color: var(--k-ink-faint); }
.rung.done b { background: var(--k-gold-lo); }
.rung.done span { color: var(--k-ink-muted); }
.rung.here b { background: var(--k-gold); }
.rung.here span { color: var(--k-gold); }

.advance { display: grid; grid-template-columns: 220px 1fr; gap: 30px; align-items: center; }
@media (max-width: 700px) { .advance { grid-template-columns: 1fr; gap: 18px; } }
.advance .ahead h3 { margin: 6px 0 0; font-family: var(--k-font-display);
                     font-variation-settings: "wdth" 75; font-weight: 680;
                     text-transform: uppercase; font-size: 22px; letter-spacing: -.01em; }
.areqs { display: flex; gap: 30px; flex-wrap: wrap; }
.areq { display: flex; gap: 11px; align-items: flex-start; }
.areq .tick { font-size: 12px; line-height: 1.5; color: var(--k-ink-faint); }
.areq.met .tick { color: var(--k-gold); }
.areq .rq { font-size: 13.5px; color: var(--k-ink-muted); }
.areq.met .rq { color: var(--k-ink); }
.areq .rp { font-family: var(--k-font-mono); font-size: 12px; color: var(--k-ink-faint);
            margin-top: 3px; font-variant-numeric: tabular-nums; }
.areq .rp b { color: var(--k-ink); }
.areq.met .rp b { color: var(--k-gold); }

/* ------------------------------------------------------------- objectives */
.objective { display: grid; grid-template-columns: 3px 1fr auto; gap: 18px; align-items: center;
             padding: 18px 22px 18px 0; background: var(--k-field-raised);
             border: 1px solid var(--k-line); border-radius: var(--r);
             text-decoration: none; color: inherit; overflow: hidden;
             transition: border-color var(--k-dur-fast) var(--k-ease-out); }
.objective + .objective { margin-top: 8px; }
.objective:hover { border-color: var(--k-line-gold); color: inherit; }
.objective:hover .oarrow { color: var(--k-gold); transform: translateX(4px); }
.obar { align-self: stretch; background: var(--k-ink-faint); }
.objective.u-critical .obar { background: var(--a-risk); }
.objective.u-high .obar { background: var(--k-gold); }
.objective.u-normal .obar { background: var(--k-gold-lo); }
.objective.u-none .obar { background: var(--k-line); }
.objective .ot { font-weight: 600; font-size: 15.5px; }
.objective.u-critical .ot { color: var(--a-risk); }
.objective .od { font-size: 13px; color: var(--k-ink-muted); margin-top: 5px; max-width: 74ch; }
.oarrow { color: var(--k-ink-faint); font-size: 18px; padding-left: 10px;
          transition: color var(--k-dur-fast) var(--k-ease-out),
                      transform var(--k-dur-fast) var(--k-ease-out); }

/* ---------------------------------------------------------------- competency_tiles */
.competency_tiles { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
@media (max-width: 900px) { .competency_tiles { grid-template-columns: repeat(2, 1fr); } }
.ctile { display: block; padding: 16px 16px 14px; border: 1px solid var(--k-line);
          border-radius: var(--r); background: var(--k-field-raised);
          text-decoration: none; color: inherit; position: relative; overflow: hidden;
          transition: border-color var(--k-dur-fast) var(--k-ease-out); }
.ctile:hover { border-color: var(--line-firm); color: inherit; }
.ctile .uc { display: block; font-family: var(--k-font-mono); font-size: 11px;
              font-weight: 700; letter-spacing: .14em; color: var(--k-ink-faint); }
.ctile .un { display: block; font-size: 13.5px; font-weight: 600; margin-top: 7px;
              line-height: 1.35; min-height: 2.7em; }
.ctile .us { display: block; margin-top: 10px; font-family: var(--k-font-mono);
              font-size: 9px; letter-spacing: .16em; text-transform: uppercase;
              color: var(--k-ink-faint); }
.ctile.s-locked { border-style: dashed; background: transparent; }
.ctile.s-locked .un { color: var(--k-ink-faint); }
.ctile.s-active .uc { color: var(--k-ink); }
/* DECLARED ONCE (5 Oct). This tile was written twice, nine hundred lines
   apart: gold border, gold wash and a gold gradient hairline here, green
   border and green text further down. The second block only set the border
   and the text, so what actually rendered was green type on a gold wash under
   a metallic hairline, which the house rule on design tells covers.
   One block, one colour: evidenced is the Meets Standard green. */
.ctile.s-evidenced { border-color: var(--lv3);
                     background: linear-gradient(180deg,
                       color-mix(in srgb, var(--lv3) 9%, transparent), transparent 62%); }
.ctile.s-evidenced .uc, .ctile.s-evidenced .us { color: var(--lv3); }

/* ================================================================= landing
   The anonymous front door, and the only screen allowed a signature moment.
   THE CEILING, borrowed from the Kureos system: a point of gold rises,
   strikes an invisible ceiling, ripples, and goes through.

   Animation is transform and opacity only, so it composites on the GPU and
   cannot stutter in front of a buyer. It runs once and stops. */

.lp {
  min-height: 100vh; display: flex; flex-direction: column;
  background: linear-gradient(180deg, var(--pub-air), var(--pub-sky) 40%, var(--pub-deep));
}
.lp-inner { max-width: 1180px; margin: 0 auto; padding: 0 30px; width: 100%; }

.lp-top { max-width: 1180px; margin: 0 auto; padding: 26px 30px; width: 100%;
          display: flex; align-items: center; justify-content: space-between; gap: 20px; }

.lp-hero { max-width: 1180px; margin: 0 auto; padding: clamp(40px, 7vh, 96px) 30px clamp(60px, 10vh, 120px);
           width: 100%; display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 44px;
           align-items: center; }
@media (max-width: 860px) { .lp-hero { grid-template-columns: 1fr; gap: 44px; } }

.lp-hero h1 { font-size: clamp(2.5rem, 1.3rem + 4.4vw, 5rem); margin: 18px 0 26px; }
.lp-lede { color: var(--k-ink-muted); font-size: clamp(1rem, .95rem + .35vw, 1.2rem);
           line-height: 1.6; max-width: 56ch; margin: 0 0 18px; }
.lp-lede.sub { color: var(--k-ink-faint); font-size: 15px; margin-bottom: 32px; }

/* --- the ceiling -------------------------------------------------------
   The resting state below IS the final state: a struck ceiling with the point
   held against it. The animation starts from an earlier position and returns
   here, so a reader on prefers-reduced-motion sees a finished mark rather
   than a half-drawn one. */
.ceiling { margin: 0; position: relative; height: 320px; }
@media (max-width: 860px) { .ceiling { height: 180px; } }
.cl-track { position: absolute; left: 50%; top: 38%; bottom: 0; width: 1px; margin-left: -.5px;
            background: linear-gradient(180deg, var(--k-line) 0%, transparent 88%); }
.cl-line { position: absolute; left: 0; right: 0; top: 38%; height: 1px;
           background: linear-gradient(90deg, transparent, var(--k-line-gold) 22%,
                       var(--k-gold) 50%, var(--k-line-gold) 78%, transparent);
           transform-origin: 50% 50%; opacity: .5; }
.cl-ripple { position: absolute; left: 50%; top: 38%; width: 12px; height: 12px;
             margin: -6px 0 0 -6px; border-radius: 50%;
             border: 1px solid var(--k-gold); opacity: 0; }
.cl-point { position: absolute; left: 50%; top: 38%; width: 7px; height: 7px;
            margin: -3.5px 0 0 -3.5px; border-radius: 50%; background: var(--k-gold);
             }

html.k-motion .cl-point  { animation: cl-rise   6s var(--k-ease-severe) .35s both; }
html.k-motion .cl-line   { animation: cl-strike 6s var(--k-ease-out)    .35s both; }
html.k-motion .cl-ripple { animation: cl-ripple 6s var(--k-ease-out)    .35s both; }

/* Rises from the floor, strikes at 2.8s of 6s, is held and compressed, then
   punches through. Transform and opacity only, so it composites on the GPU. */
@keyframes cl-rise {
  0%   { transform: translateY(198px); opacity: 0; }
  8%   { transform: translateY(178px); opacity: 1; }
  47%  { transform: translateY(0); }
  58%  { transform: translateY(0); }
  100% { transform: translateY(-132px); opacity: 0; }
}
@keyframes cl-strike {
  0%, 40% { transform: scaleX(.2); opacity: .16; }
  47%     { transform: scaleX(1);  opacity: 1; }
  100%    { transform: scaleX(1);  opacity: .5; }
}
@keyframes cl-ripple {
  0%, 46% { transform: scale(1);  opacity: 0; }
  50%     { opacity: .75; }
  100%    { transform: scale(26); opacity: 0; }
}

/* --- figures ----------------------------------------------------------- */
.lp-band { border-block: 1px solid var(--k-line); padding: 44px 0;
           background: linear-gradient(180deg, var(--gold-wash), transparent); }
.lp-figs { display: grid; grid-template-columns: repeat(5, 1fr); gap: 28px; }
@media (max-width: 900px) { .lp-figs { grid-template-columns: repeat(2, 1fr); gap: 26px; } }
.lp-figs b { display: block; font-family: var(--k-font-display);
             font-variation-settings: "wdth" 75; font-weight: 680;
             font-size: clamp(2rem, 1.2rem + 1.8vw, 3rem); line-height: 1;
             font-variant-numeric: tabular-nums;
             color: var(--k-gold); }
.lp-figs span { display: block; margin-top: 10px; font-size: 12.5px;
                color: var(--k-ink-muted); line-height: 1.45; max-width: 24ch; }

/* --- sections ---------------------------------------------------------- */
.lp-sec { padding: 64px 30px 0; }
.lp-sec h2 { margin-top: 0; }

.lp-phases { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px;
             background: var(--k-line); border: 1px solid var(--k-line);
             border-radius: var(--r); overflow: hidden; }
@media (max-width: 860px) { .lp-phases { grid-template-columns: 1fr; } }
.lp-phase { background: var(--k-field-raised); padding: 30px 26px 32px; }
.lp-phase .n { font-family: var(--k-font-mono); font-size: 11px; letter-spacing: .2em;
               color: var(--k-gold); }
.lp-phase h3 { font-family: var(--k-font-display); font-variation-settings: "wdth" 75;
               font-weight: 680; text-transform: uppercase; font-size: 26px;
               letter-spacing: -.01em; margin: 12px 0 12px; }
.lp-phase p { margin: 0; font-size: 13.5px; color: var(--k-ink-muted); line-height: 1.6; }

.lp-comps { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0 40px; }
@media (max-width: 700px) { .lp-comps { grid-template-columns: 1fr; } }
.lp-comps div { display: flex; gap: 16px; align-items: baseline;
                padding: 15px 0; border-bottom: 1px solid var(--k-line); font-size: 15px; }
.lp-comps b { font-family: var(--k-font-mono); font-size: 11px; letter-spacing: .14em;
              color: var(--k-gold); font-weight: 700; }
.lp-note { margin: 26px 0 0; max-width: 74ch; }

.lp-close { padding-bottom: 80px; }
.lp-close h2 { margin-bottom: 18px; }

@media (max-width: 560px) {
  /* The tagline and the control fight for the same row on a phone. The
     control wins; the tagline is repeated in the footer anyway. */
  .lp-top .brand span { display: none; }
}

.lp-foot { margin-top: auto; border-top: 1px solid var(--k-line);
           max-width: 1180px; margin-inline: auto; width: 100%;
           padding: 26px 30px 40px; display: flex; justify-content: space-between;
           gap: 20px; font-family: var(--k-font-mono); font-size: 10px;
           letter-spacing: .14em; text-transform: uppercase; color: var(--k-ink-faint); }

/* ------------------------------------------------------------ theme toggle
   Light is the default because this is a tool, not a launch page. Dark stays
   one click away, and the choice is remembered per browser. */

/* ================================================================== stage
   One dark band per screen, full-bleed, where the atmosphere lives. The
   working surface below it stays light and readable.

   This is the resolution of two failures: an all-dark app was tiring to read
   for hours, and an all-light one was sterile. You look at the stage once and
   read the page underneath for the rest of the session, so they can be
   different materials.

   Full-bleed out of the 1180px column, with the inner padding computed so the
   content still lines up with everything below it. */
.stage {
  position: relative;
  margin: -44px calc(50% - 50vw) 44px;
  padding: 52px max(30px, calc(50vw - 560px)) 48px;
  background: var(--stage);
  color: var(--stage-ink);
  overflow: hidden;
  isolation: isolate;
}
.stage {                                /* pointer-driven, with a static default */
  --px: 84%; --py: -18%;
}
.stage::before {                       /* a warm pool of light, off-centre */
  content: ""; position: absolute; inset: 0; z-index: -2;
  /* One neutral layer only. The gold pool that used to sit on top was a
     coloured radial bloom, which is on the banned list, and it was also the
     reason the stage read as a template hero rather than a surface. */
  background: radial-gradient(90% 120% at var(--px, 8%) var(--py, 120%), var(--stage-2), transparent 62%);
}
.stage::after {                        /* grain, so the dark is a material */
  content: ""; position: absolute; inset: 0; z-index: -1; opacity: .5;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.055'/%3E%3C/svg%3E");
}
/* The stage redefines the INK TOKENS, not a list of selectors.

   It used to override one selector at a time (.stage .lede, .stage .k-label,
   .stage .hero-stats .k and so on), which meant every component added to a
   stage band needed its own override line. The standing bug did not get one,
   so its competency codes rendered in the light theme's near-black at 48%
   opacity, on a near-black field. Dark on dark, invisible, and nothing failed.

   Redefining the tokens is safe for everything below: a selector that sets a
   colour outright still wins. It just means a component that only asks for
   --k-ink-faint now gets a value that works here.

   The alphas are raised as well. The old .42 composites to 3.77:1 against the
   stage and missed AA, so every label on every stage band was below the line:
   AT STANDARD, OBSERVATIONS, NO EVIDENCE and the lede. Now .58, at 6.00:1. */
.stage, html[data-theme="dark"] .stage {
  --k-ink:        var(--stage-ink);
  --k-ink-muted:  rgba(246, 242, 234, .72);   /* 8.57:1 */
  --k-ink-faint:  rgba(246, 242, 234, .58);   /* 6.00:1 */
  --k-line:       rgba(246, 242, 234, .16);
}
.stage h1 { color: var(--stage-ink); }
.stage .lede { color: rgba(246,242,234,.72); }
.stage .k-label, .stage .src { color: rgba(246,242,234,.58); }
.stage a { color: var(--stage-gold); }
.stage .hero-stats .k { color: rgba(246,242,234,.58); }
.stage .hero-stats .k a { color: rgba(246,242,234,.58); }
.stage .hero-stats .k a:hover { color: var(--stage-gold); }
.stage .hero-stats .v.good { color: var(--stage-gold); }
.stage .hero-stats .v small { color: rgba(246,242,234,.58); }
.stage .btn { color: var(--stage-gold); border-color: rgba(212,175,55,.4); }
.stage .btn:hover { background: var(--stage-gold); color: var(--stage); }
.stage .btn.ghost { color: rgba(246,242,234,.7); border-color: rgba(246,242,234,.18); }
.stage .btn.ghost:hover { color: var(--stage-gold); border-color: rgba(212,175,55,.4);
                          background: transparent; }

/* A hairline of gold along the bottom edge: the stage ends, it does not stop. */
.stage-edge { position: absolute; left: 0; right: 0; bottom: 0; height: 1px; z-index: 0;
              background: linear-gradient(90deg, transparent, rgba(212,175,55,.55) 35%,
                          rgba(212,175,55,.55) 65%, transparent); }

/* The radar sits on the stage, so its palette is the dark one regardless. */
.stage .radar .rg { stroke: rgba(246,242,234,.1); }
.stage .radar .rg:last-of-type { stroke: rgba(246,242,234,.2); }
.stage .radar .ax { stroke: rgba(246,242,234,.1); }
/* The shape is the standing on the dark band too. Left gold here, the
   portfolio's chart went on saying "met" in the brand colour while the
   competency map said it in green. */
.stage .radar .shape { fill: color-mix(in srgb, var(--lv3-stage) 16%, transparent);
                       stroke: var(--lv3-stage); }
.stage .radar .dot { stroke: var(--stage); }
.stage .radar .dot.l3 { fill: var(--lv3-stage); }
.stage .radar .dot.l2 { fill: var(--lv2-stage); }
.stage .radar .lbl { fill: rgba(246,242,234,.62); }
.stage .radar .lbl.off { fill: rgba(246,242,234,.3); }
/* `crit` is a competency with nothing behind it, so it takes the Not Yet Met
   colour. Gold here made the weakest label on the chart read as the brand. */
.stage .radar .lbl.crit { fill: var(--lv1-stage); }
.stage .key { color: rgba(246,242,234,.58); }
.stage .key .k3 { background: var(--lv3-stage); }
.stage .key .k2 { background: var(--lv2-stage); }
.stage .key .k1 { background: var(--lv1-stage); }

/* ---------------------------------------------------------- rank, on stage */
.stage .rankhero { border: 0; margin: 0; padding: 0;
                   grid-template-columns: 168px 1fr; gap: 42px; }
@media (max-width: 700px) { .stage .rankhero { grid-template-columns: 1fr; gap: 24px; } }
.stage .rankmark { border-color: rgba(212,175,55,.45); background: none; }
.stage .rankmark::before { inset: 11px; border-color: rgba(246,242,234,.12); }
.stage .rankmark .num { font-size: 62px; }
.stage .rankmark .of { color: rgba(246,242,234,.4); bottom: 26px; }
.stage .rankbody h1 { font-size: clamp(2.6rem, 1.6rem + 3.4vw, 4.5rem); }
.stage .rung b { background: rgba(246,242,234,.12); height: 4px; }
.stage .rung span { color: rgba(246,242,234,.38); }
.stage .rung.done b { background: rgba(212,175,55,.55); }
.stage .rung.done span { color: rgba(246,242,234,.62); }
.stage .rung.here b { background: var(--stage-gold);
                       }
.stage .rung.here span { color: var(--stage-gold); }

/* The advance panel is glass on the stage rather than a card below it. */
.stage .advance { background: rgba(246,242,234,.045); border-color: rgba(246,242,234,.1);
                  box-shadow: none; margin-top: 34px; }
.stage .advance .ahead h3 { color: var(--stage-ink); }
.stage .areq .rq { color: rgba(246,242,234,.6); }
.stage .areq.met .rq { color: var(--stage-ink); }
.stage .areq .rp { color: rgba(246,242,234,.58); }
.stage .areq .rp b { color: var(--stage-ink); }
.stage .areq .tick { color: rgba(246,242,234,.32); }
.stage .areq.met .tick, .stage .areq.met .rp b { color: var(--stage-gold); }

/* --------------------------------------------------- warmth on the surface */
.card { transition: box-shadow var(--k-dur-fast) var(--k-ease-out),
                    border-color var(--k-dur-fast) var(--k-ease-out); }
.rowlink:hover, .person:hover, .ctile:hover, .objective:hover, .qrow:hover {
}
/* THE THIRD DECLARATION OF THIS TILE, and the one that carried a rule
   violation. It read "Mastery is the one place the surface is allowed to
   glow", which was written before the house rule of 30 September and has been
   painting a gold wash ever since. Nothing on this surface glows.
   What is left is a faint tint in the level's own colour, which says the same
   thing by being the colour the standing already is. */
.ctile.s-evidenced { background:
  linear-gradient(180deg, color-mix(in srgb, var(--lv3) 13%, transparent),
                  var(--k-field-raised) 70%); }
.comp.lv3 { background:
  linear-gradient(90deg, color-mix(in srgb, var(--lv3) 9%, transparent),
                  var(--k-field-raised) 34%); }

/* --------------------------------------------------------------- chrome, dark
   The top bar is chrome, not a reading surface, so it stays dark in both
   themes. It also removes the seam where a light header met the stage. */
.top { background: var(--stage); border-bottom-color: rgba(246,242,234,.1); }
.top .brand { color: var(--stage-ink); }
.top .brand span, .top .who { color: rgba(246,242,234,.58); }
.top .nav a { color: rgba(246,242,234,.62); }
.top .nav a:hover { color: var(--stage-ink); }
.top .nav a.on { color: var(--stage-gold); border-bottom-color: var(--stage-gold); }
.top .signout button { color: rgba(246,242,234,.58); }
.top .signout button:hover { color: var(--stage-gold); }
.top .top 
/* The stage begins where the chrome ends, so it carries no top gap. */
.stage { margin-top: -44px; }

/* =========================================================== community
   The cohort is people who meet every week. A list of rows does not say
   that; faces and a next-session card do. */
.nextup { border: 1px solid rgba(212,175,55,.32); border-radius: var(--r);
          padding: 24px 26px 26px; background: rgba(212,175,55,.06);
          display: flex; flex-direction: column; gap: 3px; align-items: flex-start; }
.nextup .nu-when { font-family: var(--k-font-display); font-variation-settings: "wdth" 75;
                   font-weight: 680; text-transform: uppercase; font-size: 40px;
                   line-height: 1; margin-top: 12px; color: var(--stage-gold); }
.nextup .nu-time { font-family: var(--k-font-mono); font-size: 18px;
                   color: var(--stage-ink); margin-top: 4px; }
.nextup .nu-what { font-size: 13.5px; margin-top: 12px; color: rgba(246,242,234,.72); }
.nextup .nu-who  { font-size: 12.5px; color: rgba(246,242,234,.58); }
.nextup .chip { margin-top: 14px; border-color: rgba(212,175,55,.4); color: var(--stage-gold); }
.nextup .chip.good { border-color: rgba(212,175,55,.55); }

.faces { display: flex; flex-wrap: wrap; gap: 10px; }
.face { display: flex; flex-direction: column; align-items: center; gap: 8px;
        width: 96px; padding: 16px 8px 14px; border: 1px solid var(--k-line);
        border-radius: var(--r); background: var(--k-field-raised);
        transition: border-color var(--k-dur-fast) var(--k-ease-out),
                    box-shadow var(--k-dur-fast) var(--k-ease-out); }
.face:hover { border-color: var(--k-line-gold); }
.face .fi { width: 42px; height: 42px; border-radius: 50%; display: grid; place-items: center;
            background: var(--k-field-edge); color: var(--k-ink-muted);
            font-family: var(--k-font-mono); font-size: 13px; font-weight: 600;
            letter-spacing: .04em; }
.face .fn { font-size: 12.5px; font-weight: 600; }
.face .fm { font-family: var(--k-font-mono); font-size: 8.5px; letter-spacing: .16em;
            text-transform: uppercase; color: var(--k-gold); }
.face.me { border-color: var(--k-line-gold); background:
           linear-gradient(180deg, var(--gold-wash), var(--k-field-raised) 70%); }
.face.me .fi { background: var(--gold-wash-2); color: var(--k-gold); }

/* An announcement is a post, not a table row: give it a date rail. */
.post { display: grid; grid-template-columns: 78px 1fr; gap: 22px;
        padding: 22px 24px; border: 1px solid var(--k-line); border-radius: var(--r);
        background: var(--k-field-raised); }
.post + .post { margin-top: 10px; }
.post .pmeta { text-align: center; border-right: 1px solid var(--k-line); padding-right: 18px; }
.post .pd { display: block; font-family: var(--k-font-display);
            font-variation-settings: "wdth" 75; font-weight: 680; font-size: 19px;
            line-height: 1.1; text-transform: uppercase; }
.post .py { display: block; font-family: var(--k-font-mono); font-size: 10px;
            letter-spacing: .14em; color: var(--k-ink-faint); margin-top: 4px; }
@media (max-width: 600px) {
  .post { grid-template-columns: 1fr; gap: 10px; }
  .post .pmeta { text-align: left; border-right: 0; border-bottom: 1px solid var(--k-line);
                 padding: 0 0 10px; display: flex; gap: 8px; align-items: baseline; }
}

/* =============================================================== audit rows
   The ring counts working days consumed of the published window, so the
   commitment is visible as a clock rather than as a date to compare. */
.areq-row { display: grid; grid-template-columns: 66px 1fr 130px; gap: 22px; align-items: center;
            padding: 20px 24px; border: 1px solid var(--k-line); border-radius: var(--r);
            background: var(--k-field-raised); }
.areq-row + .areq-row { margin-top: 10px; }
.areq-row.late { border-color: var(--risk-line); background:
                 linear-gradient(90deg, var(--a-risk-lo), var(--k-field-raised) 40%); }
.areq-row .ring .fill { stroke: var(--lv2); }
.areq-row .ring .fill.late { stroke: var(--lv1); }
.ar-top { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ar-top h3 { margin: 0; }
.ar-scope { margin: 8px 0 0; font-size: 14px; color: var(--k-ink-muted); max-width: 74ch; }
.ar-meta { margin-top: 8px; font-family: var(--k-font-mono); font-size: 10.5px;
           letter-spacing: .08em; text-transform: uppercase; color: var(--k-ink-faint); }
.ar-clock { text-align: right; display: flex; flex-direction: column;
            align-items: flex-end; gap: 4px; }
.ar-days { font-family: var(--k-font-display); font-variation-settings: "wdth" 75;
           font-weight: 680; font-size: 34px; line-height: 1; color: var(--k-gold); }
.ar-days.bad { color: var(--a-risk); }
@media (max-width: 760px) {
  .areq-row { grid-template-columns: 66px 1fr; }
  .ar-clock { grid-column: 2; align-items: flex-start; text-align: left; }
}

/* ============================================================== the feed
   A composer you can type into is the whole invitation, so it sits at the
   top of the page rather than behind a button. */
.composer { background: var(--k-field-raised); border: 1px solid var(--k-line);
            border-radius: var(--r); padding: 20px 22px; }
.composer textarea, .composer input[type=text], .composer select {
  width: 100%; font-family: var(--k-font-body); font-size: 15px; color: var(--k-ink);
  background: transparent; border: 1px solid var(--k-line); border-radius: var(--r);
  padding: 12px 14px; outline: none; resize: vertical;
  transition: border-color var(--k-dur-fast) var(--k-ease-out); }
.composer textarea:focus, .composer input:focus, .composer select:focus {
  border-color: var(--k-line-gold); }
.composer select { padding: 9px 10px; font-size: 13px; }
.composer .errorlist { color: var(--a-risk); font-size: 12.5px; margin: 6px 0 0; padding-left: 16px; }
.composer > .k-label { display: block; margin: 16px 0 6px; }
.composer > .k-label:first-child { margin-top: 0; }

.cx-kinds { display: flex; gap: 8px; margin-bottom: 14px; flex-wrap: wrap; }
.cx-kind input { position: absolute; opacity: 0; pointer-events: none; }
.cx-kind span { display: inline-block; padding: 6px 13px; border: 1px solid var(--k-line);
                border-radius: var(--r); cursor: pointer;
                font-family: var(--k-font-mono); font-size: 10px; letter-spacing: .14em;
                text-transform: uppercase; color: var(--k-ink-faint);
                transition: all var(--k-dur-fast) var(--k-ease-out); }
.cx-kind input:checked + span { border-color: var(--k-line-gold); color: var(--k-gold);
                                background: var(--gold-wash); }
.cx-kind input:focus-visible + span { outline: 2px solid var(--k-line-gold); outline-offset: 2px; }

.cx-foot { display: flex; align-items: flex-end; justify-content: space-between;
           gap: 18px; margin-top: 14px; flex-wrap: wrap; }
.cx-opts { display: flex; gap: 14px; flex-wrap: wrap; }
.cx-comp { display: flex; flex-direction: column; gap: 5px; min-width: 190px; }

/* -------------------------------------------------------------- feed posts */
.feedpost .pbody { margin: 12px 0 0; font-size: 14.5px; line-height: 1.62; max-width: 74ch; }
.feedpost.practice { border-color: var(--k-line-gold);
                     background: linear-gradient(90deg, var(--gold-wash), var(--k-field-raised) 30%); }
.pauthor { font-weight: 600; font-size: 15px; text-decoration: none; color: var(--k-ink); }
.pauthor:hover { color: var(--k-gold); }
.pbody { font-size: 15px; line-height: 1.62; max-width: 74ch; }

.pacts { display: flex; align-items: center; gap: 18px; margin-top: 14px;
         font-family: var(--k-font-mono); font-size: 10.5px; letter-spacing: .1em;
         text-transform: uppercase; }
.pacts a { text-decoration: none; }
.inline { display: inline; margin: 0; }
.ack { background: none; border: 1px solid var(--k-line); border-radius: var(--r);
       padding: 4px 12px; cursor: pointer; color: var(--k-ink-faint);
       font: inherit; letter-spacing: .1em;
       transition: all var(--k-dur-fast) var(--k-ease-out); }
.ack:hover { border-color: var(--k-line-gold); color: var(--k-gold); }
.ack.on { border-color: var(--k-line-gold); color: var(--k-gold); background: var(--gold-wash); }

/* A thread indents three deep and then stops. The order still holds under a
   flattened level, and a staircase on one column is unreadable. */
.reply { border-left: 2px solid var(--k-line); padding: 14px 0 14px 20px; margin: 10px 0; }
.reply.d1 { margin-left: 26px; }
.reply.d2 { margin-left: 52px; }
.reply.d3 { margin-left: 78px; }
.reply.d1, .reply.d2, .reply.d3 { border-left-color: var(--k-field-edge); }
.answering { display: flex; align-items: center; gap: 12px; margin: 0 0 12px;
             font-size: 13px; color: var(--k-ink-muted); }
/* `display` beats the hidden attribute, so the line has to say so itself.
   Without this the cancel sat under every empty reply box. */
.answering[hidden] { display: none; }
@media (max-width: 680px) {
  .reply.d1 { margin-left: 12px; }
  .reply.d2 { margin-left: 24px; }
  .reply.d3 { margin-left: 36px; }
}

/* Search. One field, full width: the question people bring here is a phrase,
   not a form. */
.srch {
  width: 100%; font: inherit; font-size: 17px; padding: 14px 16px;
  background: var(--k-field-raised); color: var(--k-ink);
  border: 1px solid var(--k-field-edge); border-radius: 2px;
}
.srch:focus { outline: 2px solid var(--k-line-gold); outline-offset: 1px; }
.hit { margin: 12px 0 0; padding: 10px 0 10px 14px; border-left: 2px solid var(--k-line-gold); }
.hit p { margin: 6px 0 0; font-size: 14px; line-height: 1.55; color: var(--k-ink-muted); }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden;
           clip: rect(0 0 0 0); white-space: nowrap; }
.reply:hover { border-left-color: var(--k-line-gold); }
.reply .pbody { margin: 8px 0 0; font-size: 14.5px; }

.shead .act a { text-decoration: none; font-family: var(--k-font-mono); font-size: 10px;
                letter-spacing: .14em; text-transform: uppercase; color: var(--k-ink-faint); }
.shead .act a:hover, .shead .act a.on { color: var(--k-gold); }

/* Unanswered practice requests, on the stage. Nothing is worse for a cohort
   than someone asking for practice and hearing nothing back. */
.opq { display: flex; gap: 12px; align-items: baseline; text-decoration: none;
       padding: 8px 0; border-top: 1px solid rgba(246,242,234,.1); }
.opq:first-child { border-top: 0; }
.opq b { font-family: var(--k-font-mono); font-size: 11px; letter-spacing: .1em;
         color: var(--stage-gold); }
.opq span { font-size: 13px; color: rgba(246,242,234,.72); }
.opq:hover span { color: var(--stage-ink); }

/* ------------------------------------------------------------- member cards */
.mhead { display: flex; gap: 13px; align-items: center; }
.mhead .fi { width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center;
             background: var(--k-field-edge); color: var(--k-ink-muted); flex: 0 0 40px;
             font-family: var(--k-font-mono); font-size: 12px; font-weight: 600; }
.mhl { margin: 14px 0 0; font-size: 13.5px; color: var(--k-ink-muted); line-height: 1.5; }

/* ============================================================== avatars
   Initials rather than a stock silhouette. An empty photo should look like
   someone who has not uploaded one, not like an anonymous user. */
.av { border-radius: 50%; display: grid; place-items: center; flex: 0 0 auto;
      object-fit: cover; background: var(--k-field-edge); color: var(--k-ink-muted);
      font-family: var(--k-font-mono); font-weight: 600; letter-spacing: .04em; }
.av.sm { width: 26px; height: 26px; font-size: 9px; }
.av.md { width: 42px; height: 42px; font-size: 12px; }
.av.lg { width: 96px; height: 96px; font-size: 26px; border: 1px solid var(--k-line-gold); }
.stage .av.ini { background: rgba(246,242,234,.08); color: rgba(246,242,234,.66); }
.phero { display: flex; gap: 28px; align-items: center; flex-wrap: wrap; }
.face .av { margin-bottom: 2px; }
.post .pmeta .av { margin: 0 auto 8px; }

/* -------------------------------------------------------- direct messages */
.convo { display: grid; grid-template-columns: 42px 1fr auto; gap: 16px; align-items: center;
         padding: 16px 20px; border: 1px solid var(--k-line); border-radius: var(--r);
         background: var(--k-field-raised);
         text-decoration: none; color: inherit;
         transition: border-color var(--k-dur-fast) var(--k-ease-out); }
.convo + .convo { margin-top: 8px; }
.convo:hover { border-color: var(--k-line-gold); color: inherit; }
.convo.unread { border-color: var(--k-line-gold); background:
                linear-gradient(90deg, var(--gold-wash), var(--k-field-raised) 30%); }
.cv-top { display: flex; align-items: center; gap: 10px; }
.cv-last { font-size: 13.5px; color: var(--k-ink-muted); margin-top: 4px; }

.thread { display: flex; flex-direction: column; gap: 10px; }
.msg { max-width: 68ch; padding: 14px 18px; border: 1px solid var(--k-line);
       border-radius: var(--r); background: var(--k-field-raised); }
.msg p { margin: 8px 0 0; font-size: 14.5px; line-height: 1.6; }
.msg.mine { align-self: flex-end; border-color: var(--k-line-gold);
            background: linear-gradient(180deg, var(--gold-wash), var(--k-field-raised) 70%); }
.msg.system { align-self: center; max-width: 74ch; text-align: center; box-shadow: none;
              border-style: dashed; border-color: var(--risk-line); background: var(--a-risk-lo); }
.msg.system p { font-size: 13px; color: var(--k-ink-muted); }
.mhdr { display: flex; align-items: center; gap: 9px; }
.mhdr b { font-size: 13.5px; }
.mhdr .rep { margin-left: auto; text-decoration: none; }
.mhdr .rep:hover { color: var(--a-risk); }

/* ================================================================= motion
   The reveal is directional and staged. Elements start slightly low and
   slightly small, so arrival reads as approach rather than as a fade. */
html.k-motion [data-reveal] { opacity: 0; transform: translateY(18px) scale(.995); }
html.k-motion [data-reveal].shown {
  opacity: 1; transform: none;
  transition: opacity .7s var(--k-ease-out), transform .7s var(--k-ease-out);
}

/* The medallion breathes. Very slow and very small: at this amplitude it
   registers as "live" without ever asking to be looked at. */


/* Objectives lead with their urgency bar, which wipes in from the top. */
html.k-motion .objective .obar { transform: scaleY(0); transform-origin: top;
  transition: transform .5s var(--k-ease-out) .15s; }
html.k-motion .objective.shown .obar { transform: scaleY(1); }

/* Interactive surfaces say so before they are touched. */
.ctile, .person, .objective, .qrow, .convo, .face, .areq-row, .card.rowlink {
  will-change: transform;
  transition: transform var(--k-dur-fast) var(--k-ease-out),
              border-color var(--k-dur-fast) var(--k-ease-out),
              box-shadow var(--k-dur-fast) var(--k-ease-out);
}
html.k-motion .ctile:hover, html.k-motion .person:hover,
html.k-motion .objective:hover, html.k-motion .convo:hover,
html.k-motion .face:hover, html.k-motion .card.rowlink:hover { transform: translateY(-2px); }
html.k-motion .ctile.s-evidenced:hover { transform: translateY(-3px); }

.journey b { cursor: crosshair; }

/* The strip is scrubbed across, and a native tooltip is both too slow and
   unstyleable for a 24-bar row. */
.tip { position: absolute; z-index: 60; transform: translate(-50%, -100%);
       background: var(--stage); color: var(--stage-ink);
       font-family: var(--k-font-mono); font-size: 10px; letter-spacing: .1em;
       text-transform: uppercase; padding: 6px 10px; border-radius: 3px;
       pointer-events: none; opacity: 0; white-space: nowrap;
       transition: opacity var(--k-dur-fast) var(--k-ease-out); }
.tip.on { opacity: 1; }

/* Focus is visible and gold, never removed. */
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--k-gold); outline-offset: 3px; border-radius: 2px;
}

@media (prefers-reduced-motion: reduce) {
  html.k-motion [data-reveal] { opacity: 1; transform: none; transition: none; }
  * { transition: none !important; }
}

/* ============================================================== transcript
   The record set the way a supervisor works: a timecode down the left, the
   moment in the middle, and the mentor's words hanging in the right margin.

   This is deliberately not a card grid. Assessment is annotation on a
   session, and annotation lives beside the thing it annotates. The margin
   column is allowed to break the reading measure, because that is what a
   margin is for. */
.thead { display: flex; align-items: baseline; justify-content: space-between;
         gap: 18px; margin: 56px 0 18px; padding-bottom: 12px;
         border-bottom: 1px solid var(--k-ink); }
.tcomp { padding: 30px 0 26px; border-bottom: 1px solid var(--k-line); }
.tcomp:last-child { border-bottom: 0; }

.tcomp-h { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; }
.tcomp-h h3 { margin: 0; font-size: 20px; font-weight: 600; letter-spacing: -.015em; }
.tc-code { font-family: var(--k-font-mono); font-size: 12px; font-weight: 700;
           letter-spacing: .06em; color: var(--k-ink-faint); }
.tcomp.lv3 .tc-code { color: var(--lv3); }
.tcomp.lv0 .tcomp-h h3 { color: var(--k-ink-faint); }
.tcomp-standing { margin-left: auto; }

/* Timecode, moment, margin. The margin column hangs past the text measure. */
.tline { display: grid; grid-template-columns: 76px minmax(0, 1fr) 300px;
         gap: 22px; align-items: start; padding: 16px 0 15px;
         border-top: 1px solid var(--line-soft); }
.tcomp-h + .tline { border-top: 0; padding-top: 18px; }
@media (max-width: 1080px) {
  .tline { grid-template-columns: 76px minmax(0, 1fr); }
  .tnote { grid-column: 2; margin-top: 4px; }
}
@media (max-width: 560px) { .tline { grid-template-columns: 1fr; } .tnote { grid-column: 1; } }

/* The timecode is the anchor, so it is set like one: monospaced, aligned,
   and the only thing on its line. */
.tc { font-family: var(--k-font-mono); font-variant-numeric: tabular-nums;
      font-size: 15px; letter-spacing: .02em; color: var(--k-ink);
      padding-top: 1px; white-space: nowrap; }
.tline.latest .tc { color: var(--k-gold); }
.empty-line .tc { color: var(--k-ink-faint); }

.tmeta { font-size: 13px; color: var(--k-ink-muted); margin-bottom: 9px; }
.tbody .level { font-size: 10px; }

/* The annotation voice: larger, italic, hanging quote, attributed. It should
   read as somebody's handwriting in the margin, not as a table cell. */
.tnote { border-left: 1px solid var(--k-line-gold); padding: 0 0 0 18px; position: relative; }
.tnote p { margin: 0; font-size: 15px; line-height: 1.55; font-style: italic;
           color: var(--k-ink); text-wrap: pretty; }
.tnote p::before { content: "\201C"; position: absolute; left: 6px; top: -6px;
                   font-size: 30px; line-height: 1; color: var(--k-line-gold);
                   font-style: normal; }
.tnote cite { display: block; margin-top: 8px; font-size: 12.5px; font-style: normal;
              color: var(--k-ink-faint); }
.tnote cite::before { content: "\2014\00a0"; }
.tline.latest .tnote { border-left-color: var(--k-gold); }

.tfoot { margin: 14px 0 0 98px; font-size: 13px; color: var(--k-ink-muted); }
.tfoot.up { color: var(--k-gold); }
.tfoot.down { color: var(--a-risk); }
@media (max-width: 560px) { .tfoot { margin-left: 0; } }

/* ------------------------------------------------------------ seekable time
   A timecode that can be jumped to must look like a control, or nobody
   discovers that it is one. */
.tc.seekable { background: none; border: 1px solid transparent; border-radius: 3px;
               padding: 1px 6px; margin-left: -6px; cursor: pointer;
               font: inherit; color: var(--k-gold);
               transition: all var(--k-dur-fast) var(--k-ease-out); }
.tc.seekable:hover { border-color: var(--k-line-gold); background: var(--gold-wash); }
.tc.seekable::after { content: " \25B8"; opacity: .55; }

.player { width: 100%; max-height: 420px; margin-top: 14px; border-radius: var(--r);
          background: #000; display: block; }
[data-player-status].bad { color: var(--a-risk); }

.scorerow { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 14px; margin-bottom: 4px; }
@media (max-width: 760px) { .scorerow { grid-template-columns: 1fr; } }
.stamprow { display: flex; gap: 8px; }
.stamprow input { flex: 1; min-width: 0; }
.btn.stamp { padding: 9px 14px; letter-spacing: .12em; white-space: nowrap; }
.checkrow { display: flex; align-items: center; gap: 9px; font-size: 13.5px;
            color: var(--k-ink-muted); }
.checkrow input { accent-color: var(--k-gold); width: 16px; height: 16px; }

/* ------------------------------------------------------------------ upload */
.up-pick { cursor: pointer; padding: 7px 14px; font-size: 10px; }
.up-status { font-family: var(--k-font-mono); font-size: 10px; letter-spacing: .1em;
             text-transform: uppercase; color: var(--k-ink-muted); margin-top: 6px; }
.up-status.good { color: var(--k-gold); }
.up-status.warn { color: var(--k-ink); }
.up-status.bad  { color: var(--a-risk); }
.up-bar { width: 150px; height: 3px; background: var(--k-field-edge); margin-top: 6px; }
.up-bar i { display: block; height: 100%; background: var(--k-gold); width: 0;
            transition: width .25s linear; }

/* ------------------------------------------------------------- timetable
   Twenty-four rows, each one a week. The phase is a left edge rather than a
   heading, so the three blocks read as blocks without repeating a label. */
.wks { display: flex; flex-direction: column; }
.wks .wk-row { display: grid; grid-template-columns: 62px 1fr 1fr 84px; gap: 18px;
          align-items: center; padding: 11px 0 11px 14px;
          border-top: 1px solid var(--line-soft); border-left: 2px solid transparent; }
.wks .wk-row:first-child { border-top: 0; }
.wks .wk-row.p1 { border-left-color: var(--k-line); }
.wks .wk-row.p2 { border-left-color: var(--line-firm); }
.wks .wk-row.p3 { border-left-color: var(--k-line-gold); }
.wks .wk-row.gated { background: var(--gold-wash); }
.wks .wk-n b { font-family: var(--k-font-mono); font-size: 14px; font-variant-numeric: tabular-nums; }
.wks .wk-n span { display: block; font-family: var(--k-font-mono); font-size: 9.5px;
             letter-spacing: .14em; color: var(--k-ink-faint); margin-top: 2px; }
.wks .wk-slot { display: flex; flex-direction: column; gap: 3px; }
.wks .wk-when { font-size: 13.5px; }
.wks .wk-min { font-family: var(--k-font-mono); font-size: 10px; letter-spacing: .1em;
          color: var(--k-ink-faint); }
.wks .wk-slot .chip { align-self: flex-start; margin-top: 3px; }
.wks .wk-tot { text-align: right; font-family: var(--k-font-mono); font-size: 11px;
          color: var(--k-ink-muted); font-variant-numeric: tabular-nums; }
.wks + .wk-key { display: flex; gap: 20px; margin-top: 16px; padding-top: 14px;
          border-top: 1px solid var(--k-line); flex-wrap: wrap; }
@media (max-width: 760px) {
  .wks .wk-row { grid-template-columns: 52px 1fr; }
  .wks .wk-tot { grid-column: 2; text-align: left; }
}
.wks .wk-title { font-size: 13.5px; font-weight: 600; line-height: 1.35; }
.wks .wk-slot .wk-when { font-family: var(--k-font-mono); font-size: 10px; letter-spacing: .08em;
                    color: var(--k-ink-faint); margin-top: 3px; }
.wks .wk-row { grid-template-columns: 62px 1fr 1fr 74px; align-items: start; padding-top: 13px;
          padding-bottom: 13px; }

/* ══════════════════════════════════════════════════ THE JOURNEY
   Athletic-performance register: the numbers are the interface. Big tabular
   figures on the stage, a track you read down, and gauges that show the
   distance left rather than a decorative percentage.

   Everything here uses the existing tokens. The only new idea is scale: a
   readout figure is allowed to be enormous, because on a performance screen
   the number IS the content and the label is the annotation. */

.jrn-head { padding-block: clamp(28px, 5vw, 56px) clamp(24px, 4vw, 44px); }
/* ------------------------------------------------------------- the measure
   THE READING COLUMN, and why it is not `92vw`.

   `vw` counts the classic scrollbar and `100%` does not. Eight rules declared
   `min(1180px, 92vw)` and centred each with auto margins, so on a viewport with
   a 5px scrollbar the column was centred in 380 inside a 375px client area:
   the left gutter kept 30px and the right one went to zero, with the shape
   bars and the section rules running into the edge. Overlay scrollbars hide
   it, which is why it survived on this machine until a phone width was
   measured.

   `100% - 2rem` resolves against the parent, which already excludes the
   scrollbar, so the gutters are equal whatever the browser does and a phone
   keeps the 16px side margin. */
:root {
  /* ONE READING COLUMN, and it is a percentage of whatever already
     provided the gutter: `main` pads 30px each side for the page body, and
     `.stage` computes its own padding so a full-bleed band lines up with the
     text below it. Both leave a content box of the right width, so 100% is
     the answer in both places.

     Two tokens were tried first, one of them subtracting the gutter a second
     time, and the two stage variants that zeroed the stage's own padding
     meant the same token was right on three pages and thirty pixels wrong on
     two others. They no longer zero it. */
  --measure-in: min(1180px, 100%);
}

.jrn-head-in { width: var(--measure-in); margin: 0 auto; }
.jrn-eyebrow {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75; font-weight: 700;
  font-size: 11px; letter-spacing: .28em; text-transform: uppercase;
  color: var(--stage-gold);
}
.jrn-phase h1 {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75;
  font-weight: 700; letter-spacing: -.03em; line-height: .92;
  font-size: clamp(2.4rem, 7vw, 4.6rem);
  margin: 6px 0 0; color: var(--stage-ink); text-transform: uppercase;
}

/* the readout ------------------------------------------------------------ */
/* One lead and three supporting figures, not four equals. A row of equal
   numbers hands the ranking to the reader, and the ranking is the only part
   of this they cannot work out for themselves. */
.readout {
  display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1.5fr);
  gap: clamp(20px, 4vw, 54px);
  margin-top: clamp(22px, 4vw, 40px);
  border-top: 1px solid rgba(246, 242, 234, .14); padding-top: 22px;
  align-items: start;
}
.ro-rest { display: grid; grid-template-columns: repeat(3, 1fr);
           gap: clamp(14px, 3vw, 34px); align-self: end; padding-bottom: 4px; }
.ro-lead .ro-n { font-size: clamp(3.4rem, 8.6vw, 6rem);
                 font-variant-numeric: tabular-nums; }
.ro-lead .ro-of { font-size: .26em; }
.ro-lead .ro-l { font-size: 12.5px; max-width: 22ch; }
.ro-lead.ro-clear .ro-n { color: var(--a-met-stage, #8fc29a); }
.ro-note { font-size: 13px; line-height: 1.45; color: rgba(246, 242, 234, .72);
           max-width: 26ch; margin-top: 2px; }
.ro-rest .ro-n { font-size: clamp(1.5rem, 3vw, 2rem);
                 font-variant-numeric: tabular-nums; }
@media (max-width: 860px) {
  .readout { grid-template-columns: 1fr; row-gap: 26px; }
  .ro-rest { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 560px) { .ro-rest { grid-template-columns: repeat(2, 1fr); row-gap: 22px; } }
.ro { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.ro-n {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 96;
  font-weight: 700; font-size: clamp(2.1rem, 5.2vw, 3.4rem);
  line-height: .9; letter-spacing: -.035em;
  color: var(--stage-ink); font-variant-numeric: tabular-nums;
}
.ro-rank { color: var(--stage-gold); }
.ro-of {
  font-size: .42em; font-weight: 600; letter-spacing: 0;
  color: rgba(246, 242, 234, .58); margin-left: 2px;
}
.ro-l {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75; font-weight: 700;
  font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase;
  color: rgba(246, 242, 234, .58); line-height: 1.4;
}

.jrn-elapsed { margin-top: clamp(20px, 3vw, 34px); }
.jrn-elapsed-bar {
  height: 4px; border-radius: 2px; overflow: hidden;
  background: rgba(246, 242, 234, .13);
}
.jrn-elapsed-bar i {
  display: block; height: 100%; width: 0;
  background: var(--stage-gold);
  border-radius: 2px;
}
.k-motion .jrn-elapsed-bar i { transition: width 1.1s cubic-bezier(.16, 1, .3, 1) .15s; }
.jrn-elapsed-bar i { width: var(--w); }
.jrn-elapsed-l {
  display: flex; justify-content: space-between; gap: 16px; margin-top: 10px;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75; font-weight: 700;
  font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  color: rgba(246, 242, 234, .6);
}
.jrn-elapsed-l strong { color: var(--stage-ink); font-weight: 600; }

/* the track -------------------------------------------------------------- */
.sec-h {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75; font-weight: 700;
  text-transform: uppercase; letter-spacing: -.015em;
  font-size: clamp(1.3rem, 2.6vw, 1.9rem); margin: 0 0 6px;
  /* It inherited --k-ink-faint and landed at 2.95:1, just under the 3:1 a
     heading this size needs. A section heading is the thing you read to find
     your place on a page. */
  color: var(--k-ink-muted);
}
.pad { width: var(--measure-in); margin: 0 auto; padding: clamp(34px, 5vw, 58px) 0; }
.pad-alt { border-top: 1px solid var(--k-field-edge); }
.pad-end { border-top: 1px solid var(--k-field-edge); }

/* THE TRACK CLIMBS. Week one at the bottom, the capstone at the top, so
   the page is ascended rather than descended. The tree grows up from a
   seed and so does the programme; reading it downward said the opposite.
   column-reverse flips what is SEEN and leaves the DOM in week order, so
   a screen reader still goes one to twenty-four. Reversing the list in
   the view would have read it backwards. */
.track {
  list-style: none; margin: 30px 0 0; padding: 0; position: relative;
  display: flex; flex-direction: column-reverse;
}
/* the spine the dots sit on */
.track::before {
  content: ""; position: absolute; left: 78px; top: 10px; bottom: 10px; width: 2px;
  background: var(--k-field-edge);
}
@media (max-width: 640px) { .track::before { left: 46px; } }

.ck {
  position: relative; display: grid;
  grid-template-columns: 62px 34px 1fr; align-items: start;
  gap: 0 14px; padding: 14px 0;
}
@media (max-width: 640px) { .ck { grid-template-columns: 34px 24px 1fr; } }
.ck-wk {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75; font-weight: 700;
  font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--k-ink-muted); text-align: right; padding-top: 6px;
  font-variant-numeric: tabular-nums;
}
.ck-dot {
  width: 14px; height: 14px; border-radius: 50%; margin-top: 5px;
  background: var(--k-field); border: 2px solid var(--k-field-edge);
  justify-self: center; position: relative; z-index: 1;
}
.ck-body h3 {
  font-family: "Instrument Sans", system-ui, sans-serif; font-weight: 700;
  font-size: 1.02rem; margin: 0 0 3px; letter-spacing: -.01em;
}
.ck-body p { margin: 0 0 5px; color: var(--k-ink-muted); font-size: .92rem; max-width: 62ch; }
.ck-state {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75; font-weight: 700;
  font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--k-ink-muted);
}

.ck-done .ck-dot { background: var(--k-gold); border-color: var(--k-gold); }
.ck-done .ck-state { color: var(--k-gold); }
.ck-done .ck-body h3 { color: var(--k-ink); }

.ck-current .ck-dot {
  /* No halo. The row already says "you are here" and a ring of colour around
     a dot is a glow whatever its blur radius. Scale and a solid fill do the
     same job with none of the tell. */
  background: var(--k-gold); border-color: var(--k-gold);
  width: 18px; height: 18px; margin-top: 3px;
}
.ck-current .ck-body { position: relative; }
/* Only the phase she is standing in says so.
   "Current" on this track means "still in front of you", which is the right
   state for a gate she has not passed and the wrong word to print on it. At
   week eighteen the label appeared three times: on the Phase 1 Gate, on the
   Phase 2 Gate and on Phase 3. She can only be in one place, and the Route
   next door draws exactly one marker, so the two screens disagreed about where
   she was. A gate keeps its own detail line, which already reads "Due now". */
.ck-current.ck-phase .ck-body h3::after {
  content: "you are here"; margin-left: 10px;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75; font-weight: 700;
  font-size: 9.5px; letter-spacing: .18em; text-transform: uppercase;
  color: var(--k-gold); vertical-align: middle;
}
/* Quieter, not unreadable. At .62 the body of an ahead checkpoint ran at
   2.98:1, and the capstone paragraph is the single thing on this page a
   student most wants to read in advance. */
.ck-ahead .ck-body h3,
.ck-ahead .ck-body p { opacity: .82; }

/* Overdue is its own state. It used to render as "current", which told a
   student in week 18 that her week 8 gate was today's business and put two
   you-are-here markers on one track. */
.ck-overdue .ck-dot { background: var(--a-risk); border-color: var(--a-risk); }
.ck-overdue .ck-state { color: var(--a-risk); font-weight: 700; }
.ck-overdue .ck-body h3 { color: var(--k-ink); }

/* gauges ----------------------------------------------------------------- */
.gauges {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 22px 30px; margin-top: 28px;
}
.gauge-top { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.gauge-l {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75; font-weight: 700;
  font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--k-ink-muted);
}
.gauge-v {
  font-family: "Instrument Sans", system-ui, sans-serif; font-weight: 700;
  font-size: 1.5rem; letter-spacing: -.03em; font-variant-numeric: tabular-nums;
  font-variation-settings: "wdth" 75;
}
.gauge-t { font-size: .58em; font-weight: 600; color: var(--k-ink-muted); letter-spacing: 0; }
.gauge-bar {
  height: 6px; border-radius: 3px; overflow: hidden;
  background: var(--k-field-edge); margin-top: 8px;
}
.gauge-bar i {
  display: block; height: 100%; width: var(--w); border-radius: 3px;
  background: var(--k-gold);
}
.k-motion .gauge-bar i { transition: width 1s cubic-bezier(.16, 1, .3, 1) .1s; }
.gauge-met .gauge-bar i { background: var(--k-gold); }
.gauge-foot {
  display: flex; justify-content: space-between; gap: 12px; margin-top: 7px;
  font-size: 11.5px; color: var(--k-ink-muted);
}
.gauge-done { color: var(--k-gold); font-weight: 600; }
.gauge-note { text-align: right; max-width: 30ch; opacity: .92; }

/* objectives -------------------------------------------------------------- */
.objectives { list-style: none; margin: 26px 0 0; padding: 0; display: grid; gap: 2px; }
.objectives li {
  display: grid; grid-template-columns: 40px 1fr auto; align-items: center;
  gap: 16px; padding: 18px 0; border-top: 1px solid var(--k-field-edge);
}
.objectives li:last-child { border-bottom: 1px solid var(--k-field-edge); }
.obj-n {
  font-family: "Instrument Sans", system-ui, sans-serif; font-weight: 700;
  /* --k-field-edge is a SURFACE token: it is the colour of a hairline between
     two panels. Used as ink it put this numeral at 1.11:1, which is a number
     nobody can read at any size. The rank of an objective is information, so
     it takes an ink token like everything else that is. */
  font-size: 1.4rem; color: var(--k-ink-faint); font-variant-numeric: tabular-nums;
  font-variation-settings: "wdth" 75;
}
.objectives h3 { font-size: .98rem; margin: 0 0 2px; font-weight: 700; }
.objectives p { margin: 0; font-size: .9rem; color: var(--k-ink-muted); }

/* end state --------------------------------------------------------------- */
.endstate {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 26px 40px; margin-top: 26px;
}
.end-n {
  display: block;
  font-family: "Instrument Sans", system-ui, sans-serif; font-weight: 700;
  font-variation-settings: "wdth" 96;
  font-size: clamp(2.6rem, 6vw, 3.8rem); line-height: .9; letter-spacing: -.04em;
  color: var(--k-gold); font-variant-numeric: tabular-nums;
}
.end-l { display: block; margin-top: 8px; font-size: .92rem; color: var(--k-ink-muted); max-width: 34ch; }
.end-note { margin-top: 28px; max-width: 68ch; }

@media (prefers-reduced-motion: reduce) {
  .jrn-elapsed-bar i, .gauge-bar i { transition: none !important; }
}
.jrn-sub {
  margin: 12px 0 0; max-width: 56ch; font-size: 1rem;
  color: rgba(246, 242, 234, .72); line-height: 1.55;
}

/* ───────────────────────────────────────────── the status line
   Replaces the three-up card triplet, which is the single most-cited marker
   of generated design ("big number, small label, three supporting stats" in
   three shadowed cards). Same three facts, separated by a rule and a field
   shift rather than by three floating surfaces. Denser on purpose: density
   variation is what says somebody decided what mattered. */
.statline {
  display: grid; grid-template-columns: repeat(3, 1fr);
  border-top: 1px solid var(--k-line); margin-top: 18px;
}
@media (max-width: 660px) { .statline { grid-template-columns: 1fr; } }
.sl {
  padding: 16px 22px 16px 0; display: flex; flex-direction: column; gap: 3px;
  border-right: 1px solid var(--k-line);
}
.sl:last-child { border-right: 0; }
.sl + .sl { padding-left: 22px; }
@media (max-width: 660px) {
  .sl { border-right: 0; border-bottom: 1px solid var(--k-line); padding-left: 0; }
  .sl + .sl { padding-left: 0; }
  .sl:last-child { border-bottom: 0; }
}
.sl-v {
  font-family: "Instrument Sans", system-ui, sans-serif; font-weight: 700;
  font-size: 2.1rem; line-height: .95; letter-spacing: -.035em;
  font-variant-numeric: tabular-nums; color: var(--k-ink);
  font-variation-settings: "wdth" 75;
}
.sl-v.sl-txt { font-size: 1.15rem; letter-spacing: -.01em; line-height: 1.2; }
.sl-of { font-size: .5em; font-weight: 600; color: var(--k-ink-muted); letter-spacing: 0; }
.sl-k {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75; font-weight: 700;
  font-size: 10.5px; letter-spacing: .15em; text-transform: uppercase;
  color: var(--k-ink-muted); margin-top: 4px;
}
.sl-s { font-size: 12.5px; color: var(--k-ink-muted); }

/* ── phase colour applied ─────────────────────────────────────────────────
   The hue answers one question only: which phase is this. It appears on the
   spine dot, the phase heading and the stage eyebrow, and nowhere else. */
/* Three countries, not one field with three words on it. The ground opens and
   lifts across the programme, and the light moves with it: high and weak where
   the canopy is closed, low and strong once it is ahead of her.
   Each stays dark enough to carry the stage's own ink tokens, which is checked
   by measuring the rendered page rather than by reading these numbers. */
.jrn-p1 { --stage: #101a14; --stage-2: #1c2c20; --px: 50%; --py: -34%; }
.jrn-p2 { --stage: #1a2719; --stage-2: #2b3a22; --px: 64%; --py: 44%; }
.jrn-p3 { --stage: #222d1d; --stage-2: #3f4b2a; --px: 50%; --py: 122%; }
/* The wood itself, drawn by js/band.js, between the light pool and the grain. */
.stage-sky {
  position: absolute; inset: 0; width: 100%; height: 100%;
  z-index: -1; pointer-events: none; opacity: .92;
}
.stage::after { z-index: 0; }
.jrn-head-in { position: relative; z-index: 1; }

.jrn-p1 .jrn-eyebrow { color: var(--ph1-stage); }
.jrn-p2 .jrn-eyebrow { color: var(--ph2-stage); }
.jrn-p3 .jrn-eyebrow { color: var(--ph3-stage); }
.jrn-p1 .jrn-elapsed-bar i { background: var(--ph1-stage); }
.jrn-p2 .jrn-elapsed-bar i { background: var(--ph2-stage); }
.jrn-p3 .jrn-elapsed-bar i { background: var(--ph3-stage); }
.jrn-p1 .ro-rank { color: var(--ph1-stage); }
.jrn-p2 .ro-rank { color: var(--ph2-stage); }
.jrn-p3 .ro-rank { color: var(--ph3-stage); }

/* the track: each phase band and its own checkpoints carry the phase hue */
.ck-ph1.ck-done .ck-dot, .ck-ph1.ck-current .ck-dot { background: var(--ph1); border-color: var(--ph1); }
.ck-ph2.ck-done .ck-dot, .ck-ph2.ck-current .ck-dot { background: var(--ph2); border-color: var(--ph2); }
.ck-ph3.ck-done .ck-dot, .ck-ph3.ck-current .ck-dot { background: var(--ph3); border-color: var(--ph3); }
.ck-ph1 .ck-state, .ck-ph1.ck-current .ck-body h3::after { color: var(--ph1); }
.ck-ph2 .ck-state, .ck-ph2.ck-current .ck-body h3::after { color: var(--ph2); }
.ck-ph3 .ck-state, .ck-ph3.ck-current .ck-body h3::after { color: var(--ph3); }
.ck-ahead .ck-state { color: var(--k-ink-muted); }
/* a checkpoint that has been passed carries its phase hue as a left rule */
.ck-done .ck-body { border-left: 2px solid transparent; padding-left: 0; }
.ck-ph1.ck-done .ck-body { border-color: var(--ph1); }
.ck-ph2.ck-done .ck-body { border-color: var(--ph2); }
.ck-ph3.ck-done .ck-body { border-color: var(--ph3); }

/* gauges: met is green because met is a different fact from in progress */
.gauge-bar i { background: var(--k-gold); }
.gauge-met .gauge-bar i { background: var(--a-met); }
.gauge-done { color: var(--a-met); }
.gauge-near .gauge-bar i { background: var(--ph2); }

/* end state: the three figures take the three phase hues, left to right */
.endstate > :nth-child(1) .end-n { color: var(--ph1); }
.endstate > :nth-child(2) .end-n { color: var(--ph2); }
.endstate > :nth-child(3) .end-n { color: var(--ph3); }

/* the eight competency tiles: evidenced is green, in practice is the phase
   hue of the phase you are in, unobserved stays ink at low opacity.
   The colour is set once, where the tile is defined. */

/* ── notification preferences ─────────────────────────────────────────── */
.switch { display: flex; gap: 12px; align-items: flex-start; padding: 14px 0;
          border-top: 1px solid var(--k-line); cursor: pointer; }
.switch input { margin-top: 3px; flex: none; }
.catlist { margin: 18px 0 24px; }
.catlist .switch:last-child { border-bottom: 1px solid var(--k-line); }

/* ── the week board ───────────────────────────────────────────────────────
   Four questions in order, and the first two get the whole stage. Density is
   deliberate here: this band is the densest region of the screen and the rest
   of the page is quiet, which is what says somebody decided what mattered. */
.wb { padding-block: clamp(26px,5vw,52px) clamp(22px,4vw,40px); }
.wb-in { width: var(--measure-in); margin: 0 auto; }
.wb-h {
  font-family: "Instrument Sans", system-ui, sans-serif; font-variation-settings: "wdth" 75;
  font-weight: 700; text-transform: uppercase; letter-spacing: -.03em; line-height: .95;
  font-size: clamp(1.9rem,5.4vw,3.4rem); margin: 10px 0 0; color: var(--stage-ink);
}
.wb-h.wb-late { color: var(--stage-late); }
.wb-due { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 2px; }
.wb-due a {
  display: flex; justify-content: space-between; gap: 18px; align-items: baseline;
  padding: 12px 0; border-top: 1px solid rgba(246,242,234,.14);
  color: var(--stage-ink); text-decoration: none;
}
.wb-due a:hover .d-l { color: var(--ph2-stage); }
.d-l { font-weight: 600; font-size: 1.02rem; }
.d-w {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75; font-weight: 700; font-size: 11px;
  letter-spacing: .12em; text-transform: uppercase; color: rgba(246,242,234,.6);
}
.d-overdue .d-w { color: var(--stage-late); }
.d-soon .d-w { color: var(--ph2-stage); }
.wb-delta {
  margin: 22px 0 0; max-width: 60ch; font-size: 1.02rem; line-height: 1.5;
  color: rgba(246,242,234,.82);
}
.wb-next {
  display: grid; grid-template-columns: 3px 1fr auto; gap: 18px; align-items: center;
  padding: 20px 0; border-top: 1px solid var(--k-line);
  border-bottom: 1px solid var(--k-line); margin-top: 18px;
  color: inherit; text-decoration: none;
}
.wb-next:hover .ot { color: var(--k-gold); }
.wb-next .obar { align-self: stretch; background: var(--ph2); }
.wb-next.u-overdue .obar { background: var(--ph3); }

/* ── the weekly record ────────────────────────────────────────────────────
   Twenty-four cells, one per week. Deliberately not a flame and not a daily
   counter: the programme runs two sessions a week, so weekly is the honest
   period, and a manufactured daily obligation would read as theatre to a
   senior operator inside a week. */
.wkgrid {
  list-style: none; margin: 24px 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(24, 1fr); gap: 4px;
}
@media (max-width: 720px) { .wkgrid { grid-template-columns: repeat(12, 1fr); } }
.wkgrid .wk {
  aspect-ratio: 1; border-radius: 2px; display: grid; place-items: center;
  background: rgba(246,242,234,.07); border: 1px solid transparent;
}
.wkgrid .wk-n {
  font-family: "Instrument Sans", system-ui, sans-serif; font-size: 9px;
  /* .34 put the week numerals at 2.92:1 on the unlit cells, which is every
     week she has not reached. The one piece of text on the strip that says
     which week you are looking at was the least readable thing on it. */
  color: rgba(246,242,234,.62); font-variant-numeric: tabular-nums;
}
/* One vocabulary for week state, shared with the week board's strip and the
   standing bug. It was two: this grid drew a held week in programme gold while
   the dashboard drew the same week in the bug's green, and a student reads both
   screens in the same minute. The bug tokens win because they carry a measured
   contrast ratio in each theme and the phase tokens do not.

   Recovered is a held week that was not held first time, so it reads as met and
   hollow: the colour says it counts, the fill says how. */
.wkgrid .wk-complete  { background: var(--bug-met); }
.wkgrid .wk-deferred  { background: rgba(246,242,234,.13);
                        outline: 1px solid var(--bug-dev); outline-offset: -1px; }
.wkgrid .wk-recovered { background: transparent; border-color: var(--bug-met); }
/* A week she lost is a gap in the ground with the two broken ends showing.
   It used to be a filled red cell, which is the mistake the road made before it
   was fixed: colouring a missed week in makes it the most present thing on the
   strip, and a decorated miss is a strange thing to hand someone. Nothing is
   there, and the ends say where it stopped. */
.wkgrid .wk-missed    { background: transparent; position: relative; }
.wkgrid .wk-missed::before,
.wkgrid .wk-missed::after {
  content: ""; position: absolute; top: 12%; bottom: 12%; width: 2px;
  background: var(--bug-nym);
}
.wkgrid .wk-missed::before { left: 0; }
.wkgrid .wk-missed::after  { right: 0; }
.wkgrid .wk-missed .wk-n { color: var(--bug-nym); }
.wkgrid .wk-complete .wk-n { color: rgba(28,25,23,.72); }
.wkgrid .wk-recovered .wk-n { color: var(--bug-met); }
.wkgrid .wk-now { border-color: var(--stage-ink); }

.wkkey { display: flex; flex-wrap: wrap; gap: 8px 20px; margin-top: 14px; }
.wkkey span {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75; font-weight: 700; font-size: 10px;
  letter-spacing: .12em; text-transform: uppercase; color: rgba(246,242,234,.6);
}
/* 11px rather than 9: two of the four states are drawn as an outline, and
   an outline needs a swatch big enough to have an inside. */
.wkkey i { width: 11px; height: 11px; border-radius: 2px; }
.wkkey .k-complete  { background: var(--bug-met); }
.wkkey .k-deferred  { background: rgba(246,242,234,.13);
                      outline: 1px solid var(--bug-dev); outline-offset: -1px; }
.wkkey .k-recovered { background: transparent; outline: 1px solid var(--bug-met);
                      outline-offset: -1px; }
/* The legend swatch carries the same form as the cell: broken ends, no fill. */
.wkkey .k-missed    { background: transparent; position: relative; }
.wkkey .k-missed::before,
.wkkey .k-missed::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 2px;
  background: var(--bug-nym);
}
.wkkey .k-missed::before { left: 0; }
.wkkey .k-missed::after  { right: 0; }

.recover { padding: 20px 0; border-top: 1px solid var(--k-line); }
.recover textarea { width: 100%; margin: 8px 0 12px; }

/* ── flashes ──────────────────────────────────────────────────────────────
   Confirmations and validation errors. A rule and a field shift, no shadow,
   and the hue is the one already carrying that meaning elsewhere. */
.flashes { width: var(--measure-in); margin: 18px auto -6px; display: grid; gap: 6px; }
.flash {
  margin: 0; padding: 12px 16px; border-left: 2px solid var(--k-line);
  background: var(--k-field-raised); font-size: 14.5px;
}
.flash-success { border-color: var(--a-met); }
.flash-error   { border-color: var(--a-risk); }
.flash-warning { border-color: var(--ph2); }

/* ── evidence cards and marked-helpful replies ────────────────────────────
   An evidence card is written by the system and says so, because a card that
   pretends a senior professional composed "I passed my gate" about themselves
   reads as false the first time somebody notices. */
.p-evidence { border-left: 2px solid var(--ph2); padding-left: 16px; }
.p-evidence .pbody { font-size: 1.02rem; }
.p-evidence .psys {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75; font-weight: 700; font-size: 10px;
  letter-spacing: .14em; text-transform: uppercase; color: var(--k-ink-muted);
}
.reply-helpful { border-left: 2px solid var(--a-met); padding-left: 14px; }
.racts { display: flex; gap: 16px; align-items: center; margin-top: 6px; }
.linkish {
  background: none; border: 0; padding: 0; cursor: pointer; font: inherit;
  font-size: 12.5px; color: var(--k-gold); text-decoration: underline;
}

/* ── calendar subscription ────────────────────────────────────────────── */
.subscribe {
  display: flex; gap: 24px; align-items: center; justify-content: space-between;
  flex-wrap: wrap; margin-top: 28px; padding-top: 20px;
  border-top: 1px solid var(--k-line);
}
.subscribe h3 { margin: 0 0 4px; font-size: 1rem; font-weight: 700; }
.subscribe .note { margin: 0; max-width: 52ch; }

/* ── the retry ────────────────────────────────────────────────────────────
   A student's alternative to a scored moment. Set beside the score, never
   inside it: the assessor's record stands as written, and this answers it. */
.retry {
  margin: 10px 0 0 0; padding: 12px 0 12px 16px;
  border-left: 2px solid var(--ph1);
}
.retry-k {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75; font-weight: 700; font-size: 10px;
  letter-spacing: .16em; text-transform: uppercase; color: var(--ph1);
}
.retry p { margin: 5px 0 4px; }
.retry-open { margin-top: 10px; }
.retry-open summary {
  cursor: pointer; font-size: 13px; color: var(--k-gold);
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
}
.retry-open form { padding: 12px 0 4px; }
.retry-open textarea { width: 100%; margin: 8px 0 10px; }

/* ── practice insights ────────────────────────────────────────────────────
   The confidence band says how much evidence a standing rests on, never how
   good the coach is. Its hues are the phase code reused, because "thin" and
   "firm" are positions on the same scale as the programme itself. */
.ins-c {
  font-family: "Instrument Sans", system-ui, sans-serif; font-size: 11px;
  letter-spacing: .1em; color: var(--k-ink-muted); margin-right: 6px;
}
.band {
  display: inline-block; font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75; font-weight: 700;
  font-size: 10px; letter-spacing: .14em; text-transform: uppercase;
  padding: 2px 0; margin-right: 8px;
}
.band-none    { color: var(--k-ink-muted); }
.band-thin    { color: var(--ph3); }
.band-growing { color: var(--ph2); }
.band-firm    { color: var(--a-met); }
.inscols {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 32px 40px;
}
.plain { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 12px; }
.ins-big {
  font-family: "Instrument Sans", system-ui, sans-serif; font-weight: 700;
  font-size: 2.8rem; line-height: 1; letter-spacing: -.035em; margin: 10px 0 4px;
  font-variant-numeric: tabular-nums; color: var(--a-met);
  font-variation-settings: "wdth" 75;
}
.ins-big .ro-of { color: var(--k-ink-muted); }

/* The personal-best line. Quiet on purpose: it appears on every visit, so it
   must never shout, and it is a fact about the student's own trajectory
   rather than an announcement. */
.wb-best {
  margin: 8px 0 0; font-size: .95rem; color: var(--ph2-stage);
  font-family: "Instrument Sans", system-ui, sans-serif;
  letter-spacing: .02em;
}

/* ========================================================== STANDING BUG
   One row per competency, answering both halves of the only question the
   rubric raises: where am I, and where do I have to be.

   The geometry is a flight instrument's, not a dashboard's. Of eight software
   products measured for this redesign (Linear, Stripe, Datadog, Sentry,
   Honeycomb, Observable, Plausible, Grafana) NOT ONE draws a target against a
   current value. Plausible's chart has no threshold marker, none of
   Observable Plot's eighteen example charts carry one, and Grafana draws
   thresholds as bands on a scale ring rather than as a mark. The device comes
   from real instrumentation: Garmin's altimeter bug, the G1000 engine gauge's
   plain white cruise tick, Raymarine's target arc.

   FIVE PARTS. A track, three drawn zones, a translucent fill, a full-strength
   index at the current value, and a bug at the standard.

     * Square ends. Rounded ends read as a progress pill, and a pill is the
       one shape the rules forbid outright.
     * The fill is the state colour at 35% alpha with the index at 100%. That
       is Grafana's measured bar-gauge construction, and it is the honest
       substitute for the glow a real instrument has: luminance difference,
       no bloom.
     * The bug sits ABOVE the track, not in it, so the fill can never cover
       the target. On the G1000 the Command Bars never override the aircraft
       symbol, for exactly this reason.
     * The bug does not move when the value passes it. You set the bug, the
       tape slides past, the bug stays. Moving the target to meet the value
       destroys the only reference the component has.
     * EBU Tech 3341 requires the target to hold its position whether the
       scale reads absolute or relative. If this ever renders as a percentage
       instead of a level, the bug does not move.

   COLOUR CARRIES THE SCORE, NEVER THE COMPETENCY. The row says which
   competency; eight hues would be a palette where three states are a code.
   Colour is never alone either: each state prints its numeral and a three
   letter code, so the stack survives greyscale, print and a reader who
   cannot separate the hues. Cyan marks the target, never magenta: in
   aviation magenta means "fly to", and on a web page it reads as a gaming
   overlay. */

.bug-stack { display: grid; gap: 2px; margin: 0; }

.bug-row {
  display: grid;
  grid-template-columns: minmax(120px, 210px) 1fr 54px 44px;
  align-items: center; gap: 16px; padding: 7px 0;
  border-bottom: 1px solid var(--k-line);
}
.bug-row:last-child { border-bottom: 0; }

.bug-name { font-weight: 600; font-size: 13.5px; line-height: 1.25; }
.bug-name .bug-c {
  display: block; font-size: 10px; font-weight: 700;
  font-variation-settings: "wdth" 75; letter-spacing: .16em;
  text-transform: uppercase; color: var(--k-ink-faint); margin-bottom: 2px;
}

/* the instrument ------------------------------------------------------- */
.bug-track {
  position: relative; height: 8px; background: var(--bug-track);
  margin: 7px 0;                      /* room for the bug to stand proud */
}
/* Three zones, boundaries drawn, because the scale is ordinal. A track two
   thirds full means Developing; it does not mean 2.0 out of 3. */
.bug-track::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(90deg, transparent calc(33.3333% - 1px), var(--bug-zone) calc(33.3333% - 1px),
                    var(--bug-zone) 33.3333%, transparent 33.3333%),
    linear-gradient(90deg, transparent calc(66.6667% - 1px), var(--bug-zone) calc(66.6667% - 1px),
                    var(--bug-zone) 66.6667%, transparent 66.6667%);
}
/* The surface, and it is the level. ------------------------------------
   The docstring on tape.py has always said "each level also has its own fill
   form", because colour alone at these luminances is not a safe carrier. It
   was not true: all three levels drew the same flat 35% fill and only the hue
   changed. Now the fill is the material, and it is the same three materials
   the Route puts underfoot:

     Meets Standard   made road. Poured, finished, continuous.
     Developing       laid stone. Built, and you can still see the courses.
     Not Yet Met      a dirt track. Something is there; nobody laid it.

   Read down the column the texture changes before the colour does, which is
   the whole point of giving a level a form. */
.bug-fill {
  position: absolute; top: 0; bottom: 0; left: 0;
  background: var(--bug-state); opacity: .35;
}
.s-met .bug-fill {                     /* poured: one continuous surface */
  opacity: .40;
}
/* THREE SURFACES, AND THE SCALE IS THE WHOLE ARGUMENT.
   Poured, laid, scuffed: the level reads without colour, which is the point.
   The courses were 5px on and 3px off, which across a 450px track draws
   fifty-six dashes and reads as a dotted rule or a loading state rather than
   as a surface. A course is long and its joint is thin; that is what makes it
   masonry rather than a dashed border. */
.s-developing .bug-fill {              /* laid: the courses still show */
  opacity: .44;
  background: repeating-linear-gradient(90deg,
    var(--bug-state) 0 26px, transparent 26px 29px);
}
.s-not-yet .bug-fill {                 /* a track: scuffed, not laid */
  opacity: .50;
  background: repeating-linear-gradient(90deg,
    var(--bug-state) 0 9px, transparent 9px 14px);
}
.bug-index {                           /* the current value, at full strength */
  position: absolute; top: -3px; bottom: -3px; width: 2px;
  background: var(--bug-state);
}
.bug-mark {                            /* the standard, outside the track */
  position: absolute; top: -7px; width: 0; height: 0; margin-left: -4px;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 5px solid var(--bug-target);
}
.bug-mark::after {                     /* and a hairline inside it */
  content: ""; position: absolute; left: -1px; top: 5px;
  width: 1px; height: 8px; background: var(--bug-target); opacity: .6;
}

/* readouts ------------------------------------------------------------- */
.bug-read { text-align: right; }
.bug-v {
  display: block; font-weight: 600; font-size: 16px;
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--bug-state); line-height: 1.1;
}
.bug-v.none {
  font-size: 10px; font-weight: 700; font-variation-settings: "wdth" 75;
  letter-spacing: .16em; text-transform: uppercase; color: var(--k-ink-faint);
}
.bug-t {
  display: block; font-size: 10px; font-weight: 700;
  font-variation-settings: "wdth" 75; letter-spacing: .16em;
  text-transform: uppercase; color: var(--k-ink-faint);
  font-variant-numeric: tabular-nums lining-nums;
}
.bug-code {
  font-size: 10px; font-weight: 700; font-variation-settings: "wdth" 75;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--bug-state); text-align: right;
  font-variant-numeric: tabular-nums lining-nums;
}

/* state ---------------------------------------------------------------- */
.bug-row.s-met        { --bug-state: var(--bug-met); }
.bug-row.s-developing { --bug-state: var(--bug-dev); }
.bug-row.s-not-yet    { --bug-state: var(--bug-nym); }
.bug-row.s-unobserved {
  --bug-state: var(--k-ink-faint);
}
.bug-row.s-unobserved .bug-fill,
.bug-row.s-unobserved .bug-index { display: none; }
/* Nobody has walked it. Drawn as unmade ground, the same dash the journey's
   spine uses ahead of her, rather than as an empty box: an empty box reads as
   a zero, and a competency nobody has observed yet is a scheduling fact about
   the programme, not a score of nothing. */
.bug-row.s-unobserved .bug-track {
  background: repeating-linear-gradient(90deg,
    var(--a-unmade) 0 3px, transparent 3px 11px);
}
.bug-row.s-unobserved .bug-name { color: var(--k-ink-muted); }
.bug-row.s-unobserved .bug-code { color: transparent; }

/* A score changes once a fortnight, so this is a transition, not a slew.
   Rolling drum digits would be theatre: the altimeter rolls only its fastest
   digits, and nothing here changes fast. The numeral never counts up, because
   a number counting up is briefly a false reading. */
.bug-fill, .bug-index { transition: left var(--mo-move, 240ms) var(--mo-ease, cubic-bezier(.4,0,.2,1)),
                                    width var(--mo-move, 240ms) var(--mo-ease, cubic-bezier(.4,0,.2,1)); }
@media (prefers-reduced-motion: reduce) {
  .bug-fill, .bug-index { transition-duration: 1ms; }
}

/* tones ---------------------------------------------------------------- */
:root {
  --bug-track:  #e1e5e3;
  --bug-zone:   rgba(35, 31, 32, .22);
  --bug-met:    #1f7c49;   /* 4.53:1 on the paper field */
  --bug-dev:    #8f630c;   /* 4.62:1 */
  --bug-nym:    #b02a1b;   /* 5.17:1 */
  --bug-target: #1c5f73;   /* cyan, darkened for paper: 5.58:1 */
}
.stage, html[data-theme="dark"] {
  --bug-track:  #2a2724;
  --bug-zone:   rgba(246, 242, 234, .26);
  --bug-met:    #4fd38a;   /*  9.17:1 on the stage */
  --bug-dev:    #ffc247;   /* 10.88:1 */
  --bug-nym:    #ff6b61;   /*  6.27:1, replacing pure red, which the FAA
                              itself lists as a pairing to avoid on black */
  --bug-target: #6fd3e8;   /* 10.13:1 */
}

.bug-legend {
  display: flex; gap: 18px; flex-wrap: wrap; margin-top: 14px;
  font-size: 10px; font-weight: 700; font-variation-settings: "wdth" 75;
  letter-spacing: .16em; text-transform: uppercase; color: var(--k-ink-faint);
}
.bug-legend span { display: inline-flex; align-items: center; gap: 7px; }
.bug-legend i { width: 16px; height: 8px; display: block; background: var(--bug-track); }
.bug-legend i.lg-f { background: var(--bug-met); opacity: .35; }
.bug-legend i.lg-t {
  width: 0; height: 0; background: none;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 5px solid var(--bug-target);
}

@media (max-width: 640px) {
  .bug-row { grid-template-columns: 1fr 54px 44px; gap: 6px 12px; }
  .bug-row .bug-track { grid-column: 1 / -1; }
}

/* The stack is its own band at full measure. A square radar sat beside the
   name happily; eight rows of instrument need the whole width, and the hero
   was the emptiest region on the screen. Measured before this change: eight
   of twenty-five horizontal bands on the Week Board carried under 1% ink,
   so the quiet was dead space rather than composition. */
/* --measure-in, not --measure: `.stage` already restores the reading column
   with its own `max(30px, calc(50vw - 560px))` padding, so 100% here is
   already the right width and subtracting the gutter again set the bug track
   thirty pixels inside the heading above it. */
.stage .bugs { width: var(--measure-in); margin: 0 auto;
                padding: clamp(18px, 3vw, 30px) 0 clamp(26px, 4vw, 44px); }
.stage .bug-stack { width: 100%; }

/* ========================================================= EVIDENCE TRACK
   Eight competency lanes across one recording.

   LANES, NOT HUES. Eight categories on one strip is past what colour can
   carry: Final Cut Pro, a mature tool, allows four marker classes. Hudl
   Sportscode gives each code button its own row, Gong draws one bar per
   participant, Audacity stacks named label tracks. So the lane says which
   competency and colour says only the score.

   CROWDING THINS THE DRAWING, NEVER THE MARKS. Dartfish marks its timeline
   data-overcrowded and hides the glyph of any mark that is not hovered or
   selected, leaving the hit area in place. Better than a tooltip, which
   covers the neighbours it is explaining. Here .is-near does the same: the
   numeral drops out, the button stays 24px and stays clickable. */

.ev-head { padding-bottom: clamp(24px, 4vw, 40px); }
.ev-head-in { width: var(--measure-in); margin: 0 auto; }
.ev-rule {
  margin: 18px 0 0; max-width: 62ch; font-size: 14px; line-height: 1.55;
  padding-left: 14px; border-left: 2px solid var(--bug-target);
  color: var(--k-ink-muted);
}

.ev-track { width: 100%; }

/* the scale ------------------------------------------------------------ */
.ev-scale {
  position: relative; height: 18px; margin-left: 210px;
  border-bottom: 1px solid var(--k-line);
}
.ev-tick {
  position: absolute; top: 0; transform: translateX(-50%);
  font-size: 10px; font-weight: 700; font-variation-settings: "wdth" 75;
  letter-spacing: .12em; color: var(--k-ink-faint);
  font-variant-numeric: tabular-nums lining-nums;
}
.ev-tick i { display: block; width: 1px; height: 5px; margin: 0 auto 2px;
             background: var(--k-line); }

/* lanes ---------------------------------------------------------------- */
.ev-lane {
  display: grid; grid-template-columns: 210px 1fr; align-items: center;
  column-gap: 0; padding: 5px 0;
  border-bottom: 1px solid var(--k-line);
}
.ev-lane:last-child { border-bottom: 0; }
.ev-lane-n { font-size: 13px; font-weight: 600; line-height: 1.25; padding-right: 16px; }
.ev-lane-n .ev-c {
  display: inline-block; min-width: 22px;
  font-size: 10px; font-weight: 700; font-variation-settings: "wdth" 75;
  letter-spacing: .14em; color: var(--k-ink-faint);
}
.ev-lane-s {
  grid-column: 2; font-size: 11px; color: var(--k-ink-faint);
  margin-top: 3px;
}
.ev-lane.is-empty .ev-lane-n { color: var(--k-ink-muted); }

/* the bed, and the marks on it ----------------------------------------- */
.ev-bed {
  position: relative; height: 18px; background: var(--bug-track);
}
.ev-lane.is-empty .ev-bed { background: none; border-top: 1px dashed var(--k-line); height: 1px; }

.ev-mark {
  position: absolute; top: 50%; transform: translate(-50%, -50%);
  width: 24px; height: 24px;          /* hit area, four times the glyph */
  display: grid; place-items: center;
  padding: 0; border: 0; background: none; cursor: pointer;
}
.ev-mark .ev-n {
  display: grid; place-items: center;
  width: 16px; height: 16px; border-radius: var(--r);
  font-size: 10px; font-weight: 700;
  font-variant-numeric: tabular-nums lining-nums;
  background: var(--ev-state); color: var(--k-field);
}
.ev-mark.m-met        { --ev-state: var(--bug-met); }
.ev-mark.m-developing { --ev-state: var(--bug-dev); }
.ev-mark.m-not-yet    { --ev-state: var(--bug-nym); }

/* Crowding: the glyph thins, the button does not. */
.ev-mark.is-near .ev-n { width: 6px; height: 16px; font-size: 0; }
.ev-mark.is-near:hover .ev-n, .ev-mark.is-near:focus-visible .ev-n {
  width: 16px; font-size: 10px;
}
.ev-mark:focus-visible { outline: 2px solid var(--k-ink); outline-offset: 1px; }
.ev-mark:hover .ev-n { outline: 2px solid var(--k-ink); outline-offset: 1px; }

/* notes ---------------------------------------------------------------- */
.ev-missing { max-width: 72ch; margin-top: 18px; }
.ev-notes { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.ev-note {
  padding: 12px 0 13px; border-bottom: 1px solid var(--k-line);
  border-left: 2px solid var(--ev-note-state, transparent); padding-left: 14px;
}
.ev-note.n-met        { --ev-note-state: var(--bug-met); }
.ev-note.n-developing { --ev-note-state: var(--bug-dev); }
.ev-note.n-not-yet    { --ev-note-state: var(--bug-nym); }
.ev-note:target { background: var(--k-field-raised); }

.ev-note-h { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; }
.ev-tc {
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-variant-numeric: tabular-nums lining-nums; font-size: 14px;
  min-width: 48px;
}
/* A timecode is a LINK only for someone who may open the recording. For the
   student it is set as text, and that single difference is the whole screen:
   a link to a file they may not open is a button that answers 403. */
.ev-tc.is-text { color: var(--k-ink); text-decoration: none; cursor: default; }
.ev-tc.is-none { color: var(--k-ink-faint); font-weight: 400; }
.ev-note-c {
  font-size: 10px; font-weight: 700; font-variation-settings: "wdth" 75;
  letter-spacing: .16em; text-transform: uppercase; color: var(--k-ink-faint);
}
.ev-note-l { font-size: 12px; font-weight: 600; margin-left: auto; }
.ev-note-j { margin: 7px 0 0; max-width: 72ch; line-height: 1.55; }
.ev-note-b { margin: 5px 0 0; font-size: 11px; color: var(--k-ink-faint); }
.ev-unplaced { max-width: 72ch; margin-top: 20px; }

@media (max-width: 720px) {
  .ev-scale { margin-left: 0; }
  .ev-lane { grid-template-columns: 1fr; }
  .ev-lane-s, .ev-bed { grid-column: 1; }
  .ev-bed { margin-top: 5px; }
}

/* It prints, because a student brings this to their mentor session. */
@media print {
  .top, .ev-rule { display: none; }
  .stage, .ev-head { background: none; color: #000; }
  .ev-note { break-inside: avoid; }
  .ev-track { break-inside: avoid; }
}

/* The evidence track on the review screen. Same component, one inversion:
   here a mark seeks, because the reviewer may open the file. */
.ev-review { margin: 26px 0 30px; }
.ev-review .ev-mark { cursor: pointer; }

/* Printed keys. A shortcut nobody knows about is not a feature, which is why
   Veo underlines the accelerator inside every tag chip. */
.keyhint {
  margin: 14px 0 0; font-size: 12px; line-height: 1.7; color: var(--k-ink-muted);
  max-width: 72ch;
}
kbd {
  display: inline-block; padding: 1px 5px; margin: 0 1px;
  border: 1px solid var(--k-line); border-radius: var(--r);
  background: var(--k-field-raised); color: var(--k-ink);
  font-family: inherit; font-size: 11px; font-weight: 700;
  font-variation-settings: "wdth" 75; letter-spacing: .06em;
}

/* ======================================================== THE WEEK STRIP
   Twenty-four weeks as one object, with the gates marked on it.

   One of only two places in this product where a tape is the honest form. A
   tape earns its place when the span is fixed, you stand at one point in it,
   and you read that point repeatedly: 24 weeks is all three. The percentage
   bar it replaces said the same thing worse, because 4% elapsed measures time
   passing rather than work done.

   Peloton draws its calendar as the chart for exactly this shape: a day is a
   filled disc, an outlined disc, or a check. The cell here carries the week's
   own state, which the continuity record already decides. */

.wb-of {
  font-size: .42em; font-weight: 400; font-variation-settings: "wdth" 100;
  letter-spacing: 0; margin-left: .35em; color: rgba(246,242,234,.58);
}

.wstrip {
  display: grid; grid-template-columns: repeat(24, 1fr);
  gap: 3px; margin: 20px 0 0; padding: 9px 0 0; list-style: none;
}
.wstrip .wk {
  position: relative; height: 10px; background: rgba(246,242,234,.13);
}
.wstrip .wk.s-complete, .wstrip .wk.s-recovered { background: var(--bug-met); }
.wstrip .wk.s-deferred { background: rgba(246,242,234,.13);
                 /* An outline rather than an inset box-shadow: identical at
                    zero blur, and it cannot be read as a halo by a scanner
                    or by a person. */
                 outline: 1px solid var(--bug-dev); outline-offset: -1px; }
.wstrip .wk.s-missed   { background: var(--bug-nym); }
.wstrip .wk.s-open     { background: rgba(246,242,234,.30); }
.wstrip .wk.s-future   { background: rgba(246,242,234,.09); }

/* Where you are. A 2px index standing proud, the same mark the standing bug
   uses, so one vocabulary covers both. */
.wstrip .wk.is-now::after {
  content: ""; position: absolute; left: 50%; top: -4px; bottom: -4px;
  width: 2px; margin-left: -1px; background: var(--stage-ink);
}
/* A gate is a fact about the programme, not about the student, so it sits
   above the strip rather than colouring a cell. */
.wstrip .wk-gate {
  position: absolute; left: 50%; top: -9px; width: 0; height: 0;
  margin-left: -3px;
  border-left: 3px solid transparent; border-right: 3px solid transparent;
  border-top: 4px solid var(--bug-target);
}
.wstrip-l {
  display: flex; justify-content: space-between; gap: 16px; margin-top: 8px;
  font-size: 10px; font-weight: 700; font-variation-settings: "wdth" 75;
  letter-spacing: .16em; text-transform: uppercase;
  color: rgba(246,242,234,.58);
}
.wstrip-l a { color: var(--stage-gold); text-decoration: none; }
.sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* What the week actually holds ---------------------------------------- */
.wb-week { list-style: none; margin: 26px 0 0; padding: 0; }
.ws {
  display: grid; grid-template-columns: 92px 1fr auto auto;
  align-items: baseline; gap: 16px; padding: 9px 0;
  border-bottom: 1px solid rgba(246,242,234,.16);
}
.ws:last-child { border-bottom: 0; }
.ws-when {
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-variant-numeric: tabular-nums lining-nums; font-size: 12px;
  letter-spacing: .08em; text-transform: uppercase;
  color: rgba(246,242,234,.58);
}
.ws-t { font-size: 14.5px; font-weight: 600; }
.ws-m { font-size: 11px; color: rgba(246,242,234,.58); }
.ws-s {
  font-size: 10px; font-weight: 700; font-variation-settings: "wdth" 75;
  letter-spacing: .16em; text-transform: uppercase;
  color: rgba(246,242,234,.58); min-width: 76px; text-align: right;
}
.ws.s-attended .ws-s { color: var(--bug-met); }
.ws.s-missed .ws-s   { color: var(--bug-nym); }
.ws.s-excused .ws-s  { color: var(--bug-dev); }

@media (max-width: 640px) {
  .ws { grid-template-columns: 1fr auto; row-gap: 3px; }
  .ws-m { grid-column: 1 / -1; }
}

/* ============================================================ CREDENTIALS
   The public credential page. A stranger opens this with no account, so it
   carries the holder's name, the credential, the date, the rule they met and
   the issuer, and nothing about anybody else. */
.cred { padding-bottom: clamp(26px, 4vw, 44px); }
.cred-in { width: var(--measure-in); margin: 0 auto; }
.cred-holder {
  margin: 10px 0 0; font-size: clamp(1.1rem, 2.4vw, 1.5rem); font-weight: 600;
  color: var(--stage-ink);
}
.cred-facts { display: flex; flex-wrap: wrap; gap: 36px; margin: 26px 0 0; }
.cred-facts dt {
  font-size: 10px; font-weight: 700; font-variation-settings: "wdth" 75;
  letter-spacing: .16em; text-transform: uppercase;
  color: rgba(246,242,234,.58);
}
.cred-facts dd {
  margin: 5px 0 0; font-size: 17px; font-weight: 600;
  font-variant-numeric: tabular-nums lining-nums;
}
.cred-facts a { color: var(--stage-gold); }
.cred-revoked {
  margin: 24px 0 0; max-width: 62ch; padding-left: 14px;
  border-left: 2px solid var(--bug-nym); color: rgba(246,242,234,.72);
}
.cred-criteria { max-width: 72ch; font-size: 16px; line-height: 1.6; margin: 0; }
.cred-disclosure {
  max-width: 72ch; margin: 28px 0 0; padding-left: 14px;
  border-left: 2px solid var(--k-line);
  font-size: 13.5px; line-height: 1.6; color: var(--k-ink-muted);
}
.cred-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.cred-item { padding: 18px 0; border-bottom: 1px solid var(--k-line); }
.cred-item:last-child { border-bottom: 0; }
.cred-item h3 { margin: 0 0 6px; font-size: 18px; }

/* Credentials on a profile. The link is the credential; the card is the
   advertisement, so this lists links. */
.awards { list-style: none; margin: 0 0 30px; padding: 0; display: grid; gap: 2px; }
.award {
  display: flex; align-items: baseline; justify-content: space-between; gap: 18px;
  padding: 12px 0; border-bottom: 1px solid var(--k-line);
}
.award:last-child { border-bottom: 0; }
.award > a { text-decoration: none; }
.aw-n { display: block; font-size: 15.5px; font-weight: 600; color: var(--k-ink); }
.aw-d {
  display: block; margin-top: 3px; font-size: 11px; font-weight: 700;
  font-variation-settings: "wdth" 75; letter-spacing: .16em;
  text-transform: uppercase; color: var(--k-ink-faint);
}
.aw-s { font-size: 12px; white-space: nowrap; }

/* ===========================================================================
   THE ROUTE

   The landing surface, and the one screen that is a place rather than a page.
   It locks the dark theme because its whole argument is light and dark:
   ignorance is a track you cannot see past, clarity is open ground with the
   light coming from ahead. The rest of the portal stays on the working field,
   because faculty sit in it for hours and that decision has not changed.

   The ground is here; the forest and the road are drawn in js/route.js.
   =========================================================================== */
#route-world{position:fixed;inset:0;width:100vw;height:100vh;z-index:2;pointer-events:none}
.route-grain{position:fixed;inset:0;z-index:12;pointer-events:none;opacity:.04;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='170' height='170'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3'/></filter><rect width='170' height='170' filter='url(%23n)'/></svg>")}
/* Black only, and flat: a lens, never a coloured bloom. */
.route-vig{position:fixed;inset:0;z-index:11;pointer-events:none;
  background:linear-gradient(90deg,rgba(4,7,5,.20),rgba(4,7,5,.06) 20%,
             rgba(4,7,5,0) 38%,rgba(4,7,5,0) 62%,rgba(4,7,5,.06) 80%,rgba(4,7,5,.20))}

.route{position:relative;z-index:1}
/* THE ROUTE RUNS DOWN THE PAGE, and the Journey's track climbs. That is two
   screens pointing opposite ways on purpose, which is worth stating because
   it looks like the defect it is not.
   The Journey is a picture of the whole programme and the thing it draws is a
   tree, so it grows upward. The Route is the operational screen: the question
   it answers every week is what is next, and on a screen with that job the
   natural scroll has to reveal what is next. Inverted, it did the opposite,
   and the motion a student makes without thinking walked her backwards.
   Tried climbing on 5 Oct and taken back the same day. route.js came out of
   it direction-agnostic, which is kept: it no longer assumes which way the
   weeks run, so the question can be reopened by this rule alone. */
.route .country{position:relative;padding:130px 0}
/* Closed and cold where she could not see, warmer and more open as the trees
   give way. Deep, not bright: an earlier pass lit Integration to a full orange
   and the type on it dropped to about three to one. A country changes
   temperature, not exposure. The light belongs to the road. */
/* The ink is a token because the ground stops being dark.

   The four countries used to run #040705 to #3d2a15: a near-black forest to a
   dark brown, with white type throughout. That is one half of the argument.
   Ignorance to clarity has to ARRIVE somewhere, and arriving in a slightly
   warmer dark says the walk was for nothing.

   So the treeline is where the light changes and the type changes with it.
   Weeks 1 to 16 are white on forest dark. Week 17 steps out into daylight and
   the ink turns over: dark type on open ground, which is the same sentence
   said in the material instead of in the copy. The step at the top of c3 is
   deliberate and is the moment the trees end. */
/* THE THREE KEYS ARE THE THREE PHASE COLOURS (5 Oct). Discovery, Design and
   Integration are named on this screen and on the Journey, and they were
   coloured independently: mint, gold and a warm orange here, teal, gold and
   coral there. Two screens naming the same three things in two sets of
   colours is the defect this portal keeps producing.
   Both now run the one ramp, green to gold to purple, which is the Auctus
   tree read from the ground up. k1 7.57:1 at worst, acc 7.29, k3 4.57, each
   measured against the darkest ground it lands on. */
.route{--r-ink:247,245,240;--r-acc:#dcc264;--r-bad:#ff6b61;--r-bad-hi:#ffa294;
  --r-k1:#6fe03c;--r-k3:#c07cf8;--r-card:rgba(8,13,10,.88)}
.route .c3,.route .c4{--r-ink:20,34,28;--r-acc:#6b4e08;--r-bad:#a31d12;
  --r-bad-hi:#7e170e;--r-k1:#14573a;--r-k3:#5f2a96;--r-card:rgba(248,252,249,.92)}

/* COOL, NOT EARTHY. Joseph, 5 Oct: the landscape read too earthy and he
   wants it closer to Avatar.
   It ran a brown-and-sand ramp: forest dark through olive and khaki to a
   sandy cream. That is a temperate wood in autumn, and every warm step of it
   fought the mark standing in its corner, which is Kureos green and Kureos
   purple.
   It runs blue-green now. The arc is untouched, because the arc is the
   argument: closed and dark where she could not see, opening to daylight once
   the trees give way, with the ink turning over at the treeline. Only the
   hue moved, from earth to deep water-green, and the clearing arrives cool
   rather than sandy.
   NO BIOLUMINESCENCE AND NOTHING GLOWS. The obvious way to make a wood feel
   like that film is to light the undergrowth, and the house rule on design
   tells covers exactly that. What carries it here is depth of hue and the
   value range, which is also what the film actually does in its daylight. */
/* Each end of each ramp is a measured value, and two of them are measured
   because the warm version was failing there and nobody had checked. On the
   old sandy ground the Route's own accents ran 4.13, 4.10 and 3.18 to one
   against the ground they sat on: the gold eyebrow at the top of Integration,
   the missed-week red, and the red on the last of Design. All three clear now.
   c1 joins c2 and c3 joins c4. c2 does NOT join c3, and that step is the
   treeline: it is the moment the trees end and the only hard edge in the
   four. */
.route .c1{background:linear-gradient(180deg,#05100f,#071614 30%,#0a1c1a 70%,#0e2422)}
.route .c2{background:linear-gradient(180deg,#0e2422,#102a26 28%,#12322c 66%,#133831)}
.route .c3{background:linear-gradient(180deg,#c2d3c8,#cedcd3 34%,#d9e6dc 74%,#e2ece5)}
.route .c4{background:linear-gradient(180deg,#e2ece5,#edf3ee 42%,#e8f0ea)}

.route .cname{position:relative;z-index:6;padding:0 44px;max-width:1500px;margin:0 auto 10px}
.route .cname b{font-size:11.5px;letter-spacing:.2em;text-transform:uppercase;font-weight:700;
  font-variation-settings:"wdth" 75}
.route .cname i{display:block;font-style:normal;font-size:12.5px;
  color:rgba(var(--r-ink),.94);margin-top:5px;letter-spacing:.04em}
.route .cname em{display:block;font-style:normal;font-size:12.5px;
  color:rgba(var(--r-ink),.76);margin-top:3px;letter-spacing:.04em;max-width:40ch}
.route .k1 b{color:var(--r-k1)}.route .k2 b{color:var(--r-acc)}.route .k3 b{color:var(--r-k3)}

.route .stops{position:relative;z-index:6;max-width:1500px;margin:0 auto;padding:0 44px}
/* The middle column is empty on purpose: it is the corridor the road runs
   down. With two columns the control points sat inside the paragraphs and the
   road drew a line straight through the words. */
.route .stop{display:grid;grid-template-columns:minmax(0,1fr) 460px minmax(0,1fr);
  min-height:300px;align-items:center}
.route .side{max-width:35ch}
.route .stop.l .side{grid-column:1}
.route .stop.r .side{grid-column:3;margin-left:auto}

.route .wkno{display:flex;align-items:baseline;gap:11px}
.route .wkno b{font-size:34px;font-weight:700;font-variation-settings:"wdth" 75;
  letter-spacing:-.03em;line-height:1;font-variant-numeric:tabular-nums;
  color:rgba(var(--r-ink),.54)}
.route .wkno span{font-size:11px;letter-spacing:.16em;text-transform:uppercase;
  font-weight:700;font-variation-settings:"wdth" 75;color:rgba(var(--r-ink),.82)}
.route .stop h2{font-size:31px;font-weight:600;letter-spacing:-.022em;margin:12px 0 0;
  line-height:1.2;text-wrap:balance;color:rgb(var(--r-ink))}
.route .stop p{font-size:15.5px;line-height:1.62;color:rgba(var(--r-ink),.82);margin:13px 0 0}
.route .stop .met{margin-top:15px;font-size:12px;letter-spacing:.12em;text-transform:uppercase;
  color:rgba(var(--r-ink),.64);font-weight:700;font-variation-settings:"wdth" 75}
.route .gate h2{font-size:40px}
.route .gate .wkno b,.route .gate .wkno span{color:var(--r-acc)}
.route .lost .wkno b,.route .lost .wkno span{color:var(--r-bad)}
.route .lost h2{color:var(--r-bad-hi)}
.route .ahead .side{opacity:1}

.route .you{position:relative;z-index:6;max-width:1500px;margin:0 auto;padding:70px 44px}
.route .you .in{display:grid;grid-template-columns:1.1fr 370px;gap:64px;align-items:start;
  border-top:1px solid rgba(var(--r-ink),.28);border-bottom:1px solid rgba(var(--r-ink),.28);
  padding:50px 0}
.route .you .hd{display:flex;align-items:baseline;gap:16px}
.route .you .hd b{font-size:112px;line-height:.78;font-weight:700;
  font-variation-settings:"wdth" 75;letter-spacing:-.04em;font-variant-numeric:tabular-nums;
  color:rgb(var(--r-ink))}
.route .you .hd span{font-size:21px;color:rgba(var(--r-ink),.70)}
/* The app's h2 is a section label: mono, uppercase, wide-tracked, with a rule
   drawn after it by ::after. On the Route an h2 is a sentence, so the label
   styling is undone rather than fought with !important. */
.route .you h2{font-family:"Instrument Sans",system-ui,sans-serif;
  font-size:30px;font-weight:600;letter-spacing:-.022em;margin:22px 0 0;
  line-height:1.24;max-width:24ch;color:rgb(var(--r-ink));
  text-transform:none;display:block}
.route .you h2::after{content:none;display:none}
.route .said{margin:32px 0 0;border-left:2px solid var(--r-acc);padding:2px 0 2px 22px;max-width:36ch}
.route .said q{display:block;font-size:22px;line-height:1.38;font-weight:500;quotes:none;
  color:rgb(var(--r-ink))}
.route .said cite{display:block;font-style:normal;font-size:13px;
  color:rgba(var(--r-ink),.74);margin-top:13px}
.route .trace{margin:26px 0 0;font-size:13.5px;line-height:1.7;max-width:40ch;
  color:rgba(var(--r-ink),.82)}
.route .trace a{color:rgb(var(--r-ink));text-decoration:none;
  border-bottom:1px solid rgba(var(--r-ink),.4)}
.route .trace a:hover{color:var(--r-acc);border-bottom-color:var(--r-acc)}
.route .trace span{display:block;color:rgba(var(--r-ink),.74);margin-top:5px}
.route .card{border:1px solid rgba(var(--r-ink),.24);padding:24px 26px;background:var(--r-card)}
.route .card h3{font-size:11px;letter-spacing:.16em;text-transform:uppercase;font-weight:700;
  font-variation-settings:"wdth" 75;color:rgba(var(--r-ink),.68)}
.route .card .s{padding:14px 0;border-bottom:1px solid rgba(var(--r-ink),.14)}
.route .card .s:last-child{border-bottom:0;padding-bottom:0}
.route .card .s u{text-decoration:none;display:block;font-size:10.5px;letter-spacing:.12em;
  text-transform:uppercase;color:rgba(var(--r-ink),.76);font-variant-numeric:tabular-nums}
.route .card .s b{display:block;font-size:15px;font-weight:500;margin-top:5px;
  line-height:1.38;color:rgb(var(--r-ink))}
.route .card .s em{display:block;font-style:normal;font-size:12.5px;
  color:rgba(var(--r-ink),.78);margin-top:4px}
.route .card .s .go{display:block;font-size:15px;font-weight:600;margin-top:5px;
  color:rgb(var(--r-ink));text-decoration:none;border-bottom:1px solid rgba(var(--r-ink),.4)}
.route .card .s .go:hover{border-bottom-color:var(--r-acc);color:var(--r-acc)}
.route .owe{color:var(--r-bad)}

/* The arrival. A statistic in the middle of a pale field was arriving
   nowhere, so the end of the road is a document: the thing she walks out
   holding, and then the part of it that is still hers to do. */
.route .fin{padding:120px 44px 170px;position:relative;z-index:6;
  max-width:760px;margin:0 auto}
.route .fin-k{font-size:11px;letter-spacing:.2em;text-transform:uppercase;font-weight:700;
  font-variation-settings:"wdth" 75;color:var(--r-acc)}
.route .fin-h{font-size:clamp(2.2rem,5vw,3.4rem);font-weight:700;
  font-variation-settings:"wdth" 75;text-transform:uppercase;letter-spacing:-.025em;
  line-height:.98;margin:10px 0 0;color:rgb(var(--r-ink))}
.route .fin-cert{margin:36px 0 0;padding:36px 40px;background:var(--r-card);
  border-top:3px solid var(--r-acc);border-bottom:1px solid rgba(var(--r-ink),.16)}
.route .fin-cert-m{font-size:10.5px;letter-spacing:.22em;text-transform:uppercase;
  font-weight:700;font-variation-settings:"wdth" 75;color:rgba(var(--r-ink),.62)}
.route .fin-cert b{display:block;font-size:clamp(1.6rem,3.4vw,2.3rem);font-weight:700;
  font-variation-settings:"wdth" 75;text-transform:uppercase;letter-spacing:-.02em;
  line-height:1;margin:10px 0 0;color:rgb(var(--r-ink))}
.route .fin-cert p{font-size:14.5px;line-height:1.6;color:rgba(var(--r-ink),.82);
  margin:12px 0 0;max-width:52ch}
.route .fin-cert dl{margin:26px 0 0;display:grid;grid-template-columns:1fr auto;
  border-top:1px solid rgba(var(--r-ink),.16)}
.route .fin-cert dt{padding:13px 0;font-size:13px;color:rgba(var(--r-ink),.82);
  border-bottom:1px solid rgba(var(--r-ink),.16)}
.route .fin-cert dd{margin:0;padding:13px 0;font-size:13px;text-align:right;
  color:rgba(var(--r-ink),.82);border-bottom:1px solid rgba(var(--r-ink),.16)}
.route .fin-cert dd u{text-decoration:none;font-weight:700;font-size:17px;
  font-variant-numeric:tabular-nums;color:rgb(var(--r-ink));margin-right:5px}
.route .fin-next{margin:34px 0 0;padding-left:20px;border-left:3px solid rgba(var(--r-ink),.24)}
.route .fin-next p{font-size:16px;line-height:1.62;margin:10px 0 0;max-width:58ch;
  color:rgba(var(--r-ink),.88)}
.route .fin-next b{font-weight:700}
.route .fin-go{display:flex;gap:30px;flex-wrap:wrap;margin-top:40px}
.route .fin-go a{font-size:13.5px;color:rgba(var(--r-ink),.88);text-decoration:none;
  border-bottom:1px solid rgba(var(--r-ink),.34);padding-bottom:3px}
.route .fin-go a:hover{color:var(--r-acc);border-bottom-color:var(--r-acc)}

@media (max-width:760px){
  /* No corridor at this width, so the road becomes a margin and runs up the
     left edge with everything else to the right of it. */
  .route .cname,.route .stops,.route .you,.route .fin{padding-left:16px;padding-right:16px}
  .route .cname{padding-left:86px}
  .route .country{padding:76px 0}
  .route .stop{grid-template-columns:1fr;min-height:0;padding:34px 0 34px 86px}
  .route .stop.l .side,.route .stop.r .side{grid-column:1;margin-left:0;max-width:none}
  .route .stop h2{font-size:25px}.route .gate h2{font-size:29px}
  .route .you{padding:40px 16px}
  .route .you .in{grid-template-columns:1fr;gap:30px;padding:32px 0;margin-left:86px}
  .route .you .hd b{font-size:74px}
  .route .said{max-width:none}
  .route .fin b{font-size:48px}
  .route-vig{display:none}
}

/* ===========================================================================
   THE ROUTE'S VOCABULARY, CARRIED INTO THE REST OF THE PORTAL

   The Route is the only screen that is a place. It stays dark and full-bleed
   because its whole argument is light and dark, and the rest of the portal
   stays on the working field, because faculty sit in it for hours and that
   decision has not changed.

   What crosses over is not the forest. It is the one idea underneath it: the
   ground is MADE where she has done the work and UNMADE where she has not. On
   the Route that is dirt, then laid stone, then poured road. Everywhere else it
   is the same distinction drawn with a line: what is behind her is continuous,
   what is ahead of her is not laid yet.

   Two tokens, one meaning each. A third would need a third thing to mean.
   =========================================================================== */
:root {
  --a-made:   var(--k-field-edge);   /* ground she has already crossed */
  --a-unmade: var(--k-line);         /* ground that is not laid yet */
}
:root[data-theme="dark"] {
  --a-made:   rgba(246, 242, 234, .34);
  --a-unmade: rgba(246, 242, 234, .16);
}

/* The journey's spine is the road seen end-on, so it takes the same rule.
   It was one flat line from week one to week twenty-four, which says the
   ground ahead of her is the same ground she has walked, and it is not. */
.track::before { background: var(--a-made); }
.track::after {
  content: ""; position: absolute; left: 78px; width: 2px;
  /* From the first checkpoint she has not reached to the end of the track. The
     dash is the surface: a way that exists on the timetable and has not been
     walked. */
  /* Unmade ground is ABOVE her now, not below. --ahead-from is the share
     of the track she has walked, so anchoring the dash to the top and
     holding it off the bottom by that share puts it exactly where the
     climb has not reached. */
  top: 10px; bottom: var(--ahead-from, 100%);
  background: repeating-linear-gradient(180deg,
    var(--a-unmade) 0 3px, transparent 3px 11px);
}
@media (max-width: 640px) { .track::after { left: 46px; } }
.ck-ahead .ck-dot { background: transparent; border-color: var(--a-unmade); }

/* What the school refuses to certify. Unmade ground: each of these is
   deliberately not built, and the rule beside it says so in the same language
   the journey's spine uses for the weeks she has not walked. */
.refusals { list-style: none; margin: 26px 0 0; padding: 0; display: grid; gap: 0; }
.refusal {
  padding: 16px 0 16px 20px;
  border-left: 2px solid transparent;
  border-image: repeating-linear-gradient(180deg,
    var(--a-unmade) 0 3px, transparent 3px 11px) 2;
}
.refusal h3 { margin: 0 0 5px; font-size: 16px; color: var(--k-ink-muted); }
.refusal p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--k-ink-muted);
             max-width: 68ch; }

/* ===========================================================================
   GROWTH

   The tree is drawn in js/tree.js from the record. This is the frame around it
   and the legend beside it, and the legend is load-bearing: a picture of growth
   with no statement of what grew is ornament.
   =========================================================================== */
/* ===========================================================================
   THE TREE SHE WILL BE, on the Journey.

   Gold, because this is the screen about finishing, and flat gold: one colour,
   no gradient on the type or the art, no bloom behind it. The ghost and the
   fill are the same colour at two strengths, which is the whole device.
   =========================================================================== */
.willbe {
  display: grid; grid-template-columns: minmax(0, 300px) 1fr; gap: 36px;
  align-items: center; margin: 0 0 40px; padding: 0 0 36px;
  border-bottom: 1px solid var(--k-line);
}
.willbe-cv { --tree-gold: #b8912c; width: 100%; aspect-ratio: 4 / 5; display: block; }
[data-theme="dark"] .willbe-cv { --tree-gold: #d4af37; }
.willbe-key b {
  display: block; font-size: 10.5px; font-weight: 700;
  font-variation-settings: "wdth" 75; letter-spacing: .16em;
  text-transform: uppercase; color: var(--k-ink-faint);
}
.willbe-key p { font-size: 15px; line-height: 1.6; color: var(--k-ink-muted);
                max-width: 48ch; margin: 10px 0 0; }
.willbe-key dl {
  margin: 20px 0 0; display: grid; grid-template-columns: 88px 1fr; gap: 0;
  border-top: 1px solid var(--k-line);
}
.willbe-key dt {
  padding: 9px 0; font-size: 10px; font-weight: 700;
  font-variation-settings: "wdth" 75; letter-spacing: .16em;
  text-transform: uppercase; color: var(--k-ink-faint);
  border-bottom: 1px solid var(--k-line);
}
.willbe-key dd {
  margin: 0; padding: 9px 0; font-size: 13.5px; line-height: 1.5;
  border-bottom: 1px solid var(--k-line);
}
@media (max-width: 760px) {
  .willbe { grid-template-columns: 1fr; gap: 22px; }
  .willbe-cv { max-width: 260px; margin: 0 auto; }
}

.grow {
  display: grid; grid-template-columns: minmax(0, 420px) 1fr; gap: 40px;
  align-items: center; padding: 10px 0 6px;
}
/* The panel takes the ground the page is on.

   It was a dark panel in both themes, on the argument that the tree is of the
   same world she walks through on the Route and that a picture is not a
   surface you read on. On the light working field that argument loses: the
   panel is a black rectangle in the middle of a pale page, and the eye reads
   it as a hole. js/tree.js carries a palette for each ground and repaints on
   the theme toggle. */
.grow-cv {
  width: 100%; aspect-ratio: 4 / 5; display: block;
  background: var(--k-field);
  border: 1px solid var(--k-line);
}
[data-theme="dark"] .grow-cv { background: #0c1a12; }
.grow-stage {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75; font-weight: 700;
  text-transform: uppercase; letter-spacing: -.01em;
  font-size: clamp(2rem, 4vw, 3rem); line-height: 1; margin: 6px 0 0;
}
.grow-blurb { font-size: 15.5px; line-height: 1.6; color: var(--k-ink-muted);
              max-width: 46ch; margin: 14px 0 0; }
.grow-parts {
  margin: 24px 0 0; display: grid; grid-template-columns: 92px 1fr;
  gap: 0; border-top: 1px solid var(--k-line);
}
.grow-parts dt {
  padding: 10px 0; font-size: 10.5px; font-weight: 700;
  font-variation-settings: "wdth" 75; letter-spacing: .16em;
  text-transform: uppercase; color: var(--k-ink-faint);
  border-bottom: 1px solid var(--k-line);
}
.grow-parts dd {
  margin: 0; padding: 10px 0; font-size: 14px; line-height: 1.5;
  border-bottom: 1px solid var(--k-line);
}
.grow-note { font-size: 13px; line-height: 1.6; color: var(--k-ink-muted);
             max-width: 52ch; margin: 18px 0 0; padding-left: 14px;
             border-left: 2px solid var(--k-line-gold); }
@media (max-width: 760px) {
  .grow { grid-template-columns: 1fr; gap: 24px; }
  .grow-cv { max-width: 360px; margin: 0 auto; }
}

/* Her growth, in the corner of the Route. Transparent, so the tree stands in
   the same forest the road runs through rather than in a panel laid over it. */
.route-tree {
  position: fixed; top: 76px; right: 22px; z-index: 13;
  width: 124px; text-decoration: none; text-align: center;
}
.route-tree canvas { display: block; width: 124px; height: 142px;
                     --tree-gold: #d4af37; }
/* Out of the trees the ground is daylight, so the gold goes deeper with it. */
.route-tree[data-ground="light"] canvas { --tree-gold: #8a6a12; }
/* A fixed thing in the corner needs the corner kept clear, or it sits on
   whatever scrolls under it. It was overlapping this week's card. */
@media (min-width: 981px) {
  .route .stops, .route .you, .route .fin { padding-right: 168px; }
}
.route-tree span {
  display: block; margin-top: 2px; font-size: 10px; font-weight: 700;
  font-variation-settings: "wdth" 75; letter-spacing: .18em;
  text-transform: uppercase; color: rgba(247, 245, 240, .70);
}
.route-tree[data-ground="light"] span { color: rgba(26, 22, 14, .80); }
.route-tree:hover span { color: #dcc264; }
.route-tree[data-ground="light"]:hover span { color: #7a5a0c; }
@media (max-width: 980px) { .route-tree { display: none; } }


/* ===========================================================================
   LEAF LITTER

   Drawn by js/litter.js into a fixed layer behind everything, in the gutters
   either side of the reading column and never across it. Behind the content
   and out of the pointer's way: it is weather on the page, not an element of
   it. Hidden where there is no gutter to put it in, and for anyone who has
   asked for less motion, because a surprise texture is still a surprise.
   =========================================================================== */
/* FIXED, NOT ABSOLUTE (6 Oct). This was a sheet as long as the document with
   leaves settled on it, so it scrolled with the page because that is where
   litter is. They fall now, which puts them in the air in front of the page
   rather than on it: the layer is the viewport, it does not scroll, and it is
   as tall as the frame instead of as tall as the record. */
.litter {
  position: fixed; top: 0; left: 0; width: 100%; height: 100%;
  z-index: 0; pointer-events: none;
}
/* THIS USED TO SET `position: relative` AND IT TOOK THE STICKY HEADER WITH IT.
   The rule exists only to lift the content above the litter layer, and
   `z-index` needs a positioned element, not specifically a relative one.
   `.top` declares `position: sticky` five hundred lines earlier, this came
   later and won, and the header silently stopped sticking on every page in
   the product. A stacking fix that cancels a layout one is the same defect
   class as a cream token on a paper field: both are later rules undoing
   earlier ones in a way nothing reports. */
body > main, body > header { position: relative; z-index: 1; }
body > .top { z-index: 40; }
@media (max-width: 1100px) { .litter { display: none; } }

/* ── where she is ─────────────────────────────────────────────────────────
   Fixed in the corner on every screen, after kureos.com's own ALT 000 / 060.
   Small, spaced, tabular, and quiet: it is a reading, not a headline, and the
   moment it competes with the page it has stopped being one.
   Hidden on narrow screens with the litter, because a phone has no gutter to
   put it in and over content it is an obstruction. */
.standing {
  position: fixed; left: 20px; bottom: 16px; z-index: 4;
  display: flex; align-items: baseline; gap: 5px;
  pointer-events: none; user-select: none;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75, "tnum" 1;
  font-variant-numeric: tabular-nums;
  font-size: 10px; letter-spacing: .18em; text-transform: uppercase;
  color: var(--k-ink-faint);
}
.standing-n { font-size: 13px; letter-spacing: .10em; color: var(--k-ink-muted); }
.standing-s { opacity: .5; }
@media (max-width: 1100px) { .standing { display: none; } }
/* The Route locks its own dark, and the corner has to be legible on it. */
[data-theme-lock="dark"] .standing { color: rgba(247, 245, 240, .38); }
[data-theme-lock="dark"] .standing-n { color: rgba(247, 245, 240, .62); }



/* ===========================================================================
   NO SECTION GLYPHS ON THE BAND.

   There were eleven, one per part of the school, drawn as flat SVG shapes and
   laid on the band at a tenth of their colour. Joseph rejected the set on
   4 October 2026, and he was right twice over.

   They were small flat vector pictograms, which is a form he had already
   rejected once in the film work, and they sat beside the growth tree, which
   is tapered organic wood with real botanical structure drawn by a renderer
   that measures and refits itself. A crude drawing next to a good one does
   not read as a family; it makes the good one look worse.

   Nothing replaces them. The band's job is the ground and the hero type, and
   the sections that need their own identity already have a better one: the
   gold tree on the Journey, the week grid on the Record, the standing track
   on the competency map. Those are drawn from the record. A glyph is not.

   If section identity is ever wanted again, it comes out of the same engine
   that draws the tree, not out of hand-authored paths.
   =========================================================================== */


/* ===========================================================================
   THE MENTOR'S DESK

   The half of the system that makes every leaf on every tree, and it had a
   queue and nothing else. Built on the same rules as the student's side:
   quantities against their own thresholds, no league table, and the one
   uncomfortable fact stated plainly rather than buried in a chart.
   =========================================================================== */
.blind {
  max-width: 1180px; margin: 0 auto 10px; padding: 22px 26px;
  background: var(--s-wash-b); border-left: 3px solid var(--s-clay);
}
/* Even enough, or spread: the same block, without the alarm. The border is
   what carried "this is a finding", and two of the three readings are not. */
.blind-even { border-left-color: var(--k-field-edge); }
.blind p { font-size: 17px; line-height: 1.55; margin: 9px 0 0; max-width: 60ch; }
.blind b { font-weight: 700; }

.cov { margin: 20px 0 0; border-top: 1px solid var(--k-line); }
.cov-row {
  display: grid; grid-template-columns: 34px minmax(0, 1fr) minmax(0, 2.2fr) 40px;
  gap: 16px; align-items: center; padding: 11px 0;
  border-bottom: 1px solid var(--k-line);
}
.cov-c { font-size: 11px; font-weight: 700; font-variation-settings: "wdth" 75;
         letter-spacing: .12em; color: var(--k-ink-faint); }
.cov-l { font-size: 14.5px; }
.cov-bar { height: 9px; background: var(--k-field-edge); position: relative; }
/* One scored observation is one unit of width, capped so a mentor with forty
   on one competency does not flatten the rest into nothing. */
.cov-bar i {
  position: absolute; inset: 0 auto 0 0; background: var(--s-moss);
  width: calc(min(var(--n) * 7%, 100%));
}
.cov-n { font-size: 15px; font-weight: 700; text-align: right;
         font-variant-numeric: tabular-nums; }

.mte {
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.5fr) auto auto;
  gap: 26px; align-items: start; padding: 24px 0;
  border-bottom: 1px solid var(--k-line);
}
.mte-quiet { border-left: 3px solid var(--s-clay); padding-left: 18px; }
.mte-who { display: flex; gap: 16px; align-items: center; }
.mte-nm { font-size: 18px; font-weight: 700; letter-spacing: -.012em;
          color: var(--k-ink); text-decoration: none; }
.mte-nm:hover { border-bottom: 2px solid var(--s-moss); }
.mte-m { font-size: 12.5px; color: var(--k-ink-faint); margin-top: 4px; }
.mte-say p { font-size: 16px; line-height: 1.5; margin: 0; max-width: 42ch; }
.mte-gap { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.mte-owe { display: flex; gap: 22px; }
.mte-owe b { display: block; font-size: 23px; font-weight: 700;
             font-variant-numeric: tabular-nums; line-height: 1; }
.mte-owe b.owe { color: var(--s-clay); }
.mte-owe span { display: block; font-size: 11px; font-weight: 700;
                font-variation-settings: "wdth" 75; letter-spacing: .13em;
                text-transform: uppercase; color: var(--k-ink-faint); margin-top: 6px; }
.mte-go { display: flex; flex-direction: column; gap: 8px; }
/* Looking, not filing: a hairline row of links under the two buttons. */
.mte-refs { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 4px;
            padding-top: 10px; border-top: 1px solid var(--k-field-edge); }
.mte-refs a { font-family: var(--k-font-mono); font-size: 10px;
              letter-spacing: .14em; text-transform: uppercase;
              color: var(--k-ink-faint); text-decoration: none;
              transition: color var(--k-dur-fast) var(--k-ease-out); }
.mte-refs a:hover { color: var(--k-gold); }
@media (max-width: 1000px) {
  .mte { grid-template-columns: 1fr; gap: 16px; }
  .mte-go { flex-direction: row; flex-wrap: wrap; align-items: center; }
  .mte-refs { margin-top: 0; padding-top: 0; border-top: 0; }
}

/* The desk's counts are routes, not readouts. */
.hero-stats > a { text-decoration: none; color: inherit; }
.hero-stats > a:hover .k { color: var(--stage-gold); }


/* ===========================================================================
   THE FILING SHEET

   One layout for all five filings: written feedback, mentor evaluation,
   practicum observation, hours, register. They feed the five ICF graduation
   gauges, and each of them was previously reachable only through Django
   admin, which is to say not reachable.

   A sheet and a margin. The sheet is where you write; the margin states what
   is already on the record, so nobody files the eleventh of ten or marks the
   same week twice. Both sit on the raised field rather than floating: this is
   paperwork, and paperwork has an edge.
   =========================================================================== */
.sheet {
  display: grid; grid-template-columns: minmax(0, 1fr) 260px;
  gap: clamp(24px, 3vw, 44px); align-items: start;
}
@media (max-width: 860px) { .sheet { grid-template-columns: minmax(0, 1fr); } }

.sheet-form { padding: clamp(22px, 3vw, 32px) clamp(22px, 3vw, 34px); }

/* A field group. The label is the mono rule, gold on focus, which is the one
   piece of feedback that tells you where you are in a long form. */
.sheet-form .fg { margin: 0 0 22px; }
.sheet-form .fg:last-of-type { margin-bottom: 0; }
.sheet-form .fg > label.k-label { display: block; margin: 0 0 7px;
  transition: color var(--k-dur-fast) var(--k-ease-out); }
.sheet-form .fg:focus-within > label.k-label { color: var(--k-gold); }
.sheet-form input[type=number], .sheet-form input[type=date],
.sheet-form input[type=datetime-local] {
  width: 100%; font-family: var(--k-font-body); font-size: 15px; color: var(--k-ink);
  background: transparent; border: 1px solid var(--k-line); border-radius: var(--r);
  padding: 11px 13px; outline: none;
  transition: border-color var(--k-dur-fast) var(--k-ease-out);
}
.sheet-form input[type=number]:focus, .sheet-form input[type=date]:focus,
.sheet-form input[type=datetime-local]:focus { border-color: var(--k-line-gold); }
/* A week or an hour count is a figure, so it is set as one. */
.sheet-form input[type=number] { font-variant-numeric: tabular-nums; max-width: 190px; }

.fg-help { margin: 7px 0 0; font-size: 13px; color: var(--k-ink-faint); max-width: 62ch; }
.fg-err { margin: 7px 0 0; font-size: 13px; color: var(--a-risk); max-width: 62ch; }
.fg-bad input, .fg-bad textarea, .fg-bad select { border-color: var(--a-risk); }

/* A checkbox is a sentence you agree with, so the label sits beside it and
   reads as prose rather than as another mono rule. */
.fg-check > label { display: flex; align-items: baseline; gap: 10px;
                    font-size: 14.5px; color: var(--k-ink-muted); cursor: pointer; }
.fg-check input { accent-color: var(--s-leaf); width: 15px; height: 15px; }

/* The one thing that stops the filing, stated at the top of the sheet rather
   than beside a field, because a cross-field rule does not belong to a field. */
.sheet-stop { border-left: 2px solid var(--a-risk); padding: 2px 0 2px 14px;
              margin: 0 0 24px; }
.sheet-stop p { margin: 0; font-size: 14.5px; color: var(--k-ink); }

.sheet-go { display: flex; gap: 12px; flex-wrap: wrap; align-items: center;
            margin-top: 28px; padding-top: 22px; border-top: 1px solid var(--k-line); }

/* The margin. Hairline rules, no card: it is a reference column, and giving it
   its own box would make it compete with the sheet it exists to support. */
.sheet-facts > .k-label { display: block; margin: 0 0 12px; }
.sheet-facts dl { margin: 0; }
/* A two-line label and a one-line figure align on their first line, not on
   their middles: the figure reads against the label it belongs to. */
.sheet-facts dl > div { display: flex; justify-content: space-between; gap: 14px;
                        align-items: baseline; padding: 9px 0;
                        border-top: 1px solid var(--k-field-edge); }
.sheet-facts dt { flex: 1 1 auto; line-height: 1.5; }
.sheet-facts dd { flex: 0 0 auto; white-space: nowrap; }
.sheet-facts dl > div:last-child { border-bottom: 1px solid var(--k-field-edge); }
.sheet-facts dt { font-family: var(--k-font-mono); font-size: 10px;
                  letter-spacing: .14em; text-transform: uppercase;
                  color: var(--k-ink-faint); }
.sheet-facts dd { margin: 0; font-size: 13.5px; color: var(--k-ink);
                  font-variant-numeric: tabular-nums; text-align: right; }

/* Two buttons in the queue's action cell, side by side on a wide row and
   stacked when the row runs out of width. */
.qgo { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }

/* A written feedback note on the session evidence screen. Numbered, because
   the Auctus Feedback Arc is a sequence of three to five observations and
   presenting them as a paragraph loses the thing that makes it a method. */
.fbn + .fbn { margin-top: 18px; }
.fbn-h { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
         padding-bottom: 10px; border-bottom: 1px solid var(--k-field-edge); }
.fbn-who { font-family: var(--k-font-mono); font-size: 10px; letter-spacing: .14em;
           text-transform: uppercase; color: var(--k-ink-muted); }
.fbn-obs { margin: 14px 0 0; padding-left: 26px; }
.fbn-obs li { margin: 0 0 10px; font-size: 15px; line-height: 1.55; color: var(--k-ink); }
.fbn-obs li::marker { font-family: var(--k-font-mono); font-size: 11px;
                      color: var(--k-ink-faint); }

/* A gauge with nothing to judge yet. Not a failure and not a zero: the same
   distinction the clearance page has always drawn between a phase nobody has
   reached and a phase somebody missed entirely. */
.gauge-idle { color: var(--k-ink-faint); }


/* ===========================================================================
   PRACTICE INSIGHTS

   The page is called the shape of your record, and it used to describe the
   shape in sentences: three blocks of prose, a bordered table where every
   reading was a word, and a three-up of two lists and a percentage presented
   as equals.

   One device now carries it. Eight bars, width by observations against the
   student's own deepest competency, so the shape is visible rather than
   stated. Fixed maxima were tried and rejected: a record of two and three
   observations draws two nearly empty bars, and the shape disappears exactly
   when reading it matters most.
   =========================================================================== */
.ins-lead {
  display: grid; grid-template-columns: minmax(0, 210px) minmax(0, 1fr);
  gap: clamp(20px, 3vw, 44px); align-items: start;
}
@media (max-width: 720px) { .ins-lead { grid-template-columns: 1fr; } }
/* .ro-n AND .ro-of ARE STAGE TYPE. They are cream, because the Journey band
   they were written for is dark, and `--stage-ink` resolves to cream wherever
   it is read. Borrowed onto this page's near-white field they rendered the
   lead figure invisible: present in the DOM, 54px tall, and the same colour
   as the paper. Re-stated here rather than redefined globally, which would
   take the Journey's band with it. */
.ins-lead-n .ro-n { color: var(--k-ink); }
.ins-lead-n .ro-of { color: var(--k-ink-faint); }
.ins-lead-n .k-label { display: block; margin-top: 8px; }
.ins-lead-p { margin: 0; font-size: clamp(16px, 1.5vw, 18px); line-height: 1.6;
              color: var(--k-ink); max-width: 62ch; }

/* one row per competency: code, name, bar, count, assessor dots, standing, trend */
.shape { margin-top: 24px; }
.shape-row {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr) minmax(90px, 2.1fr) 28px 42px 128px 54px;
  gap: 0 14px; align-items: center; padding: 11px 0;
  border-top: 1px solid var(--k-field-edge);
}
.shape-row:last-child { border-bottom: 1px solid var(--k-field-edge); }
.shape-c { font-family: var(--k-font-mono); font-size: 10px; letter-spacing: .1em;
           color: var(--k-ink-faint); }
.shape-l { font-size: 14.5px; color: var(--k-ink); }
.shape-bar { position: relative; height: 10px; border-radius: 2px;
             background: var(--k-field-edge); overflow: hidden; }
.shape-bar > i { position: absolute; inset: 0 auto 0 0; width: var(--w);
                 background: var(--s-leaf); border-radius: 2px; }
/* NO TEXTURE ON THESE BARS, deliberately, and the standing bug next door is
   not an inconsistency.
   There the surface carries the LEVEL, which nothing else on the row draws.
   Here the band (thin, building, well evidenced) is a function of the
   observation count and the assessor count, and the bar length and the dots
   draw both of those already. A third encoding of a value the reader can
   derive from two others is noise, and at this scale thin and building were
   two dashed bars a reader had to compare rather than read. */
.shape-n { font-family: var(--k-font-display); font-weight: 700;
           font-variation-settings: "wdth" 75; font-variant-numeric: tabular-nums;
           font-size: 15px; text-align: right; color: var(--k-ink); }
.shape-a { display: flex; gap: 3px; }
.shape-a > i { width: 6px; height: 6px; border-radius: 50%;
               background: var(--k-ink-faint); }
.shape-t { font-family: var(--k-font-mono); font-size: 10px; letter-spacing: .12em;
           text-transform: uppercase; color: var(--k-ink-faint); text-align: right; }
@media (max-width: 860px) {
  .shape-row { grid-template-columns: 26px minmax(0, 1fr) 28px 42px; gap: 4px 12px; }
  .shape-bar { grid-column: 2 / -1; }
  .shape-s, .shape-t { grid-column: 2 / -1; text-align: left; }
}

/* where to aim next: a numbered list, because it is an order of preference */
.aim { list-style: none; counter-reset: aim; margin: 22px 0 0; padding: 0; }
.aim li { counter-increment: aim; display: grid;
          grid-template-columns: 34px 26px minmax(0, 1fr) auto; gap: 14px;
          align-items: baseline; padding: 13px 0;
          border-top: 1px solid var(--k-field-edge); }
.aim li:last-child { border-bottom: 1px solid var(--k-field-edge); }
.aim li::before {
  content: counter(aim); font-family: var(--k-font-display); font-weight: 700;
  font-variation-settings: "wdth" 75; font-variant-numeric: tabular-nums;
  font-size: 20px; color: var(--k-gold);
}
.aim-c { font-family: var(--k-font-mono); font-size: 10px; letter-spacing: .1em;
         color: var(--k-ink-faint); }
.aim-l { font-size: 16px; color: var(--k-ink); }
.aim-s { font-family: var(--k-font-mono); font-size: 10px; letter-spacing: .12em;
         text-transform: uppercase; color: var(--k-ink-faint); white-space: nowrap; }
@media (max-width: 680px) {
  .aim li { grid-template-columns: 34px minmax(0, 1fr); }
  .aim-c { display: none; }
  .aim-s { grid-column: 2; white-space: normal; }
}

/* two, not three. The old triplet put two lists and a percentage side by side
   as equals, which is the three-up card pattern this stylesheet names
   elsewhere as the marker of generated design. */
.inspair { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
           gap: clamp(26px, 4vw, 56px); align-items: start; }
@media (max-width: 760px) { .inspair { grid-template-columns: 1fr; } }


/* ===========================================================================
   THE COHORT

   One row per enrolment, built on the mentor desk's grid because it answers
   the same question one level up: who needs the next hour. It replaced six
   cards followed by a table of the same six students, where the only thing
   the table added was a count of outstanding checks with no indication of
   what they were.
   =========================================================================== */
.coh {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr) minmax(0, 1.5fr) auto;
  gap: 26px; align-items: start; padding: 24px 0;
  border-bottom: 1px solid var(--k-line);
}
.coh-done { opacity: .62; }
.coh-who { display: flex; gap: 16px; align-items: center; }
.coh-nm { font-size: 17px; font-weight: 600; color: var(--k-ink);
          text-decoration: none; }
.coh-nm:hover { color: var(--k-gold); }
.coh-m { font-size: 12.5px; color: var(--k-ink-faint); margin-top: 2px; }
.coh-m b { color: var(--k-ink-muted); font-variant-numeric: tabular-nums; }

.coh-where { display: flex; flex-direction: column; gap: 7px; }
.coh-wk { font-family: var(--k-font-display); font-weight: 700;
          font-variation-settings: "wdth" 75; font-variant-numeric: tabular-nums;
          font-size: 19px; color: var(--k-ink); line-height: 1; }
.coh-of { font-size: .62em; font-weight: 600; color: var(--k-ink-faint); }

/* The checks, named. "4 items" is not a finding, it is a promise of one, and
   a programme director reads these to decide who to call. */
.coh-out > .k-label { display: block; margin-bottom: 7px; }
.coh-out ul { list-style: none; margin: 0; padding: 0; }
.coh-out li { font-size: 13px; line-height: 1.5; color: var(--k-ink-muted);
              padding-left: 13px; position: relative; }
.coh-out li::before { content: ""; position: absolute; left: 0; top: .62em;
                      width: 5px; height: 1px; background: var(--a-risk); }
.coh-clear { font-size: 13px; color: var(--s-leaf); }
.coh-out > .k-label.bad { color: var(--a-risk); }

.coh-go { display: flex; flex-direction: column; gap: 10px; align-items: stretch; }
@media (max-width: 1080px) {
  .coh { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .coh-out { grid-column: 1 / -1; }
  .coh-go { grid-column: 1 / -1; flex-direction: row; align-items: center; }
}
@media (max-width: 620px) {
  .coh { grid-template-columns: 1fr; gap: 16px; }
}

/* ── the summit ───────────────────────────────────────────────────────────
   The track climbs now, so this stands at the top of it: the thing the whole
   programme is toward. Two states, and only one of them is reachable by
   waiting. Unreached it is drawn in the same ghost the unmade ground uses, so
   it reads as somewhere she has not been rather than as a prize on display.
   Reached, it resolves: the band goes to sky and the tree takes its colours. */
.summit {
  display: grid; grid-template-columns: 96px 1fr; gap: 0 22px;
  align-items: center; margin: 0 0 6px; padding: 22px 24px;
  border: 1px solid var(--k-field-edge); border-radius: 2px;
  background: var(--k-field-raised);
}
.summit-tree {
  width: 96px; height: auto; display: block;
  /* Ghosted to the ink, not merely faded: a washed-out colour tree reads as a
     rendering fault, a silhouette reads as a thing not yet arrived at. */
  filter: grayscale(1) opacity(.17);
}
.summit-eyebrow {
  display: block; font-family: "Instrument Sans", system-ui, sans-serif;
  font-variation-settings: "wdth" 75; font-weight: 700;
  font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--k-ink-faint); margin-bottom: 6px;
}
.summit-say b {
  display: block; font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-size: 1.14rem; letter-spacing: -.015em;
  color: var(--k-ink-muted); margin-bottom: 4px;
}
.summit-say p {
  margin: 0; font-size: .92rem; line-height: 1.6;
  color: var(--k-ink-muted); max-width: 60ch;
}

/* ARRIVED, and it has to read as an arrival.
   Joseph, 5 Oct: at the end something has to have happened when the student
   reaches her goal. What was here was the same card with a darker fill and a
   tree a hundred pixels wide: a state change, not an event.
   The band is the top of the climb, so it goes to open sky; her tree stands
   in it at the size of the thing it is; and the line is set the way the
   house sets a headline, 700 at 75% width in capitals. Nothing on it lights
   up or catches a highlight: the size and the ground do the work. */
.summit-reached {
  grid-template-columns: 236px 1fr; gap: 0 34px;
  border-color: transparent; background: var(--stage);
  padding: 40px 34px; margin-bottom: 14px;
}
.summit-reached .summit-tree { filter: none; width: 236px; height: 252px; }
.summit-reached .summit-eyebrow { color: var(--stage-gold); margin-bottom: 10px; }
.summit-reached .summit-say b {
  color: var(--stage-ink); font-size: clamp(1.9rem, 4.4vw, 3.1rem);
  font-variation-settings: "wdth" 75; text-transform: uppercase;
  letter-spacing: -.012em; line-height: .96; margin-bottom: 12px;
  text-wrap: balance;
}
.summit-reached .summit-say p { color: var(--stage-ink); opacity: .78; }

/* What she actually finished with, stated as figures rather than described.
   Tabular, because three numbers in a row that do not line up read as
   decoration. */
.summit-count {
  display: flex; flex-wrap: wrap; gap: 0 38px;
  list-style: none; margin: 20px 0 0; padding: 18px 0 0;
  border-top: 1px solid rgba(255, 255, 255, .14);
}
.summit-count b {
  display: block; font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75, "tnum" 1;
  font-variant-numeric: tabular-nums;
  font-size: 1.62rem; line-height: 1.1; color: var(--stage-ink);
}
.summit-count span {
  display: block; margin-top: 3px;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 9.5px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--stage-ink); opacity: .62;
}

@media (max-width: 640px) {
  .summit, .summit-reached { grid-template-columns: 1fr; gap: 14px; justify-items: start; }
  .summit-tree { width: 76px; }
  .summit-reached { padding: 28px 20px; }
  .summit-reached .summit-tree { width: 164px; height: 176px; }
  .summit-count { gap: 0 24px; }
}

/* ── the climb ────────────────────────────────────────────────────────────
   The track ascends, so the ground it crosses ascends with it: soil at the
   foot where week one and the seed are, open air through the middle, and the
   first of the sky at the top where the summit stands.
   It stays a working page. Every assessment the student has, and every date
   she is late for, is read off this screen, so the field under it holds its
   contrast and the atmosphere is carried in tints a long way short of a dark
   ground. The dark is spent once, on the arrival, which is the only place it
   buys anything. */
/* The foot of the climb is the wood she started in, painted by climb.js.
   The track is padded clear of it so every checkpoint reads against open air:
   run up behind the rows it buried weeks one to nine under dark canopy. */
.climb { position: relative; overflow: hidden; padding-bottom: 332px; }
/* THE WOOD SHE CLIMBS THROUGH, painted by climb.js.
   What was here was one watermarked tree at the scale of the section, roots
   at the foot and crown at the head. It said the right thing and it was a
   tint: a single shape at seven percent behind a gradient. The climb is a
   place now, four depths of Auctus trees hazing back into the air, dense at
   the foot and open at the head. A watermark on top of a wood would be the
   same tree twice, so it is gone. */
.climb-field {
  position: absolute; inset: 0; width: 100%; height: 100%;
  display: block; pointer-events: none; z-index: 0;
}
/* Everything the student reads sits over it. EXCEPT THE FIELD, which is the
   it. Both selectors are one class, so they had equal specificity and this
   one, being later, pulled the backdrop out of its own absolute positioning
   and dropped it into the flow as a 558px block at the top of the section. */
.climb > *:not(.climb-field) { position: relative; z-index: 1; }
/* The soil line. Week one sits under it, which is where a seed goes. */
.climb::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: rgba(62, 78, 42, .22);
}


/* ===================================================== CERTIFICATE OF COMPLETION
   The only page in this product somebody prints and keeps, so it is set as a
   document rather than as a screen: one column, generous measure, a single
   flat green rule, and nothing that depends on a backlight to read.

   Light, and light unconditionally. Every other public page is locked dark;
   this one is locked light, because a certificate printed from a dark screen
   either wastes a cartridge or arrives as grey type on white with its contrast
   inverted. */
.cert-page {
  min-height: 100vh; background: #e9e6df;
  padding: clamp(24px, 5vh, 64px) 22px clamp(40px, 8vh, 90px);
}
.cert {
  max-width: 740px; margin: 0 auto; background: #fbfaf7;
  border: 1px solid #cfcabd; padding: clamp(30px, 5vw, 62px);
  color: #16180f;
}
.cert-void { border-color: #b2543f; }
.cert-revoked {
  margin: 0 0 30px; padding: 13px 16px; border-left: 3px solid #b2543f;
  background: #f6ece9; font-size: 14.5px; line-height: 1.55; color: #5e2a1f;
}

.cert-head {
  display: flex; align-items: center; gap: 18px;
  padding-bottom: 22px; border-bottom: 2px solid #55fb24;
}
.cert-mark { width: 54px; height: auto; display: block; }
.cert-issuer { display: flex; flex-direction: column; gap: 4px; }
.cert-issuer b {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 13px; letter-spacing: .16em; text-transform: uppercase;
}
.cert-issuer span {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 500; font-size: 11.5px; letter-spacing: .1em;
  text-transform: uppercase; color: #5c6152;
}

.cert-k {
  margin: 34px 0 14px;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 11px; letter-spacing: .2em; text-transform: uppercase;
  color: #3f6b2a;
}
/* The one hero line on the page: the holder's name, nothing else. */
.cert-name {
  margin: 0 0 24px;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: clamp(2rem, 1.2rem + 3.2vw, 3.1rem); line-height: .98;
  letter-spacing: -.02em; text-transform: uppercase; color: #16180f;
}
.cert-says, .cert-body {
  margin: 0 0 18px; font-family: var(--k-font-body);
  font-size: 15.5px; line-height: 1.62; color: #2b2f24;
}
/* Above the figures, never under them in small type. */
.cert-standing {
  margin: 26px 0; padding: 15px 18px; background: #f1efe7;
  border-left: 3px solid #3f6b2a;
  font-family: var(--k-font-body); font-size: 14.5px; line-height: 1.6;
  color: #16180f;
}

.cert-fig { width: 100%; border-collapse: collapse; margin: 28px 0 30px; }
.cert-fig th, .cert-fig td {
  padding: 12px 0; text-align: left; vertical-align: top;
  border-bottom: 1px solid #ddd8cb;
}
.cert-fig th {
  width: 46%; padding-right: 22px;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
  color: #5c6152;
}
.cert-fig td {
  font-family: var(--k-font-body); font-size: 15px; line-height: 1.5;
  font-variant-numeric: tabular-nums; color: #16180f;
}

.cert-foot { margin-top: 36px; padding-top: 24px; border-top: 2px solid #55fb24; }
.cert-sign, .cert-verify { display: flex; flex-direction: column; gap: 5px; }
.cert-verify { margin-top: 20px; }
.cert-sign span, .cert-verify span {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
  color: #5c6152;
}
.cert-verify code {
  font-family: var(--k-font-body); font-size: 13.5px; color: #16180f;
  word-break: break-all;
}
.cert-contact {
  margin: 22px 0 0; font-family: var(--k-font-body);
  font-size: 13px; line-height: 1.55; color: #5c6152;
}
.cert-contact a { color: #3f6b2a; }

/* Printed, this is the whole page. The portal's chrome is not part of the
   document and a graduate should not have to crop it off. */
@media print {
  .cert-page { background: #fff; padding: 0; min-height: 0; }
  .cert { border: 0; max-width: none; padding: 0; }
  .top, .nav, .signout, .lp-top, .pol-top { display: none !important; }
  .cert-standing { background: none; padding-left: 14px; }
  @page { margin: 18mm; }
}

/* The one way out of the clearing that is a document rather than a promise. */
.fin-cert-go {
  display: inline-block; margin-top: 20px; padding: 11px 20px;
  border: 1px solid var(--s-moss); color: var(--s-moss);
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
  text-decoration: none;
}
.fin-cert-go:hover { background: var(--s-moss); color: #fbfaf7; }

/* ========================================================== THE SESSION DECKS
   What goes on the wall behind the facilitator. Not a working surface and not
   a document: projected, from across a room, over video, for two hours. So it
   is dark, the measure is short, the clock is always in the same corner, and
   nothing is smaller than it would have to be at the back of the room. */
.dk { min-height: 100vh; background: #0f1a17; color: #f7f5f0; }
.dk-bar {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  padding: 14px 26px; border-bottom: 1px solid rgba(247, 245, 240, .16);
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase;
}
.dk-bar a { color: #93a09a; text-decoration: none; }
.dk-bar a:hover { color: #f7f5f0; }
.dk-ref { color: #f7f5f0; }
.dk-mod { color: #93a09a; }
.dk-view { margin-left: auto; padding: 7px 14px; border: 1px solid #55fb24; color: #55fb24 !important; }
.dk-view:hover { background: #55fb24; color: #0f1a17 !important; }
.dk-view.on { border-color: rgba(247, 245, 240, .3); color: #93a09a !important; }

.dk-rail { max-width: 980px; margin: 0 auto; padding: 30px 26px 90px; }
.dk-slide {
  border: 1px solid rgba(247, 245, 240, .16); padding: clamp(26px, 4vw, 52px);
  margin-bottom: 22px; min-height: 300px;
  display: flex; flex-direction: column; justify-content: center;
}
.dk-title, .dk-close { align-items: flex-start; }
.dk-k {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 11px; letter-spacing: .2em; text-transform: uppercase;
  color: #55fb24; margin-bottom: 16px;
}
.dk-slide h1 {
  margin: 0 0 14px;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: clamp(2rem, 1.2rem + 3vw, 3.2rem); line-height: .98;
  letter-spacing: -.025em; text-transform: uppercase; color: #f7f5f0;
}
.dk-slide h2 {
  margin: 0 0 16px;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: clamp(1.5rem, 1rem + 1.8vw, 2.2rem); line-height: 1.04;
  letter-spacing: -.02em; color: #f7f5f0;
}
.dk-sub { margin: 0; color: #93a09a; font-family: var(--k-font-body); font-size: 15px; }

/* The clock, always the same corner, because a facilitator checks it by
   muscle memory rather than by reading the slide. */
.dk-clock { display: flex; align-items: baseline; gap: 12px; margin-bottom: 14px; }
.dk-time {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 26px; letter-spacing: -.01em; color: #55fb24;
  font-variant-numeric: tabular-nums;
}
.dk-mins {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase; color: #93a09a;
}
.dk-desc { margin: 0 0 18px; color: #c7cec6; font-family: var(--k-font-body);
           font-size: 17px; line-height: 1.5; }
.dk-body, .dk-point {
  margin: 0 0 11px; color: #e6e3dc; font-family: var(--k-font-body);
  font-size: 16px; line-height: 1.55;
}
.dk-point { padding-left: 18px; border-left: 2px solid rgba(85, 251, 36, .5); }
.dk-do {
  margin: 14px 0; padding: 12px 16px; border: 1px solid rgba(85, 251, 36, .5);
  color: #f7f5f0; font-family: var(--k-font-body); font-size: 16px; line-height: 1.5;
}

/* The facilitator half. Only ever rendered in the facilitator view, and set
   apart from the slide so the eye never mistakes one for the other. */
.dk-prompt { margin-top: 24px; padding-top: 20px; border-top: 1px dashed rgba(247, 245, 240, .26); }
.dk-say {
  margin: 0 0 12px; padding-left: 16px; border-left: 3px solid #b357f6;
  color: #f7f5f0; font-family: var(--k-font-body); font-size: 16px;
  line-height: 1.6; font-style: italic;
}
.dk-note {
  margin: 0 0 10px; padding: 10px 14px; background: rgba(212, 175, 55, .1);
  border-left: 3px solid #d4af37; color: #e6e3dc;
  font-family: var(--k-font-body); font-size: 14.5px; line-height: 1.55;
}

.dk-list { width: 100%; border-collapse: collapse; margin: 0 0 34px; }
.dk-list th, .dk-list td {
  padding: 10px 12px 10px 0; text-align: left; border-bottom: 1px solid var(--k-field-edge);
}
.dk-list th {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 10px; letter-spacing: .14em; text-transform: uppercase;
}
.dk-list td { font-family: var(--k-font-body); font-size: 14.5px; }
.dk-list .num { text-align: right; font-variant-numeric: tabular-nums; }
.dk-list a { text-decoration: none; }
.dk-bare td { opacity: .72; }

/* ======================================================= THE TRANSCRIPT
   Forty minutes of a student's own coaching, read against what a model
   heard. A reading task first and a typing task second, so the measure is a
   reading measure and the controls sit at the foot, where somebody arrives
   after reading rather than at the head where they interrupt. */
.tx-doc {
  width: var(--measure-in); margin: 0 auto; max-width: 68ch;
  font-family: var(--k-font-body); font-size: 16px; line-height: 1.7;
  color: var(--k-ink);
}
.tx-doc p { margin: 0 0 1.1em; }
/* The machine's own version, kept beside the confirmed one. Set back, because
   it is the working and not the document. */
.tx-doc.is-machine { color: var(--k-ink-muted); font-size: 15px; }

.tx-form { width: var(--measure-in); margin: 0 auto; }
.tx-area {
  display: block; width: 100%; max-width: 68ch; margin: 8px 0 0;
  padding: 18px 20px; background: transparent;
  border: 1px solid var(--k-field-edge); border-radius: 2px;
  color: var(--k-ink); font-family: var(--k-font-body); font-size: 16px;
  line-height: 1.7; outline: none; resize: vertical;
}
.tx-area:focus { border-color: var(--k-ink-muted); }

.tx-actions {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  margin: 18px 0 0; max-width: 68ch;
}
.tx-actions .note { margin: 0; }

.tx-fail {
  padding-left: 14px; border-left: 2px solid var(--a-risk);
  color: var(--k-ink-muted);
}
.tx-foot { width: var(--measure-in); margin: 56px auto 0; max-width: 68ch; }

/* ========================================================= THE SKIP LINK
   2.4.1. Off screen until it takes focus, then the first thing on the page
   and unmissable. Not `display: none`, which takes it out of the tab order
   and makes it decoration. */
.skip-link {
  position: absolute; left: 12px; top: -64px; z-index: 9999;
  padding: 12px 18px;
  background: var(--k-field-raised, #0b0b0b);
  color: var(--k-ink, #f4f1ec);
  border: 1px solid var(--k-ink, #f4f1ec);
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 12px; letter-spacing: .14em; text-transform: uppercase;
  text-decoration: none;
  transition: top .12s ease;
}
.skip-link:focus { top: 12px; }

@media (prefers-reduced-motion: reduce) {
  .skip-link { transition: none; }
}

/* ------------------------------------------------- the unearned certificate
   The same document, before it is anybody's. Nothing here changes the
   issued state: a preview that renders differently is a preview that
   promises a document the issuer will not write.

   Three devices and no more. A stamp that says what this is. A met row
   that reads exactly as it will on the day. An open row that shows the
   distance, with the number that is moving set large and the one it is
   moving towards set quiet beside it. */
.cert-above, .cert-below {
  max-width: 740px; margin: 0 auto 18px; color: #5c6152;
  font-family: var(--k-font-body); font-size: 13.5px; line-height: 1.6;
}
.cert-below { margin: 20px auto 0; }
.cert-above b { color: #16180f; font-weight: 700; }
.cert-above a, .cert-below a { color: #2f5a3a; }

.cert-preview { position: relative; }
/* Flat, rotated, low-contrast ink. Not a watermark image and not a tint
   over the page: both read as a broken render rather than as a mark. */
.cert-preview .cert-stamp {
  position: absolute; top: clamp(90px, 16vw, 150px); right: -6px;
  margin: 0; transform: rotate(-7deg); transform-origin: 100% 50%;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: clamp(15px, 3.1vw, 25px); letter-spacing: .2em;
  text-transform: uppercase; color: #b2543f;
  border: 2px solid #b2543f; padding: 8px 16px; opacity: .72;
  pointer-events: none;
}
/* The name is the student's own and it is set at full weight even here,
   because the document is theirs to earn rather than a specimen. */
.cert-preview .cert-name { color: #16180f; }

.cert-fig tr.cf-open th { color: #8a8070; }
.cert-fig tr.cf-met th::after {
  content: ""; display: inline-block; width: 6px; height: 6px;
  margin-left: 8px; border-radius: 50%; background: #4a7646;
  vertical-align: .08em;
}
.cf-now {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 23px; line-height: 1; letter-spacing: -.01em;
  font-variant-numeric: tabular-nums; color: #16180f;
}
.cf-need { color: #8a8070; font-variant-numeric: tabular-nums; }
@media (max-width: 640px) {
  .cert-preview .cert-stamp { right: auto; left: 0; transform: rotate(-5deg);
    transform-origin: 0 50%; }
}

/* ------------------------------------------------------------- the phase
   THE PHASE OWNS THE ACCENT. Three phases over twenty-four weeks, three
   colours ruled off the tree on 8 October, and until now the portal used
   none of them: a Phase 3 student's screen was pixel-identical to a Phase
   1 student's, so half a year of movement was invisible in the one place
   she looks every day.

   The ruled hexes are the DARK-GROUND values and they are used exactly.
   On the light field each one is taken down until it clears 4:1 against
   #eff1f0, because an accent nobody can read is decoration.

   Only identity carries it: the active nav mark, the rule under a stage,
   the eyebrow over a title, the leading figure. Status keeps its own
   colours. Green still means met and red still means late, in every
   phase, because a student who learns that the accent means "where I am"
   must never find it also meaning "this is fine".

   Faculty have no phase, so they fall through to the gold and nothing
   about their screens changes. */
:root { --phase: var(--k-gold); --phase-on-dark: var(--stage-gold); }
:root[data-phase="1"] { --phase: #3d8323; --phase-on-dark: #74e242; }
:root[data-phase="2"] { --phase: #8f6f1d; --phase-on-dark: #b8902c; }
:root[data-phase="3"] { --phase: #8a5bd0; --phase-on-dark: #d09cfa; }

.nav a.on { color: var(--phase); border-bottom-color: var(--phase); }
.top .nav a.on { color: var(--phase-on-dark); border-bottom-color: var(--phase-on-dark); }
.stage-edge {
  background: linear-gradient(90deg, transparent,
              color-mix(in srgb, var(--phase-on-dark) 55%, transparent) 35%,
              color-mix(in srgb, var(--phase-on-dark) 55%, transparent) 65%,
              transparent);
}
.phead .k, .stage .k, .pre-k { color: var(--phase-on-dark); }
/* The first figure in a hero row is the one that answers the screen's
   question. The rest stay neutral; three coloured numerals in a row is a
   dashboard rather than a reading. */
.stage .hero-stats > div:first-child .v:not(.bad):not(.good) { color: var(--phase-on-dark); }
/* The phase, named, beside the week counter. Set in the phase's own
   accent so the hue the screens carry is labelled once. */
.standing-p {
  margin-left: 4px; padding-left: 9px; color: var(--phase);
  border-left: 1px solid currentColor;
}
.top .standing-p, [data-theme-lock="dark"] .standing-p,
:root[data-theme="dark"] .standing-p { color: var(--phase-on-dark); }

/* ------------------------------------------------- the three layouts
   Seventy screens carried one shape: dark band, light field, table. It
   was applied to a timetable, a complaints register, a GDPR disclosure
   and a certificate without asking what any of them is for.

   Three, chosen by what the page is:
     register  a dense list somebody scans          (.grid, .dk-list)
     statement one object, large, little else       (.stmt)
     surface   a form with its context beside it    (.surface)
   plus .nil, which is what any of the three says when it holds nothing. */

/* --- what a screen says when it is empty */
.nil {
  border-left: 2px solid var(--phase, var(--k-gold));
  padding: 4px 0 4px 20px; margin: 10px 0 4px; max-width: 62ch;
}
.nil-h {
  margin: 0 0 7px;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 15.5px; letter-spacing: -.01em; color: var(--k-ink);
}
.nil-b {
  margin: 0; font-family: var(--k-font-body); font-size: 14px;
  line-height: 1.65; color: var(--k-ink-muted);
}

/* --- statement: one object at the door's scale, and almost nothing else */
.stmt { max-width: 760px; margin: 0 auto; padding: 8px 0 4px; }
.stmt-n {
  font-family: var(--k-font-display); font-variation-settings: "wdth" 75;
  font-weight: 680; font-size: clamp(64px, 13vw, 132px); line-height: .88;
  letter-spacing: -.03em; font-variant-numeric: tabular-nums;
  color: var(--k-ink); margin: 0;
}
.stmt-of {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75; font-size: 11px;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--phase, var(--k-gold)); margin: 12px 0 0;
}
.stmt-b {
  margin: 16px 0 0; max-width: 56ch;
  font-family: var(--k-font-body); font-size: 16px; line-height: 1.6;
  color: var(--k-ink-muted);
}
/* In a stage band the statement is part of the head, so it is
   left on the head's own measure rather than centred in it. */
.stage .stmt { margin: 0; max-width: none; padding: 0; }
.stage .stmt-n { color: var(--stage-ink); }
.stage .stmt-of { color: var(--phase-on-dark, var(--stage-gold)); }

/* --- surface: the form, and the context it needs, side by side */
.surface {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 20rem);
  gap: clamp(28px, 5vw, 64px); align-items: start;
}
.surface-aside {
  border-left: 1px solid var(--k-line); padding-left: clamp(20px, 3vw, 32px);
}
.surface-aside h2 {
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--k-ink-faint); margin: 0 0 12px;
}
.surface-aside p {
  font-family: var(--k-font-body); font-size: 13.5px; line-height: 1.65;
  color: var(--k-ink-muted); margin: 0 0 14px;
}
@media (max-width: 860px) {
  .surface { grid-template-columns: minmax(0, 1fr); }
  .surface-aside { border-left: 0; padding-left: 0;
    border-top: 1px solid var(--k-line); padding-top: 24px; }
}
/* The share card, shown to the person who opened the link rather than
   only to the feed that unfurled it. */
.cred-card {
  display: block; width: 100%; height: auto; max-width: 620px;
  margin: 0 0 26px; border: 1px solid rgba(246, 242, 234, .14);
}

/* ---------------------------------------------------------- the moment
   Shown once, on the load after the ladder moves, and never again.
   A band rather than a modal: a dialogue box in front of somebody's work
   is a tax, and this is a mark, not a transaction.

   One entry, the whole element at once. Per-element letter reveals are
   the first thing that reads as machine-made and the standing rule
   forbids them. No glow, no gradient, no pill. */
.moment {
  display: flex; align-items: center; gap: clamp(18px, 3vw, 30px);
  padding: 18px clamp(20px, 4vw, 44px);
  background: var(--k-field-dark, #0a1812);
  border-bottom: 1px solid rgba(246, 242, 234, .14);
}
.moment-tree { flex: 0 0 auto; display: block; }
.moment-said { flex: 1 1 auto; min-width: 0; }
.moment-k {
  margin: 0 0 3px;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 10.5px; letter-spacing: .18em; text-transform: uppercase;
  color: var(--phase-on-dark, #74e242);
}
.moment-n {
  margin: 0;
  font-family: var(--k-font-display); font-variation-settings: "wdth" 75;
  font-weight: 680; font-size: clamp(28px, 5vw, 44px); line-height: 1;
  letter-spacing: -.025em; text-transform: uppercase; color: #fff;
}
.moment-b {
  margin: 7px 0 0; max-width: 54ch;
  font-family: var(--k-font-body); font-size: 14px; line-height: 1.55;
  color: rgba(246, 242, 234, .68);
}
.moment-go {
  flex: 0 0 auto;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
  color: #fff; text-decoration: none;
  border: 1px solid rgba(246, 242, 234, .3); padding: 10px 16px;
}
.moment-go:hover { border-color: rgba(246, 242, 234, .6); }
.k-motion .moment { animation: moment-in .62s cubic-bezier(.16, .84, .3, 1) both; }
@keyframes moment-in {
  from { opacity: 0; transform: translateY(-10px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { .moment { animation: none; } }
@media (max-width: 680px) {
  .moment { flex-wrap: wrap; }
  .moment-go { width: 100%; text-align: center; }
}

/* ------------------------------------------------------ the door's SSO
   Three equal buttons under a rule, quieter than the primary action. The
   password form is the Institute's own way in and these are the
   convenience; a social button given more weight than the credential the
   Institute issued has the hierarchy backwards. */
.door-or {
  display: flex; align-items: center; gap: 14px; margin: 24px 0 18px;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 700; font-variation-settings: "wdth" 75;
  font-size: 10px; letter-spacing: .18em; text-transform: uppercase;
  color: rgba(246, 242, 234, .42);
}
.door-or::before, .door-or::after {
  content: ""; flex: 1 1 auto; height: 1px;
  background: rgba(246, 242, 234, .16);
}
.door-sso { display: grid; gap: 9px; }
.door-sso button {
  width: 100%; padding: 13px 16px; cursor: pointer;
  background: transparent; border: 1px solid rgba(246, 242, 234, .26);
  color: #f6f2ea;
  font-family: "Instrument Sans", system-ui, sans-serif;
  font-weight: 600; font-size: 13.5px; letter-spacing: .01em;
}
.door-sso button:hover { border-color: rgba(246, 242, 234, .55); }
.door-sso button:focus-visible {
  outline: 2px solid #74e242; outline-offset: 2px;
}
.door-note {
  margin: 16px 0 0; font-family: var(--k-font-body); font-size: 12.5px;
  line-height: 1.6; color: rgba(246, 242, 234, .58);
}
