/* Hexagon Hexart.in — the official Hexagon brand system, applied.

   Every token below is quoted from https://brand.hexagon.com/, reviewed
   2026-08-18. The reasoning, the citations and the two points still awaiting
   Hexagon brand approval are in docs/brand/HEXAGON_BRAND_APPLICATION.md.

   Four portal rules shape most of what follows:
     - no gradients: "Gradients are no longer supported in the Hexagon design
       system. Use solid colour only."
     - the six-sided hexagon shape is not permitted in any creative asset.
     - websites set text in Arial. Hexagon Akkurat is licensed and is not
       bundled here.
     - type is 100% black in light mode and 100% white in dark mode; colour in
       type is occasional emphasis, never decoration.
   ===================================================================== */

:root{
  /* Primary palette */
  --sky:#01ADFF;        --sky-dark:#005198;
  --land:#83C410;       --land-dark:#28721E;
  --sea:#04D0E6;        --sea-dark:#106B73;
  /* Accent palette */
  --accent-sky:#99D6FF; --accent-land:#DFF73F; --accent-sea:#7DFFFC;
  /* Background and neutral palette */
  --white:#FFFFFF; --navy:#00284C;
  --grey-1:#E7E8E9; --grey-4:#B9B9BD; --grey-9:#71737B; --grey-11:#41454F;
  --black:#000000;
  /* Special use. Functional only: warnings, errors, critical data points.
     Never type, never a background, never decoration. */
  --alert:#FA4C40; --warn:#FFC505;

  /* Semantic roles */
  --surface:var(--white);
  --surface-alt:var(--grey-1);
  --surface-inverse:var(--navy);
  --text:var(--black);
  --text-support:var(--grey-9);           /* 4.73:1 on white */
  --text-inverse:var(--white);
  --text-support-inverse:var(--grey-4);   /* 7.56:1 on navy */
  /* Margin lines, divider lines and tile hairlines are all Cool Grey 4 C. */
  --line:var(--grey-4);
  --line-soft:var(--grey-1);
  /* Hyperlink standard. The portal offers Primary Sky for both modes, but
     #01ADFF scores 2.2:1 on white and cannot carry link text at AA, so light
     mode takes the portal's light-mode-only Primary Sky Dark (7.89:1) and dark
     mode takes Accent Sea (12.5:1). Both are portal values. */
  --link:var(--sky-dark);
  --link-inverse:var(--accent-sea);
  --focus:var(--sky-dark);
  --focus-inverse:var(--accent-sea);
  /* Status. Land Dark reads 5.97:1 on white, Sea Dark 6.24:1. */
  --pass:var(--land-dark);
  --fail:var(--grey-11);

  /* Typography by role, one size for each job, on every screen.

     Two things were wrong before this. The size below a section heading was
     not fixed by role: it came out 28 in one section, 21 in the next and 28
     again in the one after, so scrolling the page meant meeting the same kind
     of thing at a different size each time. And the headings were tracked at
     -0.033 to -0.039em, which are Hexagon's numbers for Akkurat. Arial has
     heavier stems, so the same tightening closes the letters and reads as
     weight rather than as refinement; frog.co, which is the reference the
     owner offered for a page that feels settled, sets letter-spacing to
     normal on every element on its home page. Ours is normal everywhere now.

     Sizes rise once at 768 and once at 1024. Nothing is fluid: a size that
     changes continuously with the window is a size nobody chose.

     Every size sits on one of the two 1.333 chains the brand mandates, run
     from 14 and from 16: 14, 18.7, 24.9, 33.2 and 16, 21.3, 28.4, 37.9.

     One scale, the same on every screen. It stepped up on desktop at first,
     to 38 / 28 / 18, and the owner read the result as oversized while calling
     the phone rendering right. The phone values are these, so desktop now
     renders what the phone renders and there is no breakpoint to hold in
     mind.

       display   33   one per page, the hero only
       section   25   every h2
       title     21   every h3, every card
       text      16   everything else
       small     14   captions and small print
       ui        16   navigation, buttons, controls                         */
  --t-small:14px; --t-body:16px; --t-title:21px;
  --t-section:25px; --t-display:33px; --t-ui:16px;

  /* Kept as aliases so the older rules keep working, each pointing at the
     role it actually meant. */
  --t-xs:var(--t-small); --t-sm:var(--t-ui); --t-lg:var(--t-title);
  --t-h3:var(--t-title); --t-h2:var(--t-section); --t-h1:var(--t-display);
  --t-lead:var(--t-body); --t-hero:var(--t-display);
  --font:Arial,"Helvetica Neue",Helvetica,sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,monospace;

  /* Spacing. The layout grid divides the shortest side by 22 for the margin;
     these steps keep every gap a multiple of that rhythm. */
  --sp1:4px;--sp2:8px;--sp3:16px;--sp4:24px;--sp5:32px;--sp6:40px;
  --sp7:56px;--sp8:72px;--sp9:96px;--sp10:120px;

  /* The radius circle guide rounds image shapes that do not bleed off the page
     or meet a margin line. Thick lines always have rounded ends. */
  --r-shape:24px; --r-ui:4px; --r-pill:999px;
  /* The margin, from the layout grid: the shortest side of the design surface
     divided by 22. The surface is 1440 x 900, so it is 900 / 22 = 41. Type,
     shapes and imagery align on the padding grid, half a margin further in
     again, so the vertical line and the column it governs never coincide.
     The width was used here once, giving 65 and a 98px column; that narrowed
     every band by 84px and lengthened every page, and it was the wrong side
     of the surface. */
  --margin:41px; --margin-half:21px; --column:62px;
  /* Line tiles hold a 1:20 thin-to-thick ratio. */
  --line-thick:20px; --line-thin:1px;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;font-family:var(--font);font-size:var(--t-body);line-height:1.5;
  color:var(--text);background:var(--surface)}

/* The vertical margin line. Two margin lines are mandatory in a Hexagon layout,
   one horizontal and one vertical; the horizontal one is the rule under the
   masthead. It is fixed so it runs the height of the viewport, and Cool Grey
   4 C is legible on both the white and the navy grounds it crosses. */
@media(min-width:1200px){
  body::before{content:"";position:fixed;top:0;bottom:0;left:var(--margin);width:1px;
    background:var(--line);z-index:1;pointer-events:none}
  body.is-home::before{top:77px;z-index:2}
}

h1,h2,h3,h4{font-weight:400;margin:0 0 var(--sp3)}

/* One space under a heading, everywhere. It was coming out 16, 24, 32 or 40
   depending on which element happened to follow: sometimes the heading set
   it, sometimes the grid or the rail below did, and the two never agreed. The
   heading owns the space beneath it and whatever follows contributes none. */
body.is-public main h2{margin-bottom:var(--sp4)}
body.is-public main h3{margin-bottom:var(--sp3)}
body.is-public main h2+*,body.is-public main h3+*{margin-top:0}
h1{font-size:var(--t-display);line-height:1.16;letter-spacing:normal}
h2{font-size:var(--t-section);line-height:1.18;letter-spacing:normal}
h3{font-size:var(--t-title);line-height:1.28;letter-spacing:normal}
h4{font-size:var(--t-lg);line-height:1.35}
p{margin:0 0 var(--sp3);max-width:68ch}
strong,b{font-weight:700}
a{color:var(--link)}
a:hover{text-decoration-thickness:2px}
:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.on-inverse :focus-visible,
.band-navy :focus-visible,.band-deep :focus-visible,.band-blue :focus-visible,
.primer-head :focus-visible,.site-footer :focus-visible{outline-color:var(--focus-inverse)}

.skip{position:absolute;left:-9999px}
.skip:focus{left:var(--sp3);top:var(--sp3);z-index:100;background:var(--white);
  padding:var(--sp2) var(--sp3);border:1px solid var(--line)}
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0}

.wrap{max-width:1440px;margin:0 auto;padding:0 var(--sp4);position:relative;z-index:2}
@media(min-width:1024px){.wrap{padding:0 var(--sp7)}}
@media(min-width:1200px){.wrap{padding:0 var(--column)}}
.wrap-reading{max-width:760px}

/* ---------------------------------------------------------------------------
   Masthead. The horizontal margin line sits under it.
   --------------------------------------------------------------------------- */
.site-header{border-bottom:1px solid var(--line);background:var(--white);
  position:sticky;top:0;z-index:50}
.site-header .wrap{display:flex;align-items:center;gap:var(--sp4);min-height:76px;flex-wrap:wrap}
.brand{display:flex;align-items:center;text-decoration:none}
/* Minimum size: the portal floors the horizontal corporate logo at 120px wide
   for digital. This lockup carries a second line, so it is floored at 150px. */
.brand .lockup{height:auto;width:186px;min-width:150px;display:block}
@media(max-width:520px){.brand .lockup{width:150px}}
.site-nav{margin-left:auto;display:flex;align-items:center;gap:var(--sp3);
  flex-wrap:wrap;font-size:var(--t-body)}
.site-nav a:not(.btn){color:var(--text);text-decoration:none;display:inline-flex;
  align-items:center;min-height:44px}
.site-nav a:not(.btn):hover{text-decoration:underline}
/* The page you are on. Weight and a thicker rule, not colour, so the mark still
   reads for a visitor who cannot separate the palette. It sits after :hover
   because the hover shorthand would otherwise reset the thickness. */
.site-nav a:not(.btn).is-current{font-weight:700;text-decoration:underline;
  text-decoration-thickness:2px}
.site-nav a.btn{text-decoration:none}

/* Placements is a dropdown on the live site and is one here. A `details`
   element, so it opens on click and on Enter and needs no script; its children
   are in the markup whether it is open or shut, so neither page is ever
   unreachable. Square, ruled and bordered in Cool Grey, like every other
   surface on the site. */
.nav-group{position:relative}
.nav-group>summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;
  gap:var(--sp2);min-height:44px;color:var(--text)}
.nav-group>summary::-webkit-details-marker{display:none}
/* The disclosure mark is a drawn chevron with rounded ends, in the same stroke
   language as every other mark on the site. */
.nav-group>summary::after{content:"";width:7px;height:7px;
  border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;
  transform:translateY(-2px) rotate(45deg);transition:transform .2s ease}
.nav-group[open]>summary::after{transform:translateY(1px) rotate(-135deg)}
.nav-group>summary:hover{text-decoration:underline}
.nav-group>summary.is-current{font-weight:700;text-decoration:underline;
  text-decoration-thickness:2px}
.nav-group>summary:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.nav-group-menu{display:flex;flex-direction:column}
@media(min-width:861px){
  .nav-group-menu{position:absolute;top:100%;left:0;z-index:60;min-width:190px;
    background:var(--white);border:1px solid var(--line);padding:var(--sp2) 0}
  .nav-group-menu a{padding:10px var(--sp4)}
}
@media(max-width:860px){
  .nav-group{width:100%}
  .nav-group-menu{padding-left:var(--sp4)}
}
.nav-group-menu a{color:var(--text);text-decoration:none;display:flex;
  align-items:center;min-height:44px}
.nav-group-menu a:hover{text-decoration:underline}
.nav-group-menu a.is-current{font-weight:700;text-decoration:underline;
  text-decoration-thickness:2px}

/* ---------------------------------------------------------------------------
   Controls. Thick brand lines have rounded ends, and the buttons follow them.
   --------------------------------------------------------------------------- */
/* Measured off hexagon.com's own call to action on 24 August: 48px tall, 16px
   label at 400, padding 12px 40px, a full pill, and #005198, which is the blue
   this site already uses. Ours stood 56 tall on 14px/36px plus a 2px border,
   and that extra height is what made it read heavier than theirs. The border
   stays, so a primary and a secondary button still line up, and the vertical
   padding carries the difference. Their label is tracked -0.08px at 16px,
   which is the one place this site tracks anything, and it is theirs. */
.btn{display:inline-flex;align-items:center;gap:var(--sp1);border-radius:var(--r-pill);
  padding:10px 40px;font:inherit;letter-spacing:-.005em;text-decoration:none;
  border:2px solid transparent;
  cursor:pointer;transition:background .2s ease,border-color .2s ease,color .2s ease;
  min-height:44px}
.btn-primary{background:var(--sky-dark);color:var(--white)}
/* Hexagon puts a long, thin arrow after the label on its calls to action, and
   the label and the arrow sit apart rather than crowded. It was typed into
   some templates as a character and missing from others, so "Apply now" had
   none and the submit button had none. The button draws it now, so none of
   them can drift. Drawn rather than set as "→", because the character in
   Arial is short and heavy and does not read as the same mark.

   Not on `.btn-small`: the masthead button is 22px of side padding and an
   arrow crowds it. */
.btn-primary:not(.btn-small)::after{content:"";flex:none;width:34px;height:12px;
  margin-left:var(--sp2);background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 34 12' fill='none' stroke='%23fff' stroke-width='1.5'%3E%3Cpath d='M0 6h31M26 1l6 5-6 5'/%3E%3C/svg%3E") center/contain no-repeat}
.band-green .btn-primary:not(.btn-small)::after{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 34 12' fill='none' stroke='%23fff' stroke-width='1.5'%3E%3Cpath d='M0 6h31M26 1l6 5-6 5'/%3E%3C/svg%3E")}
.btn-primary:hover{background:var(--navy)}
.btn-secondary{background:transparent;color:var(--text);border-color:var(--text);padding:10px 32px}
.btn-secondary:hover{background:var(--text);color:var(--white)}
.band-navy .btn-secondary,
.band-deep .btn-secondary,.band-blue .btn-secondary,.on-inverse .btn-secondary{
  color:var(--white);border-color:var(--white)}
.band-navy .btn-secondary:hover,
.band-deep .btn-secondary:hover,.band-blue .btn-secondary:hover,.on-inverse .btn-secondary:hover{
  background:var(--white);color:var(--navy)}
.btn-danger{background:transparent;color:var(--text);border-color:var(--text);padding:12px 28px}
.btn-danger:hover{background:var(--text);color:var(--white)}
.btn-small{padding:9px 22px;font-size:var(--t-body)}

section{padding:var(--sp7) 0}
@media(min-width:1024px){section{padding:var(--sp8) 0}}
.muted{color:var(--text-support)}
/* A section's opening paragraph is body text. It used to be set at the title
   size, which is the size a card heading takes, so an introduction read as
   loudly as a heading and sat only four pixels below the section heading above
   it — too small a step to be a step at all. Two sections on the homepage never
   used this class and were therefore already correct, which is what made the
   page look uneven. It is body size everywhere now, and the measure stays,
   because a wide line is hard to read whatever size it is set at. */
.lede{font-size:var(--t-body);line-height:1.55;max-width:56ch}
.centred{text-align:center}
.prose>:first-child{margin-top:0}
.stack{display:grid;gap:var(--sp4)}

/* ---------------------------------------------------------------------------
   Line tiles. Every Hexagon layout opens with one: thick coloured lines with
   rounded ends for humanity, thin grey lines for precision, held at 1:20.
   --------------------------------------------------------------------------- */
.rule-tile{display:flex;flex-direction:column;gap:var(--sp2);margin-bottom:var(--sp5)}
.rule-tile::before{content:"";display:block;width:120px;height:var(--line-thick);
  border-radius:var(--r-pill);background:var(--sky)}
.rule-tile::after{content:"";display:block;width:220px;height:var(--line-thin);
  background:var(--line)}
.rule-tile-land::before{background:var(--land)}
.rule-tile-sea::before{background:var(--sea)}
.rule-tile-sky::before{background:var(--sky)}
.on-inverse .rule-tile::after,.band-navy .rule-tile::after,
.band-deep .rule-tile::after,.band-blue .rule-tile::after{background:var(--grey-4)}
.divider{border:0;border-top:1px solid var(--line);margin:var(--sp7) 0}

/* Colour bands. Light mode leads on white and neutral; a colour band is an
   accent, and the ratio guidance keeps them occasional rather than continuous. */
.band-blue{background:var(--sky-dark);color:var(--white)}
.band-navy,.band-deep{background:var(--navy);color:var(--white)}
.band-turq{background:var(--sea);color:var(--black)}
.band-green{background:var(--land);color:var(--black)}
.band-yellow{background:var(--accent-land);color:var(--black)}
.band-grey{background:var(--surface-alt)}
.inverse,.on-inverse{background:var(--surface-inverse);color:var(--text-inverse)}
.band-blue a:not(.btn),.band-navy a:not(.btn),.band-deep a:not(.btn),
.inverse a:not(.btn),.on-inverse a:not(.btn){color:var(--link-inverse)}
.band-turq a:not(.btn),.band-green a:not(.btn),.band-yellow a:not(.btn){color:var(--navy)}
.band-blue h1,.band-blue h2,.band-navy h1,.band-navy h2,
.band-deep h1,.band-deep h2{color:var(--white)}
/* Support text takes its value from the ground it sits on. Scoping the token
   rather than restating the colour means .muted, figcaption, dt, .meta, .note
   and every other secondary voice correct themselves together, and none of
   them can be left behind on a surface where Cool Grey 9 C would fail. */
.band-navy,.band-deep,.band-blue,.primer-head,
.inverse,.on-inverse,.site-footer{--text-support:var(--text-support-inverse)}
.band-turq,.band-green,.band-yellow{--text-support:var(--navy)}
/* Cool Grey 9 C reads 3.85:1 on Cool Grey 1 C, which is short of AA, so every
   surface painted in the alternate light ground steps down to Cool Grey 11 C. */
.band-grey,.stat,.primer-figure,.primer-example,.note-soft,.legacy-note,
.facts-band{--text-support:var(--grey-11)}
.on-turq{color:var(--navy)}

/* ---------------------------------------------------------------------------
   Digital line tile. Hexagon.com currently renders the precision strokes at
   1px and the rounded human strokes at 24px on desktop / 16px on phones. The
   viewBox keeps one shared junction while vector-effect protects those exact
   weights as the component changes size.
   --------------------------------------------------------------------------- */
.brand-line-tile{display:block;width:100%;height:100%;overflow:visible;
  --tile-upper:var(--land);--tile-lower:var(--sky);--tile-thick:24px}
.brand-line-tile line{vector-effect:non-scaling-stroke;fill:none}
.line-tile-thin{stroke:var(--line);stroke-width:calc(var(--tile-thick) / 20);
  stroke-linecap:butt}
.line-tile-thick{stroke-width:var(--tile-thick);stroke-linecap:round}
.line-tile-upper{stroke:var(--tile-upper)}
.line-tile-lower{stroke:var(--tile-lower)}
@media(max-width:1050px){.brand-line-tile{--tile-thick:16px}}

/* ---------------------------------------------------------------------------
   Home hero. The line tile is the image frame, as on Hexagon's current home
   page: stable text at the left, changing imagery inside a geometric reveal at
   the right. The carousel remains automatic and silent.
   --------------------------------------------------------------------------- */
.hero{position:relative;overflow:hidden;background:var(--white);color:var(--black);padding:0;
  isolation:isolate;display:grid;min-height:720px}
.hero-stage,.hero-shape{position:absolute;top:0;right:0;bottom:0;width:58%}
.hero-stage{z-index:1;display:grid;
  clip-path:polygon(31% 0,100% 0,100% 100%,31% 100%,0 50%);
  transition:clip-path .9s cubic-bezier(.22,1,.36,1)}
.hero-slide{grid-area:1/1;width:100%;height:100%;object-fit:cover;object-position:center;
  opacity:0;transform:scale(1);transition:opacity 1.2s ease-in-out,
  transform 7.4s cubic-bezier(.2,.65,.25,1);will-change:opacity,transform}
.hero-slide.is-current{opacity:1;transform:scale(1.055)}
.hero-pathway-slide{object-fit:contain;object-position:center;background:var(--white);
  box-sizing:border-box;padding:40px 60px 60px;transform:translateX(6%) scale(.66)}
.hero-pathway-slide.is-current{transform:translateX(6%) scale(.66)}
.hero.is-pathway-slide .hero-stage{
  clip-path:polygon(0 0,100% 0,100% 100%,0 100%,0 50%)}
.hero-veil{position:absolute;inset:0;background:rgba(255,255,255,.04)}
.hero-shape{z-index:2;pointer-events:none;transition:opacity .45s ease}
.hero.is-pathway-slide .hero-shape{opacity:1}
.hero.is-pathway-slide .hero-line-tile .line-tile-thin{opacity:0}
.hero-body{position:relative;z-index:3;min-height:720px;padding-top:var(--sp9);
  padding-bottom:var(--sp9);display:flex;flex-direction:column;justify-content:center;
  gap:var(--sp3);align-items:flex-start;width:100%}
/* One measure for the whole hero column, so the paragraphs stop on the line the
   heading stops on rather than running past it. The heading is 15ch, and in
   Arial "0" advances 0.556em, so 15ch is 8.34 times the heading's own font size
   however that font size clamps. */
/* The paragraph measure is held to the heading's own size, so the two keep
   their relationship when the heading changes. The multiplier is set so the
   column stays where it was, 418px at 1440, now that the heading sets from
   the 18-anchored chain rather than the display step. */
.hero-body{--hero-measure:calc(9.5 * var(--t-display))}
.hero-body>*{max-width:min(36%,var(--hero-measure))}
.hero h1{max-width:15ch}
/* The two hero paragraphs are one statement, so they take one type treatment and
   one colour. Hexagon sets light-mode type at 100% black; grey is support text,
   and neither of these is support text. */
.hero .lede,.hero-support{color:var(--black);font-size:var(--t-lead);line-height:1.4}
.hero-actions{display:flex;flex-wrap:wrap;gap:var(--sp3)}
.hero .btn-secondary{color:var(--black);border-color:var(--black)}
.hero .btn-secondary:hover{background:var(--black);color:var(--white)}
.hero-kicker{display:block;font-size:var(--t-sm);line-height:1.4;color:var(--sky-dark);
  margin-bottom:var(--sp2)}

/* The measured live sequence is ordered rather than abrupt: framework, title,
   supporting copy and then the photograph. The easing does most of the work;
   there is no animation runtime or continuous loop. */
.js .hero-line-tile line,.js .edge-line-tile line{stroke-dasharray:0 1}
.js .hero-line-tile .line-tile-thin{animation:line-tile-draw .72s cubic-bezier(.22,1,.36,1) .15s forwards}
.js .hero-line-tile .line-tile-thick{animation:line-tile-draw .86s cubic-bezier(.22,1,.36,1) .36s forwards}
.js .hero-stage{clip-path:polygon(100% 50%,100% 50%,100% 50%,100% 50%,100% 50%);
  animation:hero-image-reveal 1.08s cubic-bezier(.22,1,.36,1) .82s forwards}
.js .hero-reveal>.hero-kicker{opacity:0;transform:translateY(16px);
  animation:hero-copy-in .62s cubic-bezier(.22,1,.36,1) .42s forwards}
.js .hero-reveal>h1{opacity:0;transform:translateY(24px);
  animation:hero-copy-in .78s cubic-bezier(.22,1,.36,1) .62s forwards}
.js .hero-reveal>.lede{opacity:0;transform:translateY(20px);
  animation:hero-copy-in .74s cubic-bezier(.22,1,.36,1) .90s forwards}
.js .hero-reveal>.hero-support{opacity:0;transform:translateY(18px);
  animation:hero-copy-in .72s cubic-bezier(.22,1,.36,1) 1.10s forwards}
.js .hero-reveal>.hero-actions{opacity:0;transform:translateY(18px);
  animation:hero-copy-in .70s cubic-bezier(.22,1,.36,1) 1.30s forwards}
@keyframes line-tile-draw{to{stroke-dasharray:1 1}}
@keyframes hero-image-reveal{to{clip-path:polygon(31% 0,100% 0,100% 100%,31% 100%,0 50%)}}
@keyframes hero-copy-in{to{opacity:1;transform:none}}

/* ---------------------------------------------------------------------------
   Interior hero, on the same editorial system Spotlight proved.

   Light ground, so the two mandatory Cool Grey 4 C margin lines stay visible
   across it and the page's one dark emphasis is still available further down.
   The device is the real primary line tile, anchored to the bottom right: its
   thin strokes terminate on the page edge and its thick strokes terminate on
   the divider that opens the first section, so nothing floats detached.
   --------------------------------------------------------------------------- */
.hero-compact{background:var(--surface);color:var(--text);position:relative;
  overflow:hidden;isolation:isolate;padding:var(--sp8) 0}
@media(min-width:1024px){.hero-compact{padding:var(--sp9) 0 var(--sp10)}}
.hero-compact .wrap{position:relative;z-index:2}
.hero-compact-body>:last-child{margin-bottom:0}
@media(min-width:1051px){.hero-compact-body{max-width:46%}}
.hero-compact .lede{max-width:46ch}
/* The hero heading carries a sentence, so it takes the 44 step rather than the
   50 one, at the line-height and tracking hexagon.com sets there: 1.09 and
   -0.039em, against the 1.16 and -0.033em the page scale uses further down.
   Both heroes share it, so the home page and the interior pages do not
   disagree about how a page opens. */
/* Written through `body.is-public main` because the page scale is declared at
   that specificity further down; a plainer `.hero h1` is outranked by it and
   silently does nothing. */
body.is-public main .hero h1,body.is-public main .hero-compact h1{
  font-size:var(--t-display);
  line-height:1.09;letter-spacing:normal}
/* Hexagon sets its body text at 16/24 with a slight negative tracking,
   -0.08px at 16px, which is -0.005em. That tracking is most of what makes
   their paragraphs read as finer than ours; the weight is 400 on their site
   as it is on ours, and the brand allows no Light. */
body.is-public main .hero .lede,body.is-public main .hero-compact .lede,
body.is-public main .hero-support{font-size:var(--t-body);line-height:1.5;
  letter-spacing:normal}
.hero .eyebrow-line,.hero-compact .eyebrow-line,.hero-kicker{font-size:var(--t-ui)}

.hero-compact-actions{margin-top:var(--sp5)}

/* A hero carrying a diagram sets its copy and the diagram side by side, so the
   diagram occupies the corner the line tile would otherwise hold. Below the
   two-column breakpoint the diagram follows the copy rather than shrinking
   beside it: the course pyramid carries type of its own and stops being
   readable much under half the page. */
.hero-compact-figured .wrap{display:grid;gap:var(--sp6);align-items:center}
.hero-compact-figured .hero-compact-body{max-width:none}
.hero-compact-figure{margin:0}
.hero-compact-figure img{display:block;width:100%;height:auto;
  max-width:520px;margin-inline:auto}
@media(min-width:1024px){
  .hero-compact-figured .wrap{grid-template-columns:minmax(0,1fr) minmax(0,0.85fr)}
  .hero-compact-figure img{margin-inline:0 auto}
}
/* The tile is anchored to the bottom right of the hero, so its thin strokes
   terminate on the page edge and its thick strokes terminate on the divider
   that opens the first section. It is not an `edge-line-tile`: those wait for
   the scroll observer, and this one is above the fold on every page, so it
   draws once on load like the homepage hero rather than starting invisible. */
.hero-compact-tile{position:absolute;right:0;bottom:0;
  width:min(40%,520px);height:300px;z-index:1;pointer-events:none}
/* A page whose hero is one short line — sign in, reset a password, verify a
   certificate, an error surface — takes the same framework at a smaller
   measure, so the device never outweighs the sentence it sits beside. */
.hero-compact-tight{padding:var(--sp7) 0}
@media(min-width:1024px){.hero-compact-tight{padding:var(--sp8) 0 var(--sp8)}}
.hero-compact-tight .hero-compact-tile{width:min(28%,330px);height:180px}
/* Below the width at which the copy can sit beside it, the tile drops under the
   copy rather than across it. The hero reserves exactly the tile's height, so
   no line ever crosses or sits flush against a word. */
@media(max-width:1050px){
  .hero-compact{padding-bottom:calc(var(--sp7) + 168px)}
  .hero-compact-tile{width:min(62%,300px);height:150px}
  .hero-compact-tight{padding-bottom:calc(var(--sp6) + 126px)}
  .hero-compact-tight .hero-compact-tile{width:min(52%,240px);height:112px}
}
.js .hero-compact-line line{stroke-dasharray:0 1}
.js .hero-compact-line .line-tile-thin{
  animation:line-tile-draw .72s cubic-bezier(.22,1,.36,1) .15s forwards}
.js .hero-compact-line .line-tile-thick{
  animation:line-tile-draw .86s cubic-bezier(.22,1,.36,1) .36s forwards}
/* Each hero names its pair of published strokes rather than carrying a colour
   of its own, so no page can introduce a value outside the palette. */
.hero-compact-sky .brand-line-tile{--tile-upper:var(--sea);--tile-lower:var(--sky)}
.hero-compact-land .brand-line-tile{--tile-upper:var(--land);--tile-lower:var(--sea)}
.hero-compact-sea .brand-line-tile{--tile-upper:var(--sea);--tile-lower:var(--land)}
.hero-compact-deep .brand-line-tile{--tile-upper:var(--sky);--tile-lower:var(--sea)}

/* ---------------------------------------------------------------------------
   The interior page framework.

   Every public page that is not the homepage and not Spotlight — both of which
   carry their own approved composition — takes the same measured framework:
   a Cool Grey 4 C divider opens each section and starts at the fixed vertical
   margin line rather than crossing it, and the content column sits one full
   margin unit inside that line, so no line ever runs flush against copy.
   --------------------------------------------------------------------------- */
/* The hero is excluded by name rather than by order: this selector is more
   specific than `.hero-compact`, so without the exclusion it would silently
   take the hero's own padding away from it. */
body.is-public:not(.is-home) main>section:not(.hero-compact){position:relative;
  isolation:isolate;padding:var(--sp8) 0}
@media(min-width:1024px){
  body.is-public:not(.is-home) main>section:not(.hero-compact){padding:var(--sp8) 0}
}
body.is-public:not(.is-home) main>section:not(.hero-compact)::before{content:"";
  position:absolute;top:0;left:0;right:0;height:var(--line-thin);
  background:var(--line);z-index:1}
body.is-public:not(.is-home) main>section>.wrap{position:relative;z-index:2}
@media(min-width:1200px){
  body.is-public:not(.is-home) main>section:not(.hero-compact)::before{left:var(--margin)}
}
/* The partner band closes every page against the footer and needs no rule of
   its own above it. */
body.is-public:not(.is-home) main>section.partners-band::before{content:none}

/* Homepage brand grammar. Dividers start at the margin line rather than
   crossing it. The same reusable tile appears at two major transitions only. */
.home-ruled{position:relative}
.home-ruled::before{content:"";position:absolute;top:0;left:16px;right:0;
  height:var(--line-thin);background:var(--line);z-index:1}
.home-brand-section{position:relative;overflow:hidden;isolation:isolate}
.home-brand-section>.wrap{position:relative;z-index:2}
.edge-line-tile{position:absolute;right:0;width:420px;height:250px;z-index:1;
  pointer-events:none}
.edge-line-tile-land .brand-line-tile{--tile-upper:var(--land);--tile-lower:var(--sea)}
.edge-line-tile-sky .brand-line-tile{--tile-upper:var(--sea);--tile-lower:var(--sky)}
.edge-line-tile-bottom{bottom:0}
.edge-line-tile-top{top:0;transform:scaleY(-1)}
.js .edge-line-tile.is-visible .line-tile-thin{
  animation:line-tile-draw .68s cubic-bezier(.22,1,.36,1) forwards}
.js .edge-line-tile.is-visible .line-tile-thick{
  animation:line-tile-draw .84s cubic-bezier(.22,1,.36,1) .28s forwards}
/* The clip belongs to the picture, not to the figure. While it sat on the
   figure, the frame's bottom-left corner radius cut the first letter off every
   caption underneath it. */
.figure-frame{display:block;overflow:hidden;border-radius:var(--r-shape)}
.home-motion-media{overflow:hidden;border-radius:var(--r-shape)}
.js .home-motion-media img{opacity:.72;transform:scale(.985);
  transition:opacity 1.05s ease,transform 1.55s cubic-bezier(.22,1,.36,1)}
.js .home-motion-media.is-visible img{opacity:1;transform:scale(1.018)}

/* ---------------------------------------------------------------------------
   The measured Hexagon type scale, for the whole public surface.

   These values were measured directly on hexagon.com at a 1440px desktop
   viewport and were already approved twice: once for the homepage and again
   for Spotlight. They were declared separately under `.is-home` and under
   `.spot`, identically, and every other public page fell back to an older
   scale — a 50/58 heading against Spotlight's 51/61, and a 21px lead paragraph
   against Spotlight's 18/28. That is why an interior hero did not match the
   approved one. There is one declaration now, and the two page-scoped copies
   are gone.

   Scoped to `main` so the footer's own heading keeps its size, and to the
   public surface so the signed-in learner and administrator areas are not
   changed by a public presentation decision.
   --------------------------------------------------------------------------- */
body.is-public main h1{font-size:var(--t-display);line-height:1.16;
  letter-spacing:normal}
body.is-public main h2{font-size:var(--t-section);line-height:1.18;
  letter-spacing:normal}
body.is-public main h3{font-size:var(--t-title);line-height:1.32;
  letter-spacing:normal}
body.is-public main .lede{font-size:var(--t-body);line-height:1.55}
.is-home .btn{transition-duration:.5s}

/* Hexagon keeps the line tile on phones at 16px and stacks the framed image
   below the copy. Touch layouts do not depend on hover to reveal information. */
@media(max-width:1050px){
  .hero{grid-template-rows:auto 340px;min-height:0}
  .hero-body{grid-row:1;min-height:0;padding-top:var(--sp7);padding-bottom:var(--sp7)}
  .hero-body>*{max-width:100%}
  .hero h1{max-width:15ch}
  .hero-stage,.hero-shape{position:relative;grid-row:2;grid-column:1;
    inset:auto;width:100%;height:340px}
  .hero-pathway-slide{padding:14px 28px 38px}
  .home-ruled::before{left:0}
  .edge-line-tile{display:none}
}
@media(hover:hover) and (pointer:fine){
  .is-home .home-motion-media.is-visible img{
    transition:opacity 1.05s ease,transform .5s cubic-bezier(.22,1,.36,1)}
  .is-home .home-motion-media:hover img{transform:scale(1.1)}
}

/* Short labels above a heading. Sentence case, per the portal's primary
   standard; the colour and the rule carry the emphasis instead of capitals.
   The Accent Land pill this rule once also defined is gone: no page served
   from this stylesheet used it, and a coloured pill above every heading is the
   repeated label the layout system tells us to avoid. The project editions
   keep their own, in their own document stylesheet. */
.eyebrow-line{display:block;font-size:var(--t-sm);color:var(--sky-dark);
  margin-bottom:var(--sp2)}
.band-navy .eyebrow-line,
.band-deep .eyebrow-line,.band-blue .eyebrow-line,.primer-head .eyebrow-line{
  color:var(--accent-sea)}
.band-turq .eyebrow-line,.band-green .eyebrow-line,.band-yellow .eyebrow-line{color:var(--navy)}

/* ---------------------------------------------------------------------------
   Text beside picture, and image shapes.
   --------------------------------------------------------------------------- */
.split{display:grid;gap:var(--sp6);align-items:center}
@media(min-width:900px){.split{grid-template-columns:1fr 1fr;gap:var(--sp8)}
  .split-media-first>:first-child{order:-1}}
@media(max-width:899px){.split-media-first>figure{order:2}}

/* An image shape that does not bleed off the page takes the radius guide on
   every corner. No diagonal crop: the subject stays whole. */
.figure-cut{margin:0}
.figure-cut img{width:100%;height:auto;display:block;border-radius:var(--r-shape);
  background:var(--surface-alt)}
.figure-cut figcaption{margin-top:var(--sp3);font-size:var(--t-sm);color:var(--text-support)}
.band-navy .figure-cut figcaption,.band-deep .figure-cut figcaption,
.band-blue .figure-cut figcaption{color:var(--text-support-inverse)}

.grid{display:grid;gap:var(--sp4)}
@media(min-width:700px){.grid-2{grid-template-columns:repeat(2,1fr)}
  .grid-3{grid-template-columns:repeat(3,1fr)}}

.card{border:1px solid var(--line);border-radius:var(--r-shape);padding:var(--sp5);
  background:var(--white);transition:border-color .15s ease}
.card:hover{border-color:var(--grey-9)}
.card h3{margin-top:0}
.on-inverse .card,.band-navy .card,.band-deep .card{background:transparent;
  border-color:var(--grey-4);color:var(--white)}

.counters{display:grid;gap:var(--sp5);grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}
/* Tabular figures, so a number that is counting up cannot jitter its own
   width digit by digit while it moves. */
.counter .n{font-size:var(--t-section);line-height:1.1;letter-spacing:normal;
  font-variant-numeric:tabular-nums}
.shape{position:relative;overflow:hidden;border-radius:var(--r-shape);
  background:var(--surface-alt);min-height:220px}
.shape svg{position:absolute;inset:0;width:100%;height:100%}

/* Ticks. A drawn mark, so it survives a missing glyph, with the rounded caps
   the icon style requires. */
.ticks{list-style:none;padding:0;margin:0 0 var(--sp4)}
.ticks li{position:relative;padding:0 0 var(--sp2) 32px}
.ticks li::before{content:"";position:absolute;left:2px;top:.42em;width:14px;height:8px;
  border-left:2.5px solid var(--land-dark);border-bottom:2.5px solid var(--land-dark);
  border-bottom-left-radius:2px;transform:rotate(-45deg)}
.band-navy .ticks li::before,.band-deep .ticks li::before,.band-blue .ticks li::before{
  border-color:var(--accent-sea)}
.band-turq .ticks li::before,.band-green .ticks li::before,.band-yellow .ticks li::before{
  border-color:var(--navy)}
.rail-item .ticks{margin-bottom:0;font-size:var(--t-body)}
/* The sub-heading that introduces the three audiences on About. */
.audience-lead{margin:var(--sp7) 0 0}

/* ---------------------------------------------------------------------------
   Forms.
   --------------------------------------------------------------------------- */
label{display:block;font-size:var(--t-sm);margin-bottom:var(--sp1)}
input:not([type=checkbox]):not([type=radio]):not([type=hidden]):not([type=submit]):not([type=button]),
textarea,select{
  width:100%;padding:12px 16px;font:inherit;border:1px solid var(--grey-9);
  border-radius:var(--r-ui);background:var(--white);color:var(--text)}
input:focus-visible,textarea:focus-visible,select:focus-visible{border-color:var(--sky-dark)}
textarea{min-height:140px}
.field{margin-bottom:var(--sp4);max-width:560px}
/* Sign-in, sign-up, password reset, certificate verification and the public
   forms all read as one measured column rather than running the width of the
   page. Only the presentation is set here; no field, rule or route changes. */
.form-column{max-width:620px}
.form-column>:last-child{margin-bottom:0}

/* Radio groups, checkbox groups and consent boxes. The live school asked 104
   single-choice questions and 28 consent questions across its forms; each is a
   row of its own so the box and its wording read as one thing, and the whole
   row is a label so the wording is part of the target. */
.choices{display:flex;flex-direction:column;gap:var(--sp1)}
.choice{display:flex;gap:var(--sp2);align-items:flex-start;margin:0;
  font-size:var(--t-base);line-height:1.45;cursor:pointer}
.choice input{flex:0 0 auto;margin-top:4px;width:18px;height:18px;accent-color:var(--sky-dark)}
.choice span{flex:1 1 auto}
.choice:hover span{color:var(--sky-dark)}
.choice input:focus-visible{outline:2px solid var(--sky-dark);outline-offset:2px}

/* A question that applies only to some people is hidden until it does. Without
   JavaScript nothing is hidden and every question is asked, which is correct
   but longer. */
.field-conditional[hidden]{display:none}

/* Flash messages. Special-use red is a functional indicator, never the type:
   the message stays black and the colour arrives as a bar beside it. */
.flash{padding:var(--sp3) var(--sp4);border:1px solid var(--line);
  border-left:6px solid var(--grey-9);border-radius:0 var(--r-ui) var(--r-ui) 0;
  margin-bottom:var(--sp3);color:var(--text);background:var(--white)}
.flash-error{border-left-color:var(--alert)}
.flash-success{border-left-color:var(--land)}

table{width:100%;border-collapse:collapse}
th,td{text-align:left;padding:var(--sp2) var(--sp3);border-bottom:1px solid var(--line-soft);
  vertical-align:top}
th{font-size:var(--t-sm);color:var(--text-support);border-bottom-color:var(--line)}
.table-scroll{overflow-x:auto}

/* The courses catalogue sits on Background Dark Blue, as the live page sets
   it. The cards keep their own ground, so the band is the field they sit on
   rather than a second surface competing with them. */
.course-catalogue{padding:var(--sp8) 0}
@media(min-width:1024px){.course-catalogue{padding:var(--sp9) 0}}
.course-catalogue .eyebrow-line{color:var(--accent-sea)}
.course-catalogue h2{color:var(--text-inverse)}
/* The band lightens its links so they read on Background Dark Blue. The cards
   sitting on it keep their own white ground, so that lightening has to stop at
   the card edge: Accent Land on white is 1.7:1, and the link inside the first
   card was being drawn in it. */
.course-catalogue .course-body a{color:var(--link)}
.course-catalogue .course-body a:hover{color:var(--sky-dark)}
/* The section tile is decoration and belongs behind the cards. */
.course-catalogue>.wrap{position:relative;z-index:2}

/* Revoking and reissuing a certificate each need their own written reason,
   because each is recorded separately in the audit trail. Side by side in one
   cell the two boxes wrapped, so a reason box appeared to belong to nothing.
   Each action is now its own row: reason, then the button that uses it. */
.cert-actions{display:flex;flex-direction:column;gap:var(--sp2);align-items:flex-start}
.cert-action{display:flex;flex-wrap:nowrap;gap:var(--sp2);align-items:center}
.cert-action input{width:190px}

.progress{height:8px;background:var(--grey-1);border-radius:var(--r-pill);overflow:hidden}
.progress > i{display:block;height:100%;background:var(--sky);border-radius:var(--r-pill)}
.state{display:inline-flex;align-items:center;gap:var(--sp2);font-size:var(--t-body)}
.dot{width:14px;height:14px;border-radius:50%;border:2px solid var(--grey-9);display:inline-block}
.dot.done{background:var(--land-dark);border-color:var(--land-dark)}
.tag{display:inline-block;font-size:var(--t-sm);padding:3px 12px;border-radius:var(--r-pill);
  border:1px solid var(--line)}
.tag.valid{color:var(--pass);border-color:var(--pass)}
.tag.revoked{color:var(--fail);border-color:var(--fail)}
.tag.replaced{color:var(--text-support)}
.tag.legacy{background:var(--sea);color:var(--navy);border-color:var(--sea)}
/* ---------------------------------------------------------------------------
   Public certificate verification.

   The result page now shows the certificate as well as describing it. The sheet
   below is a representation built from the public record only — number,
   recipient, course, issue date and issuer — set in the same light-mode print
   language as the document itself: white ground, black type, one primary line
   tile, no gradient and no hexagon shape. It is not the PDF and it is not a
   route to the PDF; the download permission boundary is unchanged.
   --------------------------------------------------------------------------- */
.verify-plain{font-size:var(--t-lg);line-height:28px;max-width:62ch}
.cert-view{margin:var(--sp6) 0 var(--sp6)}
.cert-view figcaption{margin-top:var(--sp3);font-size:var(--t-sm);
  color:var(--text-support);max-width:62ch}
/* A4 landscape is 1.414:1. The sheet holds that ratio down to the width where
   holding it would squeeze the type, and then simply grows taller. */
.cert-sheet{background:var(--white);border:var(--line-thin) solid var(--line);
  padding:var(--sp5) var(--sp5) var(--sp4);display:flex;flex-direction:column;
  gap:var(--sp4);color:var(--black)}
@media(min-width:700px){.cert-sheet{aspect-ratio:297/210;padding:var(--sp6)}}
.cert-sheet-head{display:flex;align-items:flex-start;justify-content:space-between;
  gap:var(--sp4);border-bottom:var(--line-thin) solid var(--line);
  padding-bottom:var(--sp3)}
.cert-sheet-head .lockup{width:150px;height:auto;display:block}
.cert-sheet-num{margin:0;text-align:right;font-size:var(--t-xs);color:var(--grey-9);
  line-height:1.5}
.cert-sheet-num span{display:block;font-size:var(--t-sm);color:var(--black);
  font-family:var(--mono)}
.cert-sheet-body{flex:1;display:flex;flex-direction:column;align-items:center;
  justify-content:center;text-align:center}
.cert-sheet-title{margin:0;font-size:var(--t-title);line-height:1.1;
  letter-spacing:normal}
.cert-sheet-label{margin:var(--sp4) 0 0;font-size:var(--t-sm);color:var(--grey-9)}
.cert-sheet-name{margin:var(--sp2) 0 0;font-size:var(--t-title);line-height:1.15}
/* The primary line tile, at the same 1:20 thin-to-thick relationship the printed
   certificate holds. */
.cert-sheet-tile{display:block;width:min(180px,42%);height:10px;border-radius:5px;
  background:var(--land);margin-top:var(--sp4)}
.cert-sheet-rule{display:block;width:min(420px,84%);height:var(--line-thin);
  background:var(--line);margin-top:var(--sp3)}
.cert-sheet-course{margin:var(--sp2) 0 0;font-size:var(--t-body);line-height:1.25}
.cert-sheet-date{margin:var(--sp4) 0 0;font-size:var(--t-sm);color:var(--grey-9)}
.cert-sheet-foot{margin:0;font-size:var(--t-xs);line-height:1.6;color:var(--grey-11);
  border-top:var(--line-thin) solid var(--line);padding-top:var(--sp3)}
.verify-again{margin-top:var(--sp6)}

.tag-req{margin-left:var(--sp2);font-size:var(--t-xs);background:var(--accent-land);
  color:var(--navy);border-radius:var(--r-pill);padding:2px 9px;vertical-align:middle}

.curric{list-style:none;padding:0;margin:0}
.curric li{padding:var(--sp3) 0;border-bottom:1px solid var(--line-soft);display:flex;
  align-items:center;gap:var(--sp3);justify-content:space-between}

.foot-h{font-size:var(--t-lg);line-height:1.35;margin:0 0 var(--sp3)}
.site-footer{background:var(--surface-inverse);color:var(--text-inverse);margin-top:var(--sp9)}
.site-footer a{color:var(--link-inverse)}
.site-footer .wrap{padding-top:var(--sp7);padding-bottom:var(--sp7)}
.site-footer .lockup{width:220px;height:auto;display:block;margin-bottom:var(--sp4)}
/* The club page's own hashtag line, as the live page runs it. Support text, not
   a row of labels. */
.club-tags{font-size:var(--t-sm);color:var(--text-support);margin:0 0 var(--sp5)}
.provisional{font-size:var(--t-sm);color:var(--text-support);
  border-left:2px solid var(--line);padding-left:var(--sp3);margin-top:var(--sp3)}

/* ---------------------------------------------------------------------------
   The shared editorial rail.

   This is the composition Spotlight proved, made available to every other
   public page. It replaces the repeated bordered boxes those pages used: the
   oversized rounded card, and the tile that carried a detached 56 x 6 px colour
   bar floating in its corner belonging to nothing. Cool Grey 4 C hairlines
   carry the structure instead, the category orders the eye, and the row itself
   is the click target where the row links somewhere.

   It is deliberately not a second card: no border box, no radius, no shadow, no
   lift and no tilt. Rows are bounded by divider lines, so square is the correct
   shape under the portal's own corner rule.
   --------------------------------------------------------------------------- */
.rail{list-style:none;margin:var(--sp6) 0 0;padding:0;display:grid;
  border-top:var(--line-thin) solid var(--line)}
.rail-item{position:relative;display:flex;flex-direction:column;
  padding:var(--sp5) 0;border-bottom:var(--line-thin) solid var(--line)}
.rail-item>:last-child{margin-bottom:0}
@media(min-width:900px){
  .rail-2{grid-template-columns:repeat(2,1fr)}
  .rail-3{grid-template-columns:repeat(3,1fr)}
  .rail-2 .rail-item,.rail-3 .rail-item{padding:var(--sp6) 0}
  .rail-2 .rail-item:nth-child(odd),
  .rail-3 .rail-item:not(:nth-child(3n)){padding-right:var(--sp7);
    border-right:var(--line-thin) solid var(--line)}
  .rail-2 .rail-item:nth-child(even){padding-left:var(--sp7)}
  .rail-3 .rail-item:not(:nth-child(3n+1)){padding-left:var(--sp7)}
}
.rail-kind{margin:0 0 var(--sp2);font-size:var(--t-sm);color:var(--sky-dark)}
.rail-item h3{margin:0 0 var(--sp3);max-width:26ch}
.rail-item h3 a{color:inherit;text-decoration:none}
.rail-blurb{margin:0 0 var(--sp4);color:var(--text-support);max-width:46ch}
.rail-foot{display:flex;flex-wrap:wrap;gap:var(--sp3);align-items:center;
  margin:auto 0 0;font-size:var(--t-sm)}
.rail-meta{color:var(--text-support)}
.rail-more{margin-left:auto;display:inline-flex;align-items:center;gap:var(--sp3);
  color:var(--link)}
/* The whole row is the target where a row links somewhere, and the mark of the
   link is a line that extends, not a glyph that jumps. */
.rail-link h3 a::after{content:"";position:absolute;inset:0}
.rail-link h3 a:focus-visible{outline:none}
.rail-link:has(a:focus-visible){outline:3px solid var(--focus);outline-offset:-3px}
.rail-link:hover h3 a,.rail-link:focus-within h3 a{text-decoration:underline}
.rail-arrow{position:relative;display:inline-block;flex:none;width:34px;
  height:var(--line-thin);background:var(--link);transition:width .3s ease}
.rail-arrow::after{content:"";position:absolute;right:0;top:-4px;width:8px;height:8px;
  border-top:var(--line-thin) solid var(--link);
  border-right:var(--line-thin) solid var(--link);transform:rotate(45deg)}
.rail-link:hover .rail-arrow,.rail-link:focus-within .rail-arrow{width:52px}
/* On a Dark Blue emphasis band the rules and the link line take the values that
   carry on that ground. */
.band-navy .rail,.band-deep .rail,.band-navy .rail-item,.band-deep .rail-item{
  border-color:var(--grey-4)}
.band-navy .rail-kind,.band-deep .rail-kind,
.band-navy .rail-more,.band-deep .rail-more{color:var(--accent-sea)}
.band-navy .rail-arrow,.band-deep .rail-arrow{background:var(--accent-sea)}
.band-navy .rail-arrow::after,.band-deep .rail-arrow::after{border-color:var(--accent-sea)}

/* The five community groups. The live site names them as five themed groups and
   nothing more, so they are set as a ruled index rather than as five repeated
   pill labels, which is a shape the layout system does not use. */
.group-rail{list-style:none;margin:var(--sp5) 0;padding:0;display:grid;
  border-top:var(--line-thin) solid var(--line)}
@media(min-width:700px){.group-rail{grid-template-columns:repeat(2,1fr)}}
@media(min-width:1024px){.group-rail{grid-template-columns:repeat(3,1fr)}}
.group-rail li{padding:var(--sp3) var(--sp5) var(--sp3) 0;font-size:var(--t-body);
  border-bottom:var(--line-thin) solid var(--line)}
@media(min-width:700px){
  .group-rail li{border-right:var(--line-thin) solid var(--line);
    padding-right:var(--sp5);padding-left:var(--sp4)}
  .group-rail li:first-child{padding-left:0}
}
.band-navy .group-rail,.band-navy .group-rail li,
.band-deep .group-rail,.band-deep .group-rail li{border-color:var(--grey-4)}

/* A definition rail: a term in a left column with its record ruled beside it.
   Used where the material is a list of named things rather than a set of
   summaries — the five community groups, the club leads, the faculty mentors. */
.rail-def{list-style:none;margin:var(--sp6) 0 0;padding:0;
  border-top:var(--line-thin) solid var(--line)}
.rail-def li{display:grid;gap:var(--sp1);padding:var(--sp4) 0;
  border-bottom:var(--line-thin) solid var(--line)}
@media(min-width:700px){
  .rail-def li{grid-template-columns:minmax(0,1fr) minmax(0,1.6fr);
    gap:var(--sp7);align-items:baseline}
}
.rail-def .term{font-size:var(--t-lg);line-height:1.3;margin:0}
.rail-def .said{margin:0;color:var(--text-support)}
.band-navy .rail-def,.band-navy .rail-def li,
.band-deep .rail-def,.band-deep .rail-def li{border-color:var(--grey-4)}

/* ---------------------------------------------------------------------------
   Programme components.
   --------------------------------------------------------------------------- */
.inst-list{list-style:none;padding:0;margin:0;display:grid;gap:var(--sp2)}
@media(min-width:700px){.inst-list{grid-template-columns:repeat(2,1fr);gap:var(--sp2) var(--sp5)}}
.inst-list li{display:flex;flex-direction:column;gap:2px;padding:var(--sp3) 0;
  border-bottom:1px solid var(--line-soft)}
.inst-kind{font-size:var(--t-sm);color:var(--sky-dark)}
.inst-name{font-size:var(--t-body)}

.facts-band{padding:var(--sp5) 0;border-top:1px solid var(--line);
  border-bottom:1px solid var(--line)}
.facts{display:grid;gap:var(--sp4);margin:0;grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
.facts dt{font-size:var(--t-sm);color:var(--text-support)}
.facts dd{margin:var(--sp1) 0 0;font-size:var(--t-lg)}

.link-arrow{text-decoration:none;border-bottom:2px solid var(--sky)}
.link-arrow::after{content:" →"}
.link-arrow:hover{border-bottom-color:var(--link)}

.partners-band{margin-bottom:calc(var(--sp9) * -1)}
.partners-heading{max-width:900px}
.partners-kicker{margin:0 0 var(--sp3);font-size:var(--t-sm);
  color:var(--text-support-inverse)}
.partners-band .partners-statement{margin:0;color:var(--accent-land);
  font-size:var(--t-display);line-height:.98;letter-spacing:normal}
.partners-strip{display:grid;align-items:stretch;grid-template-columns:repeat(3,1fr);
  margin-top:var(--sp7);border-top:var(--line-thin) solid var(--grey-4);
  border-bottom:var(--line-thin) solid var(--grey-4)}
.partner{display:flex;min-height:160px;flex-direction:column;justify-content:space-between;
  gap:var(--sp4);padding:var(--sp5);border-right:var(--line-thin) solid var(--grey-4)}
.partner:first-child{padding-left:0}
.partner:last-child{border-right:0;padding-right:0}
.partner-mark-stage{display:flex;height:68px;align-items:center}
.partner-mark{width:auto;max-width:190px;max-height:64px;height:auto;display:block;
  object-fit:contain;object-position:left center}
.partner span{font-size:var(--t-sm);color:var(--text-support)}
@media(max-width:699px){
  .partners-band .partners-statement{font-size:var(--t-display)}
  .partners-strip{display:block;margin-top:var(--sp6)}
  .partner,.partner:first-child,.partner:last-child{display:grid;min-height:104px;
    grid-template-columns:minmax(150px,1fr) minmax(0,1fr);align-items:center;
    gap:var(--sp4);padding:var(--sp4) 0;border-right:0;
    border-bottom:var(--line-thin) solid var(--grey-4)}
  .partner:last-child{border-bottom:0}
  .partner-mark-stage{height:64px}
}

/* A person: the portrait the programme publishes, then the name and the role
   ruled beside it. Square, like every other frame bounded by a divider. */
/* Scoped to the rail's own list item, which is more specific than the item
   rule it sits inside and would otherwise take the columns back. */
.rail-def li.person-row{display:grid;gap:var(--sp2) var(--sp4);align-items:center;
  grid-template-columns:96px minmax(0,1fr)}
@media(min-width:700px){
  .rail-def li.person-row{grid-template-columns:96px minmax(0,14rem) minmax(0,1fr);
    gap:var(--sp5)}
}
.person-portrait{width:96px;height:96px;object-fit:cover;object-position:center top;
  display:block;grid-row:span 2;background:var(--surface-alt)}
@media(min-width:700px){.person-portrait{grid-row:auto}}
.person-portrait-none{background:var(--surface-alt)}
/* Recorded feedback. A ruled grid of players, square like every other frame
   the divider system bounds, each holding its own 16:9 box so the page does not
   move as the players arrive. */
.video-grid{list-style:none;margin:var(--sp6) 0 0;padding:0;display:grid;gap:var(--sp5)}
@media(min-width:700px){.video-grid{grid-template-columns:repeat(2,1fr)}}
@media(min-width:1024px){.video-grid{grid-template-columns:repeat(3,1fr)}}
.video-frame{position:relative;padding-top:56.25%;background:var(--navy);
  border:1px solid var(--line);border-radius:var(--r-shape);overflow:hidden}
.video-frame iframe{position:absolute;inset:0;width:100%;height:100%;border:0;display:block}
.video-title{margin:var(--sp3) 0 0;font-size:var(--t-body);line-height:1.4}
.band-navy .video-frame,.band-deep .video-frame{border-color:var(--grey-4)}
.spot-voice-portrait{width:120px;height:150px;object-fit:cover;object-position:center top;
  display:block;margin-bottom:var(--sp4);background:var(--surface-alt);
  border-radius:var(--r-shape)}

.mcard{border:1px solid var(--line);border-radius:var(--r-ui);overflow:hidden;
  background:var(--white);display:flex;flex-direction:column;
  transition:transform .15s ease,border-color .15s ease}
.mcard:hover{border-color:var(--grey-9)}
.mcard .shot{aspect-ratio:16/9;overflow:hidden;background:var(--surface-alt);position:relative}
.mcard .shot img{width:100%;height:100%;object-fit:cover;display:block}
.mcard .body{padding:var(--sp4);flex:1;display:flex;flex-direction:column;gap:var(--sp2)}
.mcard h3{margin:0;font-size:var(--t-lg)}
.mcard .meta{font-size:var(--t-sm);color:var(--text-support);margin-top:auto}
.course-kind{font-size:var(--t-sm);color:var(--sky-dark)}

.cat{font-size:var(--t-sm);color:var(--sky-dark)}

/* The programme progression is the diagram the live homepage publishes, used as
   captured rather than redrawn: its five stages, their numbering, the dashed
   pre-requisite group around stages one and two, the idea-submission and
   assessment annotations, and the route that proves an idea from three to
   five. Sizing and placement only. */
.pyramid-figure{margin:var(--sp6) 0 0;display:flex;justify-content:center}
.pyramid-figure img{width:100%;max-width:720px;height:auto;display:block}

.timeline{list-style:none;padding:0;margin:0;border-left:1px solid var(--line)}
.timeline li{padding:0 0 var(--sp5) var(--sp5);position:relative}
.timeline li::before{content:"";position:absolute;left:-7px;top:8px;width:13px;height:13px;
  background:var(--sky);border-radius:50%}
.timeline .yr{font-size:var(--t-sm);color:var(--sky-dark)}

.timeline-home{list-style:none;margin:var(--sp6) 0 var(--sp5);padding:0;
  display:grid;grid-template-columns:repeat(5,minmax(0,1fr));
  border-top:var(--line-thin) solid var(--line);border-bottom:var(--line-thin) solid var(--line)}
.timeline-home li{position:relative;min-width:0;border-right:var(--line-thin) solid var(--line);
  background:var(--white)}
.timeline-home li:last-child{border-right:0}
.milestone-media{display:block;position:relative;aspect-ratio:16/9;overflow:hidden;
  border-radius:0;background:var(--surface-alt)}
.milestone-media img{width:100%;height:100%;object-fit:cover;display:block}
.timeline-home li:nth-child(1) .milestone-media img{object-position:center 52%}
.timeline-home li:nth-child(2) .milestone-media img{object-position:center 48%}
.timeline-home li:nth-child(3) .milestone-media img{object-position:center 44%}
.timeline-home li:nth-child(4) .milestone-media img{object-position:center 52%}
.timeline-home li:nth-child(5) .milestone-media img{object-position:center 42%}
/* A compact line-and-image tile: the Cool Grey precision stroke is 5% of the
   round-ended human stroke, and the full strip uses only Sky and Sea. */
.milestone-line{position:absolute;right:-20px;bottom:27px;width:118px;height:1px;
  background:var(--grey-4);transform:translateX(var(--milestone-line-shift,0)) rotate(-32deg);
  transform-origin:center;transition:transform .5s cubic-bezier(.22,1,.36,1)}
.milestone-line::after{content:"";position:absolute;right:-10px;top:50%;width:68px;height:20px;
  border-radius:999px;background:var(--sky);transform:translateY(-50%)}
.timeline-home li:nth-child(even) .milestone-line::after{background:var(--sea)}
.milestone-copy{display:block;min-height:168px;padding:var(--sp4) var(--sp4) var(--sp5)}
.timeline-home .milestone-number{display:block;font-size:var(--t-sm);color:var(--sky-dark);
  margin-bottom:var(--sp3)}
.timeline-home h4{font-size:var(--t-lg);line-height:1.4;margin:0;max-width:17ch;font-weight:400}
@media(hover:hover) and (pointer:fine){
  .timeline-home li:hover .milestone-line{--milestone-line-shift:-12px}
}
@media(max-width:899px){
  .timeline-home{grid-template-columns:repeat(2,minmax(0,1fr))}
  .timeline-home li:nth-child(even){border-right:0}
  .timeline-home li:nth-child(-n+3){border-bottom:var(--line-thin) solid var(--line)}
  .timeline-home li:nth-child(3){border-right:var(--line-thin) solid var(--line)}
  .timeline-home li:nth-child(5){grid-column:1/-1;border-right:0}
  .timeline-home li:nth-child(5) .milestone-media{aspect-ratio:16/7}
  .milestone-copy{min-height:142px}
  .timeline-home h4{max-width:none;font-size:var(--t-body)}
}

/* The technologies a project was built with. A ruled list, not a row of pills. */
.stack-list{list-style:none;margin:0 0 var(--sp5);padding:0}
.stack-list li{padding:var(--sp2) 0;border-bottom:var(--line-thin) solid var(--line-soft);
  font-size:var(--t-body)}
/* The school cohort takes a full Primary Land band, as the live page gives it
   a full colour band of its own. Black type throughout, which that ground
   requires, and the button inverts so it is legible on it. */
.band-green .eyebrow-line,.band-green .muted,.band-green h2,.band-green p,
.band-green li{color:var(--black)}
.band-green .ticks li::before{border-color:var(--black)}
.band-green .btn-primary{background:var(--black);color:var(--white)}
.band-green .home-ruled::before,.home-ruled.band-green::before{background:var(--line)}

/* The programme's own line, where the live site puts it: in the footer, quiet,
   above the description rather than leading a band of its own. */
.foot-statement{margin:var(--sp4) 0 var(--sp2);font-size:var(--t-lg);line-height:1.25;
  letter-spacing:normal;color:var(--white)}

/* The people who lead the club and the people who mentor it, named on the club
   band as the live page names them. A portrait, a name, a role and an
   institute: the definition rail, not a card. */
/* The live page tiles these people, a portrait above the name, and colours the
   tile. Its ground is Accent Land, which is attention-only and never a ground
   for type; Primary Land takes black type and says the same thing. */
.spot-club-people{display:grid;gap:var(--sp5);margin:var(--sp5) 0 0;
  grid-template-columns:1fr}
@media(min-width:700px){.spot-club-people{grid-template-columns:repeat(2,1fr);gap:var(--sp6)}}
.spot-people-label{margin:0 0 var(--sp3);font-size:var(--t-body);color:var(--land-dark)}
.spot-club-people ul{list-style:none;margin:0;padding:0;display:grid;gap:var(--sp3);
  grid-template-columns:repeat(3,minmax(0,1fr))}
.spot-club-people li{background:var(--land);color:var(--black);border-radius:12px;
  padding:var(--sp2);text-align:center;font-size:var(--t-xs);line-height:1.3;
  display:flex;flex-direction:column;justify-content:flex-end}
/* The portraits the programme holds are small and already cropped close, so
   they are set to one fixed height rather than to a ratio, which was blowing
   the nearest face up to fill a square. One of the six has no portrait at all
   and none is invented for her; her tile is the name alone. */
.spot-club-people img{width:100%;height:110px;object-fit:cover;object-position:center top;
  border-radius:var(--r-shape);display:block;margin:0 0 var(--sp2)}
.spot-club-people b{display:block;margin-bottom:2px}
/* The live page stands the figures beside the opening rather than under it,
   which keeps the whole opening on one screen instead of two. */
.spot-hero-figures{margin-top:var(--sp6);grid-template-columns:repeat(2,1fr);gap:var(--sp4)}
@media(min-width:1000px){
  .spot-hero-grid{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);
    gap:var(--sp8);align-items:center}
  .spot-hero-figures{margin-top:0}
}

/* The collaborations, as one even grid. Every photograph takes the same frame:
   these came in at every ratio their photographer left them at, and the grid
   was ragged because of it. The name and what the collaboration is for sit
   under the picture, which is where the live page puts them. */
.spot-collab-grid{list-style:none;margin:var(--sp6) 0 0;padding:0;display:grid;
  gap:var(--sp4);grid-template-columns:repeat(2,minmax(0,1fr))}
@media(min-width:800px){.spot-collab-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media(min-width:1100px){.spot-collab-grid{grid-template-columns:repeat(4,minmax(0,1fr))}}
/* These are group photographs and handovers: the people stand in the upper
   half of every one of them, so a centred crop took the tops of their heads
   off in seven of the seventeen. A wider frame loses less of the picture, and
   the crop is pulled up to where the faces actually are. */
.spot-collab-shot{display:block;aspect-ratio:4/3;overflow:hidden;
  border-radius:var(--r-shape);
  background:var(--surface-alt)}
.spot-collab-shot img{width:100%;height:100%;object-fit:cover;display:block;
  object-position:center 12%}
/* Sentence case, with the override gone: the standard bars uppercase and
   tracking changes, and these three labels were the last of it on the page. */
.spot-collab-kind{display:block;margin:var(--sp3) 0 2px;font-size:var(--t-body);
  color:var(--sea-dark)}
.spot-collab-name{display:block;font-size:var(--t-body);line-height:1.35}
/* Cool Grey 9 C scores 4.73:1 on white and 3.85:1 on the grey band, which
   fails at this size. Cool Grey 11 C carries it, and the label is at 14 px
   rather than 12: the standard says not to take support text below 16 px, and
   this is as close to that as a caption under a tile can sit. */
.spot-collab-evidence{display:block;margin-top:2px;font-size:var(--t-body);color:var(--grey-11)}
.spot-collab-note{max-width:78ch;margin:var(--sp4) 0 0}

/* A row that opens its own summary. The live site opens the same summary in a
   pop-up; this opens it where it stands, which needs no scripting, keeps the
   row addressable and leaves the page usable with the panel shut. The marker is
   the site's own arrow rather than the browser's triangle. */
.rail-fold{margin-top:var(--sp2)}
.rail-fold>summary{display:inline-flex;align-items:center;gap:var(--sp2);
  cursor:pointer;font-size:var(--t-body);color:var(--link);list-style:none}
.rail-fold>summary::-webkit-details-marker{display:none}
.rail-fold>summary::after{content:"";width:9px;height:9px;border-right:1.5px solid currentColor;
  border-bottom:1.5px solid currentColor;transform:rotate(45deg) translate(-2px,-2px)}
.rail-fold[open]>summary::after{transform:rotate(225deg) translate(-1px,-1px)}
.rail-fold>summary:focus-visible{outline:3px solid var(--focus);outline-offset:3px}
.rail-fold .rail-blurb{margin-top:var(--sp3)}

/* Spotlight: the club's ongoing work, the fields the cohort works in, and the
   centre head. All three are the ruled rail this site already uses for a list
   of named things; none of them is a new device. */
/* The live page's own arrangement: one dark panel showing a single project at
   a time, and the next session on Accent Land beside it. */
.spot-activities-band{padding-top:0}
.spot-activities-grid{display:grid;gap:0;grid-template-columns:1fr}
@media(min-width:900px){
  .spot-activities-grid{grid-template-columns:minmax(0,1.6fr) minmax(0,1fr)}
}
.spot-activity-panel{position:relative;background:var(--black);color:var(--white);
  padding:var(--sp6);display:grid;grid-template-rows:1fr auto;min-height:270px}
.spot-activity{grid-row:1;grid-column:1;text-align:center;align-self:center;
  opacity:0;visibility:hidden;transition:opacity .35s ease}
.spot-activity.is-current{opacity:1;visibility:visible}
.no-js .spot-activity,.spot-activity-panel.is-static .spot-activity{opacity:1;
  visibility:visible;grid-row:auto;padding-bottom:var(--sp5)}
.spot-activity-label{margin:0 0 var(--sp2);font-size:var(--t-body);color:var(--sea)}
.spot-activity h3{margin:0 0 var(--sp3);font-size:var(--t-h3);font-style:italic;color:var(--white)}
.spot-activity p{margin:0 auto;max-width:52ch;font-size:var(--t-body);color:var(--white)}
.spot-activity-dots{grid-row:2;grid-column:1;justify-self:center;display:flex;
  gap:var(--sp2);margin:0;padding-top:var(--sp5)}
.spot-activity-dots button{width:12px;height:12px;padding:0;border:0;border-radius:50%;
  background:var(--grey-4);cursor:pointer}
.spot-activity-dots button:focus-visible{outline:3px solid var(--white);outline-offset:3px}
.spot-activity-dots button.is-current{background:var(--sea)}
.spot-sessions{background:var(--accent-land);color:var(--black);padding:var(--sp6)}
.spot-sessions-label{margin:0 0 var(--sp3);font-size:var(--t-body)}
.spot-sessions h3{margin:0 0 var(--sp2);font-size:var(--t-lg);color:var(--black)}
.spot-sessions-when{margin:0 0 var(--sp3);font-size:var(--t-body)}
.spot-sessions p{margin:0;font-size:var(--t-body);line-height:1.45}
.spot-talent-rail{margin-top:var(--sp7);padding-top:var(--sp5);
  border-top:var(--line-thin) solid var(--grey-4)}
.spot-talent-rail>h3{margin:0 0 var(--sp4);font-size:var(--t-lg)}
.spot-talent-labels{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;
  gap:var(--sp3) var(--sp5)}
.spot-talent-labels li{font-size:var(--t-body);background:var(--sea);color:var(--black);
  border-radius:var(--r-ui);padding:var(--sp2) var(--sp3)}
.spot-head-profile .split{align-items:start}
@media(min-width:900px){
  .spot-head-profile .split{grid-template-columns:minmax(0,2fr) minmax(0,1fr)}
}
/* The portrait sat loose in the middle of its column with white on every side.
   It starts on the column now and takes the same frame the other photographs
   on this page take, so it reads as part of the set rather than a cut-out. */
.spot-head-figure{margin:0;justify-self:start}
.spot-head-figure img{display:block;width:177px;max-width:100%;height:auto;
  border-radius:var(--r-shape);background:var(--surface-alt)}

/* The community groups on the homepage. The live page sets the five out as one
   straight row in a single outlined frame, with the section's name as the first
   cell, and that arrangement is kept.

   The colour is where it changes. The live tiles are Primary Sea carrying white
   type, and Primary Sky, Primary Sea and Primary Land grounds all require black
   type: the accessibility chart decides this, not taste. Sea is also the right
   accent by meaning, since these groups are the programme's technology and
   innovation communities. Sentence case throughout, and 8 px corners, the
   radius the portal gives a small standalone shape.

   The row is the desktop arrangement. Below 1100 px it becomes three across,
   then two, then one, because five tiles in a line on a phone would each be
   too narrow to hold their own name. */
/* No frame and no band of its own. The section carries the same white ground as
   the hero above it and runs straight into the dark vision band below, so the
   five tiles are the only thing that changes colour and the page reads as one
   surface rather than three stacked slabs. Without a frame there is nothing to
   inset the heading, so it starts on the content column like every other. */
.club-band{display:grid;gap:var(--sp4);grid-template-columns:1fr;
  margin:0 0 var(--sp4)}
@media(min-width:1100px){
  .club-band{grid-template-columns:minmax(190px,240px) 1fr;align-items:center;
    gap:var(--sp5)}
}
.club-band-label{margin:0;font-size:var(--t-body);line-height:1.25;
  letter-spacing:normal}
/* The link is the section's last line, so its own trailing margin would sit on
   top of the section's padding and read as a second, larger gap. */
.home-community .wrap>p:last-child{margin-bottom:0}
/* A rail of five names needs less room around it than a section of copy. */
@media(min-width:1024px){.home-community{padding:var(--sp7) 0}}
.club-band-tiles{list-style:none;margin:0;padding:0;display:grid;gap:var(--sp3);
  grid-template-columns:1fr}
@media(min-width:560px){.club-band-tiles{grid-template-columns:repeat(2,1fr)}}
@media(min-width:860px){.club-band-tiles{grid-template-columns:repeat(3,1fr)}}
@media(min-width:1100px){.club-band-tiles{grid-template-columns:repeat(5,1fr)}}
.club-band-tiles li{display:flex;align-items:center;justify-content:center;
  text-align:center;background:var(--sea);color:var(--black);
  border-radius:var(--r-shape);padding:var(--sp4) var(--sp3);min-height:132px;
  font-size:var(--t-body);line-height:1.35}

/* ---------------------------------------------------------------------------
   The programme journey. One section: what the programme is, the picture of it
   happening, and the five markers of what it has done. The markers used to be a
   section of their own, repeating the introduction a screen further down.

   The journey rail opens on the same Cool Grey divider the framework uses at
   every other section entrance, so the two halves read as one story with a
   pause in it rather than as two unrelated blocks.
   --------------------------------------------------------------------------- */
/* The four figures sit beside the vision copy on its band, two by two, which
   is the live arrangement. Each is the band's own ground inside a Cool Grey 4 C
   hairline rather than a second fill: two solid grounds inside one band would
   put a colour on the page the palette does not carry. */
/* The live page stands the four figures in a single row. They read as one
   measure of the programme that way rather than as a block of four. */
.vision-figures{display:grid;gap:var(--sp3);grid-template-columns:repeat(2,1fr);
  align-content:center}
@media(min-width:1100px){.vision-figures{grid-template-columns:repeat(4,1fr)}}
@media(max-width:520px){.vision-figures{grid-template-columns:1fr}}
.vision-figure{border:var(--line-thin) solid var(--grey-4);border-radius:var(--r-shape);
  padding:var(--sp4) var(--sp3);text-align:center}
.vision-figure .muted{margin:var(--sp2) 0 0;color:var(--white)}
.home-vision .split{align-items:center}
@media(min-width:1100px){
  /* Four across needs the width, so the copy and the figures stack on this
     band rather than sitting side by side as a two-column split. */
  .home-vision .split{display:block}
  .home-vision .vision-figures{margin-top:var(--sp6)}
}
/* The band was set on the same generous rhythm as a page of body copy, which
   on two paragraphs reads as gaps rather than as spacing. */
.home-vision p{margin:0 0 var(--sp3)}
.home-vision h2{margin-bottom:var(--sp4)}
@media(min-width:1024px){.home-vision{padding:var(--sp7) 0}}
/* "Use the black logo against the lightest colours and the white logo against
   the darkest." The official horizontal vector is painted rather than redrawn,
   so the letterforms are Hexagon's own and only the colour is stated. Its
   clear space is built into the artwork, and 174 px clears both the 120 px
   digital minimum and this project's own 150 px floor. */
.vision-sponsor{margin:var(--sp5) 0 0}
.hexagon-mark{display:block;width:174px;height:49px;background:var(--white);
  -webkit-mask:url("/static/brand/hexagon-logo.svg") no-repeat center/contain;
  mask:url("/static/brand/hexagon-logo.svg") no-repeat center/contain}

/* The five markers, on the same band. One photograph each, with the marker's
   own words across the bottom of it, which is the live arrangement.

   The live captions are white on translucent teal; Primary Sea takes black type
   and never white, so the bar is solid Sea with black type. Solid also keeps
   the words off the photograph itself, which the portal restricts to areas of
   texture and negative space. The card is one rounded shape with the picture
   clipped inside it, so the corner radius belongs to the card and cannot cut
   the first letter of a caption the way the old figure frame did. */
.vision-journey{margin-top:var(--sp6)}
.vision-journey>h3{margin:0 0 var(--sp4);max-width:34ch}
.milestone-cards{list-style:none;margin:0 0 var(--sp4);padding:0;display:grid;
  gap:var(--sp3);grid-template-columns:1fr}
@media(min-width:600px){.milestone-cards{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1100px){.milestone-cards{grid-template-columns:repeat(5,minmax(0,1fr))}}
/* The caption bar takes the marker's own accent, chosen by what the marker is
   about rather than by its position in the row: Sky for the programme itself,
   its structure and its progression, Land for students and achievement. Colour
   selection is by meaning, and this is the site's one colour convention. Both
   grounds take black type, which the chart requires of either. */
.milestone-cards li{display:flex;flex-direction:column;min-width:0;overflow:hidden;
  border-radius:var(--r-shape);background:var(--sea)}
.milestone-cards li.accent-sky{background:var(--sky)}
.milestone-cards li.accent-land{background:var(--land)}
.milestone-cards li.accent-sea{background:var(--sea)}
/* Written through `body.is-public main` because the page scale is declared at
   that specificity; a plainer `.milestone-cards h3` is outranked and does
   nothing. This is a caption on a picture, not a heading in a column: at five
   across the tile is about 250px wide, and at the title size the words ran to
   three and four lines and took the eye off the photograph above them. */
body.is-public main .milestone-cards h3{font-size:var(--t-body);line-height:1.35}
/* A squarer frame and a crop taken to the people in each picture. At 4:3 with
   a centred crop these five carried ceiling, empty desk and blank wall, which
   is the negative space the photography rule asks to be composed out rather
   than framed in. Each position below is set from the photograph it names. */
.milestone-shot{display:block;position:relative;aspect-ratio:5/4;overflow:hidden}
.milestone-shot img{width:100%;height:100%;object-fit:cover;display:block;
  transform:scale(1.08)}
/* Read off each photograph: 1 was framing the floor and the camera rig, 3 was
   framing the ceiling. A higher percentage keeps the lower part of the picture,
   which is where the people are in every one of these five. */
.milestone-cards li:nth-child(1) .milestone-shot img{object-position:40% 44%}
.milestone-cards li:nth-child(2) .milestone-shot img{object-position:center 56%}
.milestone-cards li:nth-child(3) .milestone-shot img{object-position:center 78%}
.milestone-cards li:nth-child(4) .milestone-shot img{object-position:60% 50%}
.milestone-cards li:nth-child(5) .milestone-shot img{object-position:center 46%}
.milestone-cards h3{margin:0;flex:1;display:flex;align-items:center;
  justify-content:center;text-align:center;color:var(--black);font-weight:400;
  font-size:var(--t-body);line-height:1.35;padding:var(--sp3) var(--sp2)}
.vision-journey>p:last-child{margin-bottom:0}
@media(max-width:1099px) and (min-width:600px){
  .milestone-cards li:nth-child(5){grid-column:1/-1}
  .milestone-cards li:nth-child(5) .milestone-shot{aspect-ratio:16/6}
}
.journey-rail{margin-top:var(--sp8);padding-top:var(--sp6);
  border-top:var(--line-thin) solid var(--line)}
.journey-rail>h3{margin:0;max-width:34ch}
.journey-rail .timeline-home{margin-bottom:var(--sp5)}
.journey-rail>p:last-child{margin-bottom:0}

/* The innovation section's media slot carries the programme's own published
   cohort video. It keeps the same shape and the same rounded frame the
   photograph it replaced had. */
.home-innovation-video .video-frame{border-radius:var(--r-shape) 0 var(--r-shape) var(--r-shape);overflow:hidden;
  border:0}
.home-institutions .provisional{max-width:62ch}
.home-school-cohort:not(.band-green){background:var(--white)}

/* ---------------------------------------------------------------------------
   Homepage certification course cards. The three courses are the learner
   progression, so each one carries a graphic cover rather than a photograph:
   a solid Hexagon Dark Blue ground, thin Cool Grey precision lines and one
   connected slanted composition whose thick, round-ended stroke is the human
   line. Accent colour marks the step, never decorates it. Square editorial
   geometry, a light border, no lift, no tilt and no image zoom; hover and
   keyboard focus move the slanted line and extend the arrow only, and the
   reduced-motion rule at the foot of this file stills both.
   --------------------------------------------------------------------------- */
.course-card{position:relative;display:flex;flex-direction:column;min-width:0;
  border:1px solid var(--line);border-radius:var(--r-shape);overflow:hidden;
  background:var(--white);transition:border-color .3s ease}
.course-card:hover,.course-card:focus-within{border-color:var(--navy)}
.course-card-1{--course-accent:var(--accent-land)}
.course-card-2{--course-accent:var(--sky)}
.course-card-3{--course-accent:var(--sea)}

.course-cover{position:relative;overflow:hidden;min-height:224px;
  background:var(--surface-inverse);color:var(--text-inverse);isolation:isolate}
/* Two vertical precision lines at the thirds, one horizontal across them. */
.course-cover-grid{position:absolute;top:0;bottom:0;left:33.3%;right:33.3%;z-index:1;
  border-left:var(--line-thin) solid var(--line);border-right:var(--line-thin) solid var(--line);
  opacity:.24}
.course-cover-grid::before{content:"";position:absolute;top:36%;left:-100%;right:-100%;
  height:var(--line-thin);background:var(--line)}
/* One junction, two strokes: the thin precision line and the thick human line
   leave the same point at the cover's right edge. */
.course-cover-lines{position:absolute;right:0;top:66%;z-index:2;width:0;height:0;
  transition:transform .45s cubic-bezier(.22,.61,.36,1)}
.course-cover-lines::before,.course-cover-lines::after{content:"";position:absolute;
  right:0;bottom:0;transform-origin:100% 100%}
.course-cover-lines::before{width:270px;height:var(--line-thin);background:var(--line);
  transform:rotate(58deg)}
.course-cover-lines::after{width:150px;height:var(--line-thick);
  border-radius:var(--r-pill);background:var(--course-accent);transform:rotate(30deg)}
.course-card:hover .course-cover-lines,
.course-card:focus-within .course-cover-lines{transform:translateX(-14px)}

.course-number{position:absolute;top:var(--sp4);left:var(--sp4);z-index:3;
  font-size:var(--t-xs);color:var(--course-accent)}
.course-cover-copy{position:absolute;z-index:3;left:var(--sp4);right:var(--sp6);
  bottom:var(--sp4)}
.course-audience{margin:0 0 var(--sp2);font-size:var(--t-xs);
  color:var(--text-support-inverse)}
.course-cover h3{margin:0;font-size:var(--t-title);line-height:1.08;
  letter-spacing:normal;color:var(--text-inverse)}

.course-body{display:flex;flex:1;flex-direction:column;padding:var(--sp4);
  border-top:6px solid var(--course-accent)}
.course-summary{margin:0 0 var(--sp4);color:var(--text)}
.course-meta{margin:auto 0 0;padding-top:var(--sp3);border-top:var(--line-thin) solid var(--line);
  font-size:var(--t-sm);color:var(--text-support)}
.course-explore{display:flex;align-items:center;justify-content:space-between;
  gap:var(--sp3);margin-top:var(--sp3);color:var(--link);text-decoration:none}
.course-explore::after{content:"";position:absolute;inset:0}
.course-card:hover .course-explore,
.course-explore:focus-visible{text-decoration:underline}
.course-arrow{position:relative;flex:none;width:34px;height:var(--line-thin);
  background:var(--course-accent);transition:width .3s ease}
.course-arrow::after{content:"";position:absolute;right:0;top:-4px;width:8px;height:8px;
  border-top:var(--line-thin) solid var(--course-accent);
  border-right:var(--line-thin) solid var(--course-accent);transform:rotate(45deg)}
.course-card:hover .course-arrow,
.course-card:focus-within .course-arrow{width:48px}
@media(max-width:699px){
  .course-cover{min-height:196px}
  .course-cover-lines::before{width:200px}
  .course-cover-lines::after{width:118px}
}

.home-innovation-intro{align-items:start;margin-bottom:var(--sp7)}
.home-project-grid{display:grid;grid-template-columns:repeat(3,1fr);border-top:1px solid var(--line)}
.home-project-item{position:relative;padding:var(--sp5) var(--sp5) var(--sp5) 0;
  border-right:1px solid var(--line);min-height:260px}
.home-project-item+ .home-project-item{padding-left:var(--sp5)}
.home-project-item:last-child{border-right:0}
.home-project-item h3{margin:var(--sp2) var(--sp6) var(--sp3) 0}
.home-project-item h3 a{text-decoration:none;color:inherit}
.home-project-item h3 a::after{content:"";position:absolute;inset:0}
.home-project-item .project-arrow{position:absolute;right:var(--sp4);top:var(--sp5);
  font-size:var(--t-h3);line-height:1;transition:transform .5s cubic-bezier(.22,1,.36,1)}
.home-project-item:hover h3 a{text-decoration:underline}
.home-project-item:hover .project-arrow{transform:translateX(8px)}
.feedback-audiences{margin-top:var(--sp5);display:grid;grid-template-columns:repeat(3,1fr);
  border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.feedback-audience{position:relative;padding:var(--sp4) var(--sp6) var(--sp4) 0;
  border-right:1px solid var(--line)}
.feedback-audience+ .feedback-audience{padding-left:var(--sp4)}
.feedback-audience:last-child{border-right:0}
.feedback-audience h3,.feedback-audience p{margin:0}
.feedback-audience h3 a{text-decoration:none;color:inherit}
.feedback-audience h3 a::after{content:"";position:absolute;inset:0}
.feedback-audience>span{position:absolute;right:var(--sp4);top:var(--sp4);font-size:var(--t-h3)}
.feedback-audience:hover h3 a{text-decoration:underline}
@media(max-width:899px){
  .home-project-grid,.feedback-audiences{grid-template-columns:1fr}
  .home-project-item,.home-project-item+ .home-project-item,.feedback-audience,
  .feedback-audience+ .feedback-audience{padding:var(--sp4) var(--sp6) var(--sp4) 0;
    border-right:0;border-bottom:1px solid var(--line);min-height:0}
  .home-project-item:last-child,.feedback-audience:last-child{border-bottom:0}
}

/* The partner band's own rules live with the band, above. The dated pill went
   with the migration flags it carried. */

.lesson-body{max-width:72ch}
.lesson-body img{max-width:100%;height:auto;border-radius:var(--r-shape);
  margin:var(--sp4) 0;display:block}
.lesson-body h2{margin-top:var(--sp6)}
.lesson-body h3{margin-top:var(--sp5)}
.lesson-body ul,.lesson-body ol{padding-left:1.4em}
.lesson-body li{margin-bottom:var(--sp2)}
.lesson-body table{margin:var(--sp4) 0}

.stat-row{display:grid;gap:var(--sp3);grid-template-columns:repeat(auto-fit,minmax(140px,1fr))}
.stat{background:var(--surface-alt);border-radius:var(--r-shape);padding:var(--sp4);
  text-align:center}
.stat .v{font-size:var(--t-h3);line-height:1.1}
.gallery{display:grid;gap:var(--sp3);grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}
.gallery img{width:100%;aspect-ratio:4/3;object-fit:cover;border-radius:var(--r-shape);display:block}

/* ---------------------------------------------------------------------------
   The programme lockup. Supplied artwork, used as supplied: the clear space is
   built into the file, so nothing may sit inside the image box.
   --------------------------------------------------------------------------- */
.lockup{display:block;height:auto;max-width:100%}

/* ---------------------------------------------------------------------------
   Mobile navigation. Behaviour unchanged; only the surface is restyled.
   --------------------------------------------------------------------------- */
.nav-toggle{display:none;margin-left:auto;background:none;border:1px solid var(--line);
  border-radius:var(--r-ui);padding:9px 11px;cursor:pointer;color:var(--text);line-height:0}
.nav-toggle span{display:block;width:20px;height:2px;background:currentColor;margin:4px 0;
  border-radius:var(--r-pill);transition:transform .18s ease,opacity .18s ease}
.nav-toggle[aria-expanded="true"] span:nth-child(1){transform:translateY(6px) rotate(45deg)}
.nav-toggle[aria-expanded="true"] span:nth-child(2){opacity:0}
.nav-toggle[aria-expanded="true"] span:nth-child(3){transform:translateY(-6px) rotate(-45deg)}
@media(max-width:900px){
  .site-header .wrap{min-height:64px;flex-wrap:nowrap;gap:var(--sp3)}
  .js .nav-toggle{display:block}
  .js .site-nav{display:none}
  .js .site-nav.open{display:flex;position:absolute;left:0;right:0;top:100%;
    flex-direction:column;align-items:stretch;gap:0;background:var(--white);
    border-bottom:1px solid var(--line);box-shadow:0 12px 28px rgba(0,40,76,.14);
    padding:var(--sp2) 0;max-height:calc(100vh - 64px);overflow-y:auto}
  .js .site-nav.open a{padding:13px var(--sp4);border-bottom:1px solid var(--line-soft)}
  .js .site-nav.open a:last-child{border-bottom:0}
  .js .site-nav.open .btn{margin:var(--sp3) var(--sp4) var(--sp2);justify-content:center}
  .js .site-nav.open a.btn-primary{color:var(--white);border-bottom:0}
  .js .site-nav.open a.btn-secondary{color:var(--text);border-bottom:0}
  .site-header .wrap{position:relative}
}

/* ---------------------------------------------------------------------------
   Primers.
   --------------------------------------------------------------------------- */
.primer-head{background:var(--navy);color:var(--white);position:relative}
.primer-head .wrap{position:relative;z-index:2;padding:var(--sp6) var(--sp4) var(--sp5);
  max-width:760px}
.primer-head h1{color:var(--white);margin:var(--sp2) 0 var(--sp3)}
.primer-head .crumb{color:var(--accent-sea);font-size:var(--t-sm);margin:0}
.primer-head .crumb a{color:var(--accent-sea)}
.primer-meta{display:flex;flex-wrap:wrap;gap:var(--sp3);align-items:center;margin:0;
  font-size:var(--t-sm);color:var(--grey-4)}
.pill{background:var(--accent-land);color:var(--navy);border-radius:var(--r-pill);
  padding:3px 11px;font-size:var(--t-xs)}

.primer{font-size:var(--t-body)}
.primer-concepts{list-style:none;counter-reset:pc;padding:0;margin:var(--sp5) 0}
.primer-concepts li{counter-increment:pc;position:relative;
  border-left:1px solid var(--line);margin-left:14px;padding:0 0 var(--sp4) 30px}
.primer-concepts li::before{content:counter(pc);position:absolute;left:-15px;top:0;
  width:29px;height:29px;border-radius:50%;background:var(--sky-dark);color:var(--white);
  display:flex;align-items:center;justify-content:center;font-size:var(--t-sm)}
.primer-concepts li:last-child{border-left-color:transparent;padding-bottom:0}
.primer-concepts b{color:var(--sky-dark)}

.primer-figure{margin:var(--sp5) 0;padding:var(--sp4);background:var(--surface-alt);
  border-radius:var(--r-shape)}
.primer-figure img{width:100%;height:auto;display:block;border-radius:var(--r-ui);
  background:var(--white)}
.primer-figure figcaption{margin-top:var(--sp2);font-size:var(--t-sm);color:var(--text-support)}
.primer-example{margin:var(--sp5) 0;padding:var(--sp4) var(--sp5);background:var(--surface-alt);
  border-left:6px solid var(--sea);border-radius:0 var(--r-shape) var(--r-shape) 0}
.primer-example h3,.primer-relevance h3,.primer-takeaways h3{margin:0 0 var(--sp2);
  font-size:var(--t-body);color:var(--sky-dark)}
.primer-example p,.primer-relevance p{margin:0}
.primer-relevance{margin:var(--sp5) 0;padding-left:var(--sp4);border-left:6px solid var(--land)}
.primer-terms{margin:var(--sp4) 0;padding:var(--sp4) var(--sp5);border:1px solid var(--line);
  border-radius:var(--r-shape);font-size:var(--t-body)}
.primer-terms dt{font-weight:700;color:var(--text)}
.primer-terms dd{margin:0 0 var(--sp2)}
.primer-terms dd:last-child{margin-bottom:0}
.primer-takeaways{margin:var(--sp6) 0 0;padding:var(--sp5);border-radius:var(--r-shape);
  background:var(--navy);color:var(--white)}
.primer-takeaways h3{color:var(--accent-sea)}
.primer-takeaways ul{margin:0;padding-left:1.2em}
.primer-takeaways li{margin-bottom:var(--sp2)}
.primer-takeaways li:last-child{margin-bottom:0}
.primer-dated{margin-top:var(--sp4);padding:var(--sp3) var(--sp4);border:1px solid var(--line);
  border-radius:var(--r-ui);font-size:var(--t-sm);color:var(--text-support)}
.primer-actions{margin:var(--sp6) 0 var(--sp4);display:flex;gap:var(--sp3);
  align-items:center;flex-wrap:wrap}
.primer-nav{display:flex;justify-content:space-between;gap:var(--sp3);flex-wrap:wrap;
  padding-top:var(--sp4);border-top:1px solid var(--line);font-size:var(--t-body)}

/* ---------------------------------------------------------------------------
   Assessments.
   --------------------------------------------------------------------------- */
.note-soft{background:var(--surface-alt);border-left:6px solid var(--sea);
  padding:var(--sp3) var(--sp4);border-radius:0 var(--r-shape) var(--r-shape) 0;margin:var(--sp4) 0}
.quiz-form{margin-top:var(--sp5)}
.quiz-note{margin:var(--sp4) 0;color:var(--text-support)}
.quiz-q{border:1px solid var(--line);border-radius:var(--r-shape);padding:var(--sp5);
  margin:0 0 var(--sp4);background:var(--white)}
.quiz-q legend{display:flex;gap:var(--sp3);align-items:flex-start;padding:0;
  font-size:var(--t-body);line-height:1.4}
.quiz-n{flex:0 0 auto;width:28px;height:28px;border-radius:50%;background:var(--sky-dark);
  color:var(--white);display:inline-flex;align-items:center;justify-content:center;
  font-size:var(--t-sm)}
.quiz-hint{margin:var(--sp2) 0 0;font-size:var(--t-sm);color:var(--text-support)}
.quiz-opt{display:flex;gap:var(--sp3);align-items:flex-start;font-size:var(--t-body);
  padding:11px var(--sp3);border-radius:var(--r-ui);margin-top:var(--sp2);cursor:pointer}
.quiz-opt:hover{background:var(--surface-alt)}
/* The whole row is the label, so the target was already the full width. The
   control itself is brought to 24px as well, so the visible thing a learner
   aims at on a phone meets the minimum on its own. */
.quiz-opt input{margin-top:1px;flex:0 0 auto;width:24px;height:24px}

.score-bar{position:relative;height:var(--line-thick);border-radius:var(--r-pill);
  background:var(--grey-1);overflow:hidden;margin:var(--sp5) 0 var(--sp2)}
.score-fill{height:100%;border-radius:var(--r-pill)}
.score-fill.ok{background:var(--land)}
.score-fill.no{background:var(--grey-9)}
.score-mark{position:absolute;top:0;bottom:0;width:2px;background:var(--navy)}
.cert-issued{margin:var(--sp5) 0;padding:var(--sp6);border-radius:var(--r-shape);
  color:var(--white);background:var(--navy)}
.cert-issued h2{color:var(--accent-sea);margin:0 0 var(--sp2);font-size:var(--t-lg)}
.cert-issued p{margin:0 0 var(--sp3)}
.cert-number{font-family:var(--mono);font-size:var(--t-lg);letter-spacing:.04em;
  color:var(--accent-sea)}
.review-head{margin-top:var(--sp6);font-size:var(--t-body);color:var(--sky-dark)}
.quiz-review{list-style:none;padding:0;margin:var(--sp3) 0 0}
.quiz-review>li{border:1px solid var(--line);border-left-width:6px;
  border-radius:0 var(--r-shape) var(--r-shape) 0;padding:var(--sp5);margin-bottom:var(--sp3)}
.quiz-review>li.right{border-left-color:var(--land)}
.quiz-review>li.wrong{border-left-color:var(--alert)}
.quiz-review .qp{margin:0 0 var(--sp3);font-weight:700}
.qopts{list-style:none;padding:0;margin:0;font-size:var(--t-body)}
.qopts li{padding:6px 0;color:var(--text-support)}
.qopts li.correct{color:var(--text)}
.qopts li.chosen{background:var(--surface-alt);border-radius:var(--r-ui);
  padding-left:var(--sp3);padding-right:var(--sp3)}
.mark{font-size:var(--t-xs);margin-left:var(--sp2);padding:2px 9px;
  border-radius:var(--r-pill);background:var(--land);color:var(--navy)}
.mark.bad{background:var(--grey-1);color:var(--grey-11)}
.qfb{margin:var(--sp3) 0 0;padding-top:var(--sp3);border-top:1px solid var(--line-soft);
  font-size:var(--t-body);color:var(--text)}
/* A note about a legacy certificate. Ruled and square, like every other note
   on the public surface, rather than a rounded box with a coloured edge. */
.legacy-note{background:var(--surface-alt);border-left:2px solid var(--sea);
  padding:var(--sp3) var(--sp4);margin:var(--sp4) 0}

/* ---------------------------------------------------------------------------
   Spotlight, projects and evidence.
   --------------------------------------------------------------------------- */
/* The linked tile, and the lift it carried on hover, went with the tile. The
   ruled rail is what a linked record is now, and it moves a line rather than
   the container. */

.collab-kind{font-size:var(--t-sm);color:var(--sky-dark);margin:var(--sp5) 0 0}
.collab-kind:first-of-type{margin-top:var(--sp4)}
.disclose{margin-top:var(--sp6);border-top:1px solid var(--line);padding-top:var(--sp4)}
.disclose>summary{font-size:var(--t-body);cursor:pointer;padding:var(--sp2) 0;list-style:none;
  display:flex;align-items:center;gap:var(--sp2)}
.disclose>summary::-webkit-details-marker{display:none}
.disclose>summary::before{content:"+";display:inline-flex;align-items:center;
  justify-content:center;width:29px;height:29px;border-radius:50%;flex:0 0 auto;
  border:2px solid var(--sky-dark);color:var(--sky-dark);font-size:var(--t-lg);line-height:1}
.disclose[open]>summary::before{content:"–"}
.disclose .note{font-size:var(--t-body);color:var(--text-support);max-width:68ch;
  margin:var(--sp3) 0 var(--sp5)}

.evidence-grid{display:grid;gap:var(--sp4);grid-template-columns:repeat(2,1fr);align-items:start}
@media(min-width:700px){.evidence-grid{grid-template-columns:repeat(3,1fr)}}
@media(min-width:1024px){.evidence-grid{grid-template-columns:repeat(4,1fr)}}
.evidence{margin:0}
.evidence img{width:100%;height:auto;display:block;border-radius:var(--r-ui);
  background:var(--surface-alt)}
.evidence figcaption{font-size:var(--t-sm);line-height:1.4;margin-top:var(--sp2)}
.evidence-kind{display:block;font-size:var(--t-xs);color:var(--text-support);margin-top:2px}

.crumb{font-size:var(--t-sm);color:var(--text-support);margin:0 0 var(--sp3)}
.crumb a{color:inherit}
.crumb span{margin:0 6px}
.band-navy .crumb,.band-deep .crumb{color:var(--accent-sea)}
.steps{padding-left:var(--sp4);margin:0 0 var(--sp5)}
.steps li{margin-bottom:var(--sp2)}
.fact-rail{border-top:1px solid var(--line);padding-top:var(--sp5)}
@media(min-width:900px){.fact-rail{border-top:0;border-left:1px solid var(--line);
  padding:0 0 0 var(--sp5)}}
.rail-h{font-size:var(--t-sm);color:var(--sky-dark);margin:var(--sp5) 0 var(--sp2)}
.rail-h:first-child{margin-top:0}
.rail-list{list-style:none;padding:0;margin:0 0 var(--sp2)}
.rail-list li{padding:6px 0;border-bottom:1px solid var(--line-soft);font-size:var(--t-body)}

.resource{display:flex;flex-direction:column}
.resource .resource-kind{font-size:var(--t-sm);color:var(--sky-dark);margin:0 0 var(--sp1)}
.resource h3{margin:0 0 var(--sp2);font-size:var(--t-lg)}
.resource p:last-child{margin-top:auto;padding-top:var(--sp3);margin-bottom:0}

/* ---------------------------------------------------------------------------
   Spotlight.

   Everything here is scoped to `.spot`, the wrapper the Spotlight template puts
   around its own sections, so no other public page is affected. The grammar was
   measured on hexagon.com on 2026-08-19 and read against the Brand Portal's
   Layout construction page on the same day:

     - light editorial ground leads; one Cool Grey 1 C reference band and one
       Dark Blue emphasis band are the only departures from white;
     - Cool Grey 4 C divider lines carry the section framework and start at the
       fixed vertical margin line rather than crossing it;
     - the content column sits one full margin unit inside that line, so no line
       ever runs flush against copy;
     - information is set as ruled editorial rails, not as repeated boxes with
       detached accent bars;
     - an image that bleeds off the page keeps its square corners; an image that
       floats free keeps the radius guide.
   --------------------------------------------------------------------------- */

/* The content column is declared once, on `.wrap`, from the margin tokens. */
/* Spotlight sits on the same column as every other page; it no longer sets
   one of its own. */

/* The measured Hexagon scale this page introduced now serves the whole public
   surface, declared once above. Spotlight inherits it unchanged. */

/* Sections and the divider framework. Isolating each band keeps the fixed
   vertical margin line painting over the coloured grounds it crosses. */
.spot-band{position:relative;isolation:isolate}
.spot-band>.wrap{position:relative;z-index:2}
/* The live Spotlight runs tighter than this one did: 96 px above and below
   every section read as a gap between unrelated things rather than as one page.
   72 px on desktop, 56 px below it. */
.spot-section{padding:var(--sp7) 0}
@media(min-width:1024px){.spot-section{padding:var(--sp8) 0}}
.spot-club{padding:var(--sp7) 0}
@media(min-width:1024px){.spot-club{padding:var(--sp8) 0}}
.spot-section::before,.spot-club::before{content:"";position:absolute;top:0;left:0;right:0;
  height:var(--line-thin);background:var(--line);z-index:1}
@media(min-width:1200px){
  .spot-section::before,.spot-club::before{left:var(--sp7)}
}
.spot-head{margin-bottom:var(--sp6)}
.spot-head>:last-child{margin-bottom:0}

/* Hero. No photograph: the primary line tile carries it, drawn from one
   junction at the left of the tile and terminating on the page's right edge and
   on the divider below. */
.spot-hero{background:var(--surface);overflow:hidden;padding:var(--sp8) 0}
@media(min-width:1024px){.spot-hero{padding:var(--sp9) 0 var(--sp10)}}
.spot-hero-tile{bottom:0;width:min(40%,520px);height:300px}
.spot-hero-body>:last-child{margin-bottom:0}
.spot-hero .lede{max-width:46ch}

/* Transformative innovations. An editorial index: the category orders the eye,
   the title carries the link, and the whole ruled row is the click target. */
.spot-intro{display:grid;gap:var(--sp6);align-items:center}
@media(min-width:900px){.spot-intro{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--sp8)}}
.spot-intro-copy>:last-child{margin-bottom:0}
.spot-intro-copy .lede{max-width:46ch}
.spot-intro-figure{margin:0}

.spot-index{list-style:none;margin:var(--sp6) 0 0;padding:0;display:grid;
  border-top:var(--line-thin) solid var(--line)}
@media(min-width:900px){.spot-index{grid-template-columns:repeat(2,1fr)}}
.spot-index-item{position:relative;display:flex;flex-direction:column;
  padding:var(--sp4) 0;border-bottom:var(--line-thin) solid var(--line)}
@media(min-width:900px){
  .spot-index-item{padding:var(--sp4) 0}
  .spot-index-item:nth-child(odd){padding-right:var(--sp6);
    border-right:var(--line-thin) solid var(--line)}
  .spot-index-item:nth-child(even){padding-left:var(--sp6)}
}
/* The live page sets the category as a chip rather than a line of type. It is
   the same Primary Sea the talent labels take, with the black type that ground
   requires. */
.spot-index-cat{margin:0 0 var(--sp2);font-size:var(--t-xs);display:inline-block;
  align-self:flex-start;background:var(--sea);color:var(--black);
  border-radius:6px;padding:2px var(--sp2)}
.spot-index-item h3{font-size:var(--t-lg)}
.spot-index-blurb{font-size:var(--t-body);margin:0 0 var(--sp3)}
/* On the dark band every one of these has to be repainted: Primary Sky Dark is
   a light-ground colour and it disappears on Background Dark Blue. The rules
   and the hairlines go to Cool Grey 4 C for the same reason. */
.band-deep .spot-index-cat{background:var(--sea);color:var(--black)}
.band-deep .spot-index{border-color:var(--grey-4)}
.band-deep .spot-index-item{border-color:var(--grey-4)}
.band-deep .spot-index-item h3 a{color:var(--white)}
.band-deep .spot-index-blurb{color:var(--white)}
.band-deep .spot-index-more{color:var(--sea)}
.band-deep .spot-index-team{color:var(--grey-4)}
.band-deep .spot-talent-rail>h3{color:var(--white)}
.spot-index-item h3{margin:0 0 var(--sp3);max-width:24ch}
.spot-index-item h3 a{color:inherit;text-decoration:none}
.spot-index-item h3 a::after{content:"";position:absolute;inset:0}
.spot-index-item h3 a:focus-visible{outline:none}
.spot-index-item:has(a:focus-visible){outline:3px solid var(--focus);outline-offset:-3px}
.spot-index-blurb{margin:0 0 var(--sp5);color:var(--text-support);max-width:46ch}
.spot-index-foot{display:flex;flex-wrap:wrap;gap:var(--sp3);align-items:center;
  margin:auto 0 0;font-size:var(--t-sm)}
.spot-index-team{color:var(--text-support)}
.spot-index-more{margin-left:auto;display:inline-flex;align-items:center;gap:var(--sp3);
  color:var(--link)}
/* The arrow is a line that extends, not a glyph that jumps. */
.spot-arrow{position:relative;display:inline-block;flex:none;width:34px;
  height:var(--line-thin);background:var(--link);transition:width .3s ease}
.spot-arrow::after{content:"";position:absolute;right:0;top:-4px;width:8px;height:8px;
  border-top:var(--line-thin) solid var(--link);
  border-right:var(--line-thin) solid var(--link);transform:rotate(45deg)}
.spot-index-item:hover h3 a,.spot-index-item:focus-within h3 a{text-decoration:underline}
.spot-index-item:hover .spot-arrow,.spot-index-item:focus-within .spot-arrow{width:52px}

/* Partners in progress. A definition rail: what the collaboration is for on the
   left, the institutions ruled beside it, so seventeen names read as a record. */
.spot-collab{margin-top:var(--sp7);border-top:var(--line-thin) solid var(--line)}
.spot-collab-group{display:grid;gap:var(--sp2);padding:var(--sp5) 0;
  border-bottom:var(--line-thin) solid var(--line)}
@media(min-width:900px){
  .spot-collab-group{grid-template-columns:minmax(0,240px) minmax(0,1fr);gap:var(--sp7)}
}
.spot .spot-collab .collab-kind{margin:0;font-size:var(--t-sm);line-height:1.5;
  letter-spacing:normal;color:var(--sky-dark)}
.spot-collab-list{gap:0}
.spot-collab-list li{padding:var(--sp1) 0;border-bottom:0}
@media(min-width:700px){.spot-collab-list{grid-template-columns:repeat(2,1fr);gap:0 var(--sp7)}}
/* The last group already closes on a rule, so the disclosure does not draw a
   second parallel one a gap below it. */
.spot .disclose{margin-top:0;border-top:0;padding-top:var(--sp5)}

/* Moments from the community. The period leads the row so the chronology scans;
   the note that says why the entry is dated stays beside it, not under it. */
.spot-moments{list-style:none;margin:0;padding:0;
  border-top:var(--line-thin) solid var(--line)}
.spot-moment{display:grid;gap:var(--sp3);padding:var(--sp6) 0;
  border-bottom:var(--line-thin) solid var(--line)}
@media(min-width:900px){
  .spot-moment{grid-template-columns:minmax(0,240px) minmax(0,1fr);gap:var(--sp7)}
}
.spot-moment-period{margin:0;font-size:var(--t-lg);line-height:1.35}
.spot-moment-body h3{margin:0 0 var(--sp3)}
.spot-moment-body p{max-width:64ch}
.spot-moment-body>:last-child{margin-bottom:0}

/* The student club. The one purposeful Dark Blue band on this page. The
   photograph bleeds off the right edge, so square corners are the correct
   shape rather than a rounded tile floating inside the band. */
/* The band itself carries no padding: the copy column owns the vertical rhythm,
   so the photograph fills the band edge to edge instead of floating inside it. */
/* The club sits on the page's own ground now, as it does on the live page, and
   the people who run it are the picture. The photograph that used to bleed off
   the right edge is gone: the live page carries none here. */
.spot-club{overflow:hidden}
.spot-club-grid{display:block}
/* The photograph that used to fill the second column is gone, so the club is
   one column now: the words at their own measure, and the two groups of people
   side by side across the width beneath them. */
.spot-club-copy .lede,.spot-club-copy>p{max-width:64ch}
.spot-club-copy{position:relative;z-index:2}
.spot-club-copy .lede{max-width:46ch}
.spot-club-copy>:last-child{margin-bottom:0}
.spot-club-actions{display:flex;flex-wrap:wrap;gap:var(--sp3)}
.spot-club-people{margin:0}

/* Voices and moments. The words lead, the attribution follows, and the current
   status of the feedback recordings sits in the same rail rather than in a box
   that implies a recording is there to play. */
.spot-voices{display:grid;border-top:var(--line-thin) solid var(--line)}
@media(min-width:900px){.spot-voices{grid-template-columns:minmax(0,1.35fr) minmax(0,1fr)}}
.spot-voice{padding:var(--sp6) 0;border-bottom:var(--line-thin) solid var(--line)}
.spot-voice>:last-child{margin-bottom:0}
@media(min-width:900px){
  .spot-voice{padding-right:var(--sp7);border-right:var(--line-thin) solid var(--line)}
  .spot-voice-status{padding-right:0;padding-left:var(--sp7);border-right:0}
}
.spot-voice-words{margin:0 0 var(--sp5);padding:0;border:0;
  font-size:var(--t-title);line-height:1.35;letter-spacing:normal;
  color:var(--text);max-width:32ch}
.spot .spot-voice-name{margin:0 0 var(--sp1);font-size:var(--t-lg);line-height:1.35;
  letter-spacing:normal}
.spot-voice-role{margin:0;font-size:var(--t-body)}
.spot-voice-where{margin:0 0 var(--sp4);font-size:var(--t-body)}
.spot-voice-status h3{margin:0 0 var(--sp3)}
.spot-voice-status p{max-width:52ch}

/* Student talent profiles. The closing index, ruled rather than boxed. */
.spot-talent-list{list-style:none;margin:0;padding:0;display:grid;gap:0 var(--sp7)}
@media(min-width:700px){.spot-talent-list{grid-template-columns:repeat(2,1fr)}}
@media(min-width:1024px){.spot-talent-list{grid-template-columns:repeat(3,1fr)}}
.spot-talent-item{padding:var(--sp5) 0;border-top:var(--line-thin) solid var(--line)}
.spot .spot-talent-item h3{margin:0 0 var(--sp3);font-size:var(--t-lg);line-height:1.35;
  letter-spacing:normal}
.spot-talent-item p{margin:0;max-width:46ch}

@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important}
}

/* ---------------------------------------------------------------------------
   Signed-in screens: the learner's own area and the administration.

   These carry no marketing and no photography. They are working screens, so
   the rules are different from the public site: information sits close
   together, a row is a row, and the eye should be able to run down a column
   without the layout moving. Everything below uses the same tokens as the rest
   of the site, so it stays the same typeface, the same palette and the same
   spacing scale.
   --------------------------------------------------------------------------- */

/* Something the learner needs to know, said once, at the top. Not an error and
   not a success, so it takes the neutral sky rather than green or red. */
.notice{border:1px solid var(--sky);border-left:4px solid var(--sky);
  background:var(--grey-1);padding:var(--sp3) var(--sp4);border-radius:var(--r-sm);
  margin:0 0 var(--sp5);font-size:var(--t-body)}
.notice a{margin-left:var(--sp1)}

/* Where a learner left off. The single most useful thing on either screen, so
   it is stated in words and then repeated as the one prominent action. */
.up-next{margin:var(--sp2) 0 var(--sp2);color:var(--text-support)}
.up-next-bar{display:flex;align-items:center;justify-content:space-between;
  gap:var(--sp4);flex-wrap:wrap;border:1px solid var(--line);
  border-radius:var(--r-sm);padding:var(--sp3) var(--sp4);margin:0 0 var(--sp5)}
.quiet-link{margin-left:var(--sp3);font-size:var(--t-small)}

/* The state of an identity check, as a paragraph. It used to borrow `.state`,
   which is an inline chip built for the certificate page, and an inline-flex
   container squeezed two words into a column three lines deep. */
.status-note{border:1px solid var(--line);border-left:4px solid var(--grey-5);
  border-radius:var(--r-sm);padding:var(--sp3) var(--sp4);margin:0 0 var(--sp5)}
.status-note.is-ok{border-left-color:var(--pass)}
.status-note.is-stop{border-left-color:var(--fail)}
.status-note strong{display:block;margin-bottom:var(--sp1)}

/* Administration. A dense table, because the work is comparing rows. */
.admin-table{width:100%;border-collapse:collapse;font-size:var(--t-small)}
.admin-table th{text-align:left;color:var(--text-support);
  border-bottom:1px solid var(--line);padding:var(--sp2) var(--sp3);white-space:nowrap}
.admin-table td{padding:var(--sp2) var(--sp3);border-bottom:1px solid var(--grey-2);
  vertical-align:top}
/* A row carrying a status badge must not stand taller than one without, or the
   eye loses the rhythm running down the column. */
.admin-table .tag{padding:1px 10px;font-size:var(--t-small);line-height:1.35}
.admin-table tr:last-child td{border-bottom:0}
.admin-table .num{text-align:right;white-space:nowrap}
.admin-table .dim{color:var(--text-support)}
.admin-table.compare td:first-child{color:var(--text-support);width:9rem}

.admin-search{display:flex;gap:var(--sp2);align-items:center;flex-wrap:wrap;
  margin:0 0 var(--sp4)}
.admin-search .field-input{max-width:26rem;flex:1 1 18rem}

/* The four states, as filters. The count is part of the label, so an
   administrator can see the shape of the register without running a report.

   Square, not pills. A fully rounded end belongs to buttons, the brand lines,
   progress bars and one-off status badges; a row of five repeated labels is
   the thing the brand guidance tells us not to build. Underlined tabs also
   read better here, because the current one has to be obvious at a glance. */
.admin-filters{display:flex;gap:var(--sp4);flex-wrap:wrap;margin:0 0 var(--sp3);
  border-bottom:1px solid var(--line)}
.filter-tab{display:inline-block;padding:var(--sp2) 0;font-size:var(--t-small);
  text-decoration:none;color:var(--text-support);border-bottom:3px solid transparent;
  margin-bottom:-1px}
.filter-tab b{font-weight:700;margin-left:var(--sp1)}
.filter-tab:hover{color:var(--text)}
.filter-tab.is-current{color:var(--text);border-bottom-color:var(--sky)}

.admin-count{font-size:var(--t-small);color:var(--text-support);margin:0 0 var(--sp3)}
.admin-pager{display:flex;align-items:center;gap:var(--sp4);margin-top:var(--sp4);
  font-size:var(--t-small)}
.admin-range{display:flex;align-items:center;gap:var(--sp2);flex-wrap:wrap;
  margin:0 0 var(--sp4);font-size:var(--t-small)}
/* The base form rule is written with five :not() clauses, which outweighs a
   plain class, so these repeat them to win rather than reaching for
   !important. A date is eight characters and should occupy eight characters,
   not the width of the screen. */
.admin-range input[type=date]:not([type=checkbox]):not([type=radio]){
  padding:8px 10px;border:1px solid var(--line);border-radius:var(--r-sm);
  font:inherit;width:9.5rem}
.admin-range label{display:inline-block;margin-bottom:0;
  color:var(--text-support)}
.admin-search .field-input:not([type=checkbox]):not([type=radio]){
  max-width:26rem;flex:1 1 18rem;padding:10px 14px}
.id-attempt .reason:not([type=checkbox]):not([type=radio]){
  max-width:none;flex:1 1 22rem;width:auto;padding:8px 12px}

/* One attempt at an identity check, with what was typed beside what was read. */
.id-attempt{border:1px solid var(--line);border-radius:var(--r-sm);
  padding:var(--sp4);margin:0 0 var(--sp4)}
.id-attempt-head{display:flex;align-items:center;gap:var(--sp2);flex-wrap:wrap;
  margin:0 0 var(--sp2)}
.id-attempt .reason{max-width:none;flex:1 1 22rem}
.tag.pending{color:var(--sky-dark);border-color:var(--sky)}

/* The photograph a learner sent, shown back to them so they can tell whether
   the right one went. Small, because it is a check, not a gallery. */
.card-thumb{max-width:320px;width:100%;border:1px solid var(--line);
  border-radius:var(--r-sm);margin:var(--sp2) 0 0}

/* The administration's own menu. Five things in the order the work happens,
   then the settings, set back so they do not compete with them. */
.admin-nav{display:flex;align-items:baseline;gap:var(--sp4);flex-wrap:wrap;
  padding-bottom:var(--sp3);margin-bottom:var(--sp5);
  border-bottom:1px solid var(--line);font-size:var(--t-small)}
.admin-nav a{text-decoration:none;color:var(--text)}
.admin-nav a:hover{text-decoration:underline}
.admin-nav a.is-current{color:var(--sky-dark)}
.admin-nav-rest{display:flex;gap:var(--sp3);flex-wrap:wrap;margin-left:auto}
.admin-nav-rest a{color:var(--text-support)}
.nav-back{color:var(--text-support)}

/* A working screen's heading is a label, not a landing. The public hero is
   built to give a photograph and a brand line room to breathe, and inherited
   whole it left a band of empty white on every signed-in page before anything
   useful started. Here it is closed up and the decoration is dropped. */
.is-working .hero-compact{padding:var(--sp5) 0 var(--sp4)}
@media(min-width:1024px){.is-working .hero-compact{padding:var(--sp6) 0 var(--sp4)}}
.is-working .hero-compact .hero-shape,
.is-working .hero-compact-tile{display:none}
.is-working .hero-compact-body{max-width:60ch}
@media(min-width:1051px){.is-working .hero-compact-body{max-width:60ch}}
.is-working main>.wrap>section:first-child,
.is-working section.wrap{padding-top:var(--sp4)}

/* Cards in a row end level, whatever length the descriptions happen to be, so
   the buttons line up instead of stepping down the page. */
.is-working .grid .mcard{display:flex;flex-direction:column}
.is-working .grid .mcard .body{display:flex;flex-direction:column;flex:1}
.is-working .grid .mcard .body>form,
.is-working .grid .mcard .body>p:last-child{margin-top:auto}

/* Headings on a working screen need air above them and little below: they
   separate one block of work from the next rather than opening a page. */
.is-working section.wrap h2{margin-top:var(--sp6);margin-bottom:var(--sp3)}
.is-working section.wrap h2:first-child{margin-top:0}
.is-working .admin-table+h2,.is-working .curric+h2{margin-top:var(--sp6)}

/* A course the learner is already on is a row of work, not an advertisement.
   The picture is there to identify it, so it is capped rather than given the
   full sixteen-by-nine a marketing card wants. */
.is-working .mcard .shot{aspect-ratio:auto;max-height:132px}
.is-working .mcard .shot img{height:132px}

/* A table that is a short list, not a register. Left where the eye starts,
   rather than stretched across the screen with the number a hand-span from
   the name it belongs to. */
.admin-table.narrow{max-width:56rem}

/* The unfillable field. Moved off the page rather than hidden with display or
   visibility, both of which a script checks for before deciding whether to
   fill something in. Nothing here is a security control on its own; it is one
   of three layers in hexart/antibot.py. */
.nofill{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* A rating scale: one row, numbered, with both ends named, so a learner can see
   at a glance which end is which. It used to draw ten identical unlabelled
   buttons down the page. */
.quiz-scale{display:flex;align-items:center;gap:var(--sp2);flex-wrap:wrap;
  margin-top:var(--sp2)}
.quiz-scale-end{font-size:var(--t-small);color:var(--text-support);max-width:9rem}
.quiz-scale-point{display:inline-flex;flex-direction:column;align-items:center;
  gap:4px;font-size:var(--t-small);min-width:44px;cursor:pointer}
.quiz-scale-point input{margin:0}

/* The poster a video waits behind. It is a button rather than a picture with a
   handler bolted on, so it is reachable by keyboard and announced as something
   that can be pressed, which a div never is. */
.video-poster{position:absolute;inset:0;width:100%;height:100%;padding:0;
  border:0;background:var(--navy);cursor:pointer;display:block;overflow:hidden}
.video-poster img{width:100%;height:100%;object-fit:cover;display:block}
.video-poster:focus-visible{outline:3px solid var(--sky);outline-offset:-3px}

/* The mark that says this is a video. Drawn rather than an image file: one
   fewer request, and it stays sharp at any size. */
.video-play{position:absolute;left:50%;top:50%;width:76px;height:76px;
  margin:-38px 0 0 -38px;border-radius:50%;background:rgba(0,40,76,.82);
  border:2px solid #FFFFFF}
.video-play::after{content:"";position:absolute;left:50%;top:50%;
  margin:-13px 0 0 -8px;border-style:solid;border-width:13px 0 13px 22px;
  border-color:transparent transparent transparent #FFFFFF}
.video-poster:hover .video-play{background:var(--sky-dark)}

/* Contents for a page that runs to about twelve screens on a telephone. Ruled
   rather than boxed, because the page already carries more shapes than it
   needs, and wrapping rather than scrolling sideways. */
.spot-contents{display:flex;flex-wrap:wrap;gap:var(--sp2) var(--sp4);
  margin-top:var(--sp5);padding-top:var(--sp3);border-top:1px solid var(--line);
  font-size:var(--t-small)}
.spot-contents a{color:var(--sky-dark)}

/* An action that follows a long explanation is an action nobody can reach on a
   telephone without scrolling past everything first. These screens now carry
   it at the top as well; `.action-first` is the one at the top, and it is
   hidden on a wide screen where the whole page is visible at once. */
.action-first{margin:0 0 var(--sp5)}
@media(min-width:768px){.action-first{display:none}}

.form-length{font-size:var(--t-small);color:var(--text-support);
  margin:0 0 var(--sp4)}

/* Writing to one learner. Kept narrow, because a message to a person is prose
   and prose set the width of a table is unreadable. */
.write-box{max-width:52ch;margin-bottom:var(--sp6)}
.write-box textarea{width:100%;font:inherit;line-height:1.55}

/* The passcode page. The only page on the site that is the whole of what a
   visitor sees, so it sits in the middle of the window rather than at the top
   of a column, and it carries its own spacing: it had none at all, and
   inherited a page layout built for pages that scroll. */
.gate{display:flex;align-items:center;justify-content:center;
  min-height:calc(100vh - 340px);padding:var(--sp8) var(--sp4)}
/* `min` rather than a flat width: at 390px a 26rem card is wider than the
   screen, and the whole thing ran off the right edge. */
.gate-card{width:100%;max-width:min(26rem,100%);box-sizing:border-box}
.gate-card *{box-sizing:border-box}
.gate-card .eyebrow-line{display:block;margin-bottom:var(--sp2)}
.gate-card h1{margin:0 0 var(--sp3)}
.gate-card .lede{margin:0 0 var(--sp5);max-width:none}
.gate-card .field{margin-bottom:var(--sp4)}
.gate-card .field-input{width:100%}
.gate-card .btn{width:100%;justify-content:center}
.gate-wrong{margin:0 0 var(--sp4);padding:var(--sp2) var(--sp3);
  border-left:3px solid var(--fail);background:var(--grey-1);
  font-size:var(--t-small)}
.gate-foot{margin:var(--sp6) 0 0;padding-top:var(--sp4);
  border-top:1px solid var(--line);font-size:var(--t-small);
  color:var(--text-support)}

/* The line tile behind the heading belongs on a page somebody is reading, not
   on a door. */
.gate .hero-shape{display:none}

.site-footer-bare{padding:var(--sp5) 0}
.site-footer-bare p{margin:0;font-size:var(--t-small);max-width:52ch}
