/* ==================================================================
   Arcanté — one stylesheet, no external anything.

   3.7.0. Rewritten on a token system.

   The 3.6.0 sheet had grown to 26 distinct spacing values, 20 font
   sizes (five of them half-pixel) and 9 corner radii across 706 lines.
   Nothing was wrong with any single number; the problem was that there
   was no system, so every new screen invented its own. This file has
   eight spacing steps, seven type sizes and three radii, and a rule
   about colour:

     ACCENT (violet) means INTERACTIVE. A link, a chosen tab, a primary
     button, a focus ring. It never means "important" and it never
     means "category".

     GREEN / AMBER / RED mean STATE. Good, needs attention, wrong.
     They never decorate.

   Everything else is ink on paper: three ink weights, two rule
   weights, two surfaces. If a thing needs to stand out and is neither
   interactive nor a state, it stands out by weight, size or space —
   not by acquiring a colour or a box.

   Two constraints that are not negotiable, carried from 3.5.0:

     1. NO JAVASCRIPT. Arcanté sets script-src 'self' with no
        unsafe-inline and ships no script file. Disclosure is
        <details>/<summary>, natively.

     2. NOTHING SCROLLS SIDEWAYS. Wide tables reflow into cards below
        640px rather than growing a scrollbar.
   ================================================================== */

:root{
  /* ---- spacing: eight steps, each a meaningful jump ---- */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px;
  --s5:24px; --s6:32px; --s7:48px; --s8:64px;

  /* ---- type: seven sizes ---- */
  --t-xs:11px; --t-sm:13px; --t-base:15px; --t-md:17px;
  --t-lg:21px; --t-xl:27px; --t-2xl:34px;

  /* 3.9.7: the recorder's clock - read from across a studio, and the one
     display size in the product. Deliberately NOT an eighth --t- step:
     the type scale is seven sizes and this is a single object's size. */
  --clock:56px;

  /* ---- radii: three ---- */
  --r-sm:6px; --r-md:10px; --r-full:999px;

  /* ---- surfaces ---- */
  --bg:#faf8f6;          /* warm paper, carried from the 0.11.0 console */
  --surface:#ffffff;     /* a card, the header, a popover */
  --surface-2:#f4f0ed;   /* a well: inset, quieter than the page */

  /* ---- ink: three weights, and that is all ---- */
  --ink:#191517;         /* body text, headings */
  --ink-2:#615762;       /* secondary — labels, captions, supporting prose */
  --ink-3:#726b73;       /* tertiary — column heads, timestamps, hints.
                            Dark enough to clear 4.5:1 on --surface-2,
                            which is the worst ground it ever sits on. */

  /* ---- rules: two ---- */
  --line:#e6e0dc;        /* the ordinary divider */
  --line-2:#d0c7c2;      /* a stronger edge: form controls, table head */

  /* ---- accent. INTERACTIVE ONLY. ---- */
  --accent:#5b2a86;
  --accent-hover:#47206a;
  --accent-ink:#ffffff;
  --accent-wash:#f2ebfa;

  /* ---- state. STATE ONLY. ---- */
  --good:#1a6b43;  --good-wash:#e8f5ee;
  --attn:#8a5710;  --attn-wash:#fdf3e2;
  --prob:#96201f;  --prob-wash:#fbeaea;

  --lift:0 1px 2px rgba(25,21,23,.05);
  --lift-2:0 8px 28px rgba(25,21,23,.14);
  --focus:0 0 0 3px rgba(91,42,134,.28);
}

/* 3.9.69 — APPEARANCE. Simon, 19 Sep: "Light dark setting is not clear on
   iPad and phone for teacher user (Andrew)." There WAS no setting: the
   site simply followed the device, and a teacher whose iPad goes dark at
   dusk had no way to say otherwise. Now: Profile → Appearance offers
   Light, Dark, or Same as the device; the choice is saved to the account
   and written on <html data-theme="…">. The dark palette is declared
   once and applied two ways — by the device when nothing is chosen, and
   by the attribute when something is. */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --bg:#121013;
    --surface:#1a161a;
    --surface-2:#221d23;
    --ink:#f2eef1; --ink-2:#a9a0a7; --ink-3:#948b93;
    --line:#2c262e; --line-2:#3d3542;
    --accent:#b98fe0; --accent-hover:#cba9eb; --accent-ink:#1a0f28; --accent-wash:#241a30;
    --good:#6fd39d; --good-wash:#12261c;
    --attn:#e0b464; --attn-wash:#2a2113;
    --prob:#f08a8a; --prob-wash:#2a1616;
    --lift:0 1px 2px rgba(0,0,0,.4);
    --lift-2:0 8px 28px rgba(0,0,0,.5);
    --focus:0 0 0 3px rgba(185,143,224,.34);
  }
}
:root[data-theme="dark"]{
    --bg:#121013;
    --surface:#1a161a;
    --surface-2:#221d23;
    --ink:#f2eef1; --ink-2:#a9a0a7; --ink-3:#948b93;
    --line:#2c262e; --line-2:#3d3542;
    --accent:#b98fe0; --accent-hover:#cba9eb; --accent-ink:#1a0f28; --accent-wash:#241a30;
    --good:#6fd39d; --good-wash:#12261c;
    --attn:#e0b464; --attn-wash:#2a2113;
    --prob:#f08a8a; --prob-wash:#2a1616;
    --lift:0 1px 2px rgba(0,0,0,.4);
    --lift-2:0 8px 28px rgba(0,0,0,.5);
    --focus:0 0 0 3px rgba(185,143,224,.34);
}

/* ==================================================================
   base
   ================================================================== */
*{box-sizing:border-box}
html,body{margin:0;padding:0;max-width:100%;overflow-x:hidden}
body{
  background:var(--bg); color:var(--ink);
  font:var(--t-base)/1.6 'Avenir Next','Lato','Helvetica Neue',Helvetica,Arial,sans-serif;
  -webkit-font-smoothing:antialiased;
}
body.centred{display:flex;align-items:center;justify-content:center;min-height:100vh;padding:var(--s5)}
img,table{max-width:100%}

/* One focus treatment, everywhere, and it is always visible.
   :focus-visible rather than :focus so a mouse click on a button does
   not leave a ring behind it. */
a:focus-visible,button:focus-visible,summary:focus-visible,
input:focus-visible,select:focus-visible,textarea:focus-visible,
[tabindex]:focus-visible{
  outline:2px solid var(--accent);outline-offset:2px;border-radius:var(--r-sm);
}
input:focus,select:focus,textarea:focus{
  outline:2px solid var(--accent);outline-offset:0;border-color:var(--accent);
}

a{color:var(--accent)}
a:hover{color:var(--accent-hover)}

/* ---- headings ----
   h1 stays Georgia: it is the page's name and it should feel like a
   masthead. h2 and h3 do NOT. Georgia at 21px next to Avenir at 15px
   reads *lighter* than the body it introduces, which is exactly
   backwards, and it was why every screen felt like undifferentiated
   text. They become sans, 600, and slightly smaller. */
h1{font-family:Georgia,'Times New Roman',serif;font-weight:400;font-size:var(--t-xl);
   line-height:1.2;margin:0 0 var(--s1);letter-spacing:-.01em}
h2{font-size:var(--t-md);font-weight:600;line-height:1.3;margin:0 0 var(--s3);letter-spacing:-.005em}
h3{font-size:var(--t-base);font-weight:600;line-height:1.35;margin:0 0 var(--s2)}

p{margin:0 0 var(--s3)}
p:last-child{margin-bottom:0}

/* ---- the small utility vocabulary ---- */
.muted{color:var(--ink-2)}
.small{font-size:var(--t-sm)}
.fineprint{font-size:var(--t-sm);color:var(--ink-2);line-height:1.6;margin-top:var(--s3)}
.nowrap{white-space:nowrap}
.mid{text-align:center}
.empty{color:var(--ink-3);padding:var(--s5) 0}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.dim{opacity:.4}
.tight{padding-top:0}

/* An all-caps micro-label above a heading. Says what KIND of thing
   follows, so the heading itself does not have to. */
.eyebrow{
  display:block;font-size:var(--t-xs);font-weight:600;letter-spacing:.09em;
  text-transform:uppercase;color:var(--ink-3);margin:0 0 var(--s1);
}

/* Vertical rhythm as a container rather than a margin on every child.
   `.stack` is the answer to "why is there 22px here and 18px there". */
.stack > * + *{margin-top:var(--s5)}
.stack.close > * + *{margin-top:var(--s3)}

/* ==================================================================
   header
   ================================================================== */
.top{
  display:flex;align-items:center;gap:var(--s3) var(--s5);flex-wrap:wrap;
  padding:var(--s3) var(--s5);
  background:var(--surface);border-bottom:1px solid var(--line);
  position:relative;
}
.brand{font-family:Georgia,'Times New Roman',serif;font-size:var(--t-lg);flex:none}
.brand .a,.mark .a{color:var(--accent)}
a.brand{
  text-decoration:none;color:var(--ink);display:inline-block;
  border-radius:var(--r-sm);padding:var(--s1) var(--s2);margin-left:calc(var(--s2) * -1);
}
a.brand:hover{background:var(--accent-wash)}

/* ---- which school ----
   A disclosure even while there is one school, because Arcanté is
   multi-tenant and the control should exist before it is needed.
   Simon, 1 Sep 2026: "it also tells users without explicitly saying
   so that the system is designed for multiple schools." */
.tenant,details.tenant{
  position:relative;flex:none;display:flex;flex-direction:column;line-height:1.25;
  padding-left:var(--s4);border-left:1px solid var(--line);
}
details.tenant > summary{
  list-style:none;cursor:pointer;display:flex;flex-direction:column;line-height:1.25;
  border-radius:var(--r-sm);padding:var(--s1) var(--s2);margin-left:calc(var(--s2) * -1);
}
details.tenant > summary::-webkit-details-marker{display:none}
details.tenant > summary:hover{background:var(--accent-wash)}
.tenant .tlabel{
  font-size:var(--t-xs);letter-spacing:.09em;text-transform:uppercase;color:var(--ink-3);
}
.tenant .tname{font-size:var(--t-sm);font-weight:600}
details.tenant .tname{display:flex;align-items:center;gap:var(--s1)}
details.tenant .car{font-size:var(--t-xs);color:var(--ink-3);line-height:1}
details.tenant[open] .car{transform:rotate(180deg)}
.tenant-pop{
  position:absolute;z-index:30;top:calc(100% + var(--s2));left:var(--s2);min-width:250px;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  padding:var(--s3) var(--s4);box-shadow:var(--lift-2);
  font-size:var(--t-sm);line-height:1.5;
}
.tenant-pop .cur{font-weight:600;display:block;margin-bottom:var(--s1)}
.tenant-pop .why{color:var(--ink-2)}

/* ---- tabs ----
   3.9.4: four links and a menu, and the bar does not wrap (D-29). The
   wrap was the "fixed height" complaint - ten links for a superadmin
   folded onto a second row at ordinary widths, so the header was one
   height for a teacher and another for Simon. */
.tabs{display:flex;gap:var(--s1);flex-wrap:nowrap;align-items:center}
.tabs a{
  padding:var(--s2) var(--s3);border-radius:var(--r-sm);
  text-decoration:none;color:var(--ink-2);font-size:var(--t-sm);
  white-space:nowrap;
}
.tabs a:hover{background:var(--accent-wash);color:var(--accent)}
.tabs a.on{background:var(--accent);color:var(--accent-ink);font-weight:600}

/* ---- the Office menu ----
   The school's own work - To do, Enrolments, Workload, Accounts, Import,
   Activity - behind one disclosure, so the bar reads the same for
   everyone. Same construction as the school switcher: a <details>,
   because Arcanté ships no JavaScript and its CSP forbids handlers. */
details.office{position:relative;flex:none}
details.office > summary{
  list-style:none;cursor:pointer;display:flex;align-items:center;gap:var(--s1);
  padding:var(--s2) var(--s3);border-radius:var(--r-sm);
  color:var(--ink-2);font-size:var(--t-sm);white-space:nowrap;
}
details.office > summary::-webkit-details-marker{display:none}
/* C62 (3.9.5): Safari drew the default disclosure triangle before "Office"
   despite list-style:none - inline-flex on a <summary> re-enables it
   there. display:flex plus an empty ::marker removes it in every engine. */
details.office > summary::marker{content:''}
/* C63 (3.9.6): Firefox needs list-style:none ON EVERY summary as well as
   the ::marker rule, and the school switcher's summary had neither
   rule for Firefox. One rule for all disclosures, so the next <details>
   cannot bring the triangle back. */
summary{list-style:none}
summary::-webkit-details-marker{display:none}
summary::marker{content:'';display:none}
details.office > summary:hover{background:var(--accent-wash);color:var(--accent)}
details.office > summary.on{background:var(--accent);color:var(--accent-ink);font-weight:600}
details.office .car{font-size:var(--t-xs);line-height:1;color:currentColor}
details.office[open] .car{transform:rotate(180deg)}
.office-pop{
  position:absolute;z-index:30;top:calc(100% + var(--s2));left:0;min-width:200px;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  padding:var(--s2);box-shadow:var(--lift-2);
  display:flex;flex-direction:column;gap:1px;
}
.office-pop a{display:block}

/* The person in the HEADER. Scoped to .top (3.9.7): an unscoped .who
   also matched the register's `td class="who"`, which turned that cell
   into a flex box - the row's rule then stopped short of the marks and
   the line across the register was broken in two (Simon, 6 Sep). */
.top .who{margin-left:auto;display:flex;align-items:center;gap:var(--s2);font-size:var(--t-sm)}
.top .who .name{font-weight:600}
.top .who .role{color:var(--ink-3)}

/* ---- the menu ----
   The body is a SIBLING of the <details>, never a child. A closed
   <details> hides its own children with content-visibility on an
   internal slot, which `display:...!important` on the child does not
   override — the desktop header came up with no tabs at all. As a
   sibling it is ordinary markup, and the general sibling combinator
   does the reveal. Found by the browser pass. */
details.menu{position:relative;margin-left:auto}
details.menu > summary{
  list-style:none;cursor:pointer;display:inline-flex;flex-direction:column;
  justify-content:center;gap:var(--s1);
  min-width:44px;min-height:44px;align-items:center;
  padding:var(--s3);border:1px solid var(--line-2);border-radius:var(--r-sm);
}
details.menu > summary::-webkit-details-marker{display:none}
details.menu > summary:hover{border-color:var(--accent);background:var(--accent-wash)}
details.menu > summary i{display:block;width:18px;height:2px;background:var(--ink);border-radius:2px}
details.menu > summary .lbl{
  position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;
}

/* 3.9.6 (A7). One breakpoint, 1000px, chosen by measuring: the widest
   real header (a superadmin with a two-word surname, four tabs, Office,
   the avatar and the name) fits on one row from 1000px up with nothing
   wrapping; below that the hamburger takes over. Simon, 6 Sep 2026: the
   bar changed shape at the wrong moments as the window was dragged -
   between 861px and roughly 1000px the desktop bar was shown but the
   header wrapped to a second row. Above the breakpoint the header is
   nowrap, so it cannot. The browser suite measures it at 20px steps. */
@media (min-width:1000px){
  .top{flex-wrap:nowrap}
  details.menu{display:none}
  .menu-body{display:flex;align-items:center;gap:var(--s4);margin-left:auto;min-width:0}
  .menu-body .tabs{display:flex}
  .top .who{flex-wrap:nowrap;white-space:nowrap;min-width:0}
  .top .who a.me{min-width:0}
  .top .who .name{max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline-block;vertical-align:bottom}
  .top .who .role{white-space:nowrap}
}
@media (max-width:999px){
  .menu-body{
    display:none;
    position:absolute;z-index:30;top:calc(100% - 2px);right:var(--s3);min-width:236px;
    background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
    padding:var(--s2);box-shadow:var(--lift-2);
  }
  details.menu[open] ~ .menu-body{display:block}
  .menu-body .tabs{flex-direction:column;gap:1px;align-items:stretch}
  .menu-body .tabs a{padding:var(--s3);font-size:var(--t-base)}
  /* 3.9.4: inside the hamburger the Office group opens in place, as a
     labelled section of the same list, rather than as a floating pop. */
  details.office{width:100%}
  details.office > summary{padding:var(--s3);font-size:var(--t-base);width:100%}
  .office-pop{
    position:static;min-width:0;box-shadow:none;border:0;border-radius:0;
    padding:0 0 var(--s1) var(--s3);
  }
  .top .who{
    margin:var(--s2) 0 0;padding:var(--s3) var(--s3) var(--s1);
    border-top:1px solid var(--line);
    flex-direction:column;align-items:flex-start;gap:var(--s1);
  }
  .top .who form.inline{margin-top:var(--s1)}
  .top .who .linkish{padding:0}
}



/* ---- 3.9.5: the Schedule as a calendar (D-36) ----
   One article per day, soonest first, banded by term week. The day
   name is the link; the classes beneath are a compact list with the
   time in a fixed column so the eye runs straight down it. Red still
   means nobody is teaching it, and nothing else is coloured. */
.weekband{
  display:inline-block;margin:var(--s5) 0 var(--s2);
  padding:var(--s1) var(--s3);border-radius:var(--r-sm);
  background:var(--accent-wash);color:var(--accent);
  font-size:var(--t-xs);font-weight:600;letter-spacing:.08em;text-transform:uppercase;
}
.weekband:first-of-type{margin-top:var(--s3)}
.dayrow{
  display:grid;grid-template-columns:minmax(200px,240px) 1fr auto;gap:var(--s3) var(--s5);
  align-items:start;padding:var(--s4) 0;border-bottom:1px solid var(--line);
}
.dayrow:last-of-type{border-bottom:0}
.dayrow.today .dayname a{color:var(--accent)}
.dayname{font-family:Georgia,'Times New Roman',serif;font-weight:400;font-size:var(--t-md);
         line-height:1.3;margin:0;letter-spacing:-.005em}
.dayname a{color:var(--ink);text-decoration:none}
.dayname a:hover{color:var(--accent);text-decoration:underline}
.daysub{display:block;font-family:inherit;font-size:var(--t-xs);color:var(--ink-3);
        font-weight:400;margin-top:var(--s1);letter-spacing:0}
.daysub::first-letter{text-transform:uppercase}
.daycls{list-style:none;margin:0;padding:0}
/* 3.9.16 sizes the last column too. Who is teaching it is a name, or a
   name and a tag, or the word "nobody" — three different widths, and
   while the track was `auto` the class name beside it moved on every
   line. The whole reason the time sits in a fixed column is so the eye
   can run down it; the other two columns deserve the same. */
.daycls li{
  display:grid;grid-template-columns:104px minmax(0,1.4fr) minmax(0,1fr);gap:var(--s3);
  align-items:baseline;padding:var(--s1) 0;font-size:var(--t-sm);
}
.daycls li .t{color:var(--ink-2);font-variant-numeric:tabular-nums;white-space:nowrap}
.daycls li .l{font-weight:600}
.daycls li .l a{color:var(--ink);text-decoration:none}
.daycls li .l a:hover{color:var(--accent);text-decoration:underline}
.daycls li .w{color:var(--ink-2)}
.daycls li.mine .l::after{content:" · you";color:var(--accent);font-weight:400}
.dayact{align-self:center}
.dayact .btn{margin-top:0}
@media (max-width:860px){
  .dayrow{grid-template-columns:1fr auto}
  .daycls{grid-column:1 / -1}
  .dayact{grid-row:1;grid-column:2}
}
@media (max-width:640px){
  .dayrow{grid-template-columns:1fr;gap:var(--s2)}
  .dayact{grid-row:auto;grid-column:1;justify-self:start}
  .daycls li{grid-template-columns:96px 1fr;row-gap:2px}
  .daycls li .w{grid-column:2}
}


/* ---- 3.9.5: the register on a phone ----
   Five radio columns cannot fit in 375px; they ran off the right edge
   and the "added by name" tag folded into a vertical column beside the
   name (Simon, 5 Sep). Above 640px the table is unchanged and the pill
   text is for screen readers only. Below it, each learner is a block:
   name on one line, five labelled pills on the next, each a 40px target. */
table.register .mark{display:inline-flex;align-items:center;gap:var(--s2);cursor:pointer;font:inherit;margin:0}
table.register .mark input{margin:0;width:18px;height:18px;accent-color:var(--accent)}
table.register .mark .mk{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
table.register td.who .tag{margin-left:var(--s2)}
@media (max-width:640px){
  table.register,table.register tbody,table.register tr,table.register td{display:block;width:100%}
  table.register thead{display:none}
  table.register tr{padding:var(--s3) 0;border-bottom:1px solid var(--line)}
  table.register tr:last-child{border-bottom:0}
  table.register td{border:0;padding:0}
  table.register td.who{margin-bottom:var(--s2);font-weight:600}
  table.register td.who .tag{display:inline-block;margin-left:var(--s2);font-weight:600}
  table.register td.mid{display:inline-block;width:auto;margin:0 var(--s2) var(--s2) 0;text-align:left}
  table.register .mark{
    padding:var(--s2) var(--s3);min-height:40px;border:1px solid var(--line-2);
    border-radius:var(--r-full);background:var(--surface);font-size:var(--t-sm);color:var(--ink-2);
  }
  table.register .mark input{width:14px;height:14px}
  table.register .mark .mk{position:static;width:auto;height:auto;overflow:visible;clip:auto}
  table.register .mark:has(input:checked){border-color:var(--accent);background:var(--accent-wash);color:var(--accent);font-weight:600}
  /* the violins list: two wide buttons cannot share a row on a phone */
  .violins td.nowrap{white-space:normal}
  .violins td form.inline{display:flex;flex-direction:column;gap:var(--s2);align-items:stretch}
  .violins td form.inline .btn{width:100%;margin:0}
}

.weekband.quiet{background:var(--surface-2);color:var(--ink-3)}
/* Simon, 5 Sep 2026 (D-38): concerts and events are told apart from
   classes by colour. The one category colour in the system, chosen so it
   cannot be mistaken for a state or for the interactive violet. */
:root{--event:#0f6b6e;--event-wash:#e3f3f3}
@media (prefers-color-scheme: dark){:root:not([data-theme="light"]){--event:#6fd0d3;--event-wash:#112a2b}}
:root[data-theme="dark"]{--event:#6fd0d3;--event-wash:#112a2b}
.tag.event{background:var(--event-wash);color:var(--event)}
.daycls li.event .l a{color:var(--event)}
.daycls li.event .t{color:var(--event)}

/* ==================================================================
   3.9.5 — the Day page (D-36)
   ================================================================== */
.crumbs{margin:0 0 var(--s3);color:var(--ink-3)}
.crumbs a{text-decoration:none}
.crumbs a:hover{text-decoration:underline}
.rail{display:flex;flex-wrap:wrap;gap:var(--s2);margin:var(--s3) 0 var(--s2);list-style:none;padding:0}
.rail a{
  display:inline-flex;align-items:center;gap:var(--s2);
  padding:var(--s2) var(--s3);min-height:36px;
  border:1px solid var(--line-2);border-radius:var(--r-full);background:var(--surface);
  color:var(--ink-2);font-size:var(--t-sm);text-decoration:none;white-space:nowrap;
}
.rail a:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-wash)}
.rail a .n{
  display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;
  border-radius:var(--r-full);background:var(--accent-wash);color:var(--accent);
  font-size:var(--t-xs);font-weight:600;font-variant-numeric:tabular-nums;
}
.rail a.done{color:var(--ink-3)}
.rail a.done .n{background:var(--good);color:#fff}
.rail-note{margin:0 0 var(--s4)}
.stepcard{border-left:3px solid var(--accent)}
.daypanel{margin-top:var(--s5);padding-top:var(--s4);border-top:1px solid var(--line)}
.daypanel .pagehead{margin-bottom:var(--s3)}
.daypanel .pagehead h2{margin:0}
.daypanel .due{margin-top:0}
table.dayall td{vertical-align:middle}
@media (max-width:640px){
  .rail{gap:var(--s1)}
  .rail a{font-size:var(--t-xs);padding:var(--s1) var(--s2);min-height:32px}
  .rail a .n{width:18px;height:18px}
}

/* ==================================================================
   page frame
   ================================================================== */
main{max-width:1100px;margin:0 auto;padding:var(--s6) var(--s5) var(--s8)}

/* ---- one page header pattern ----
   Title, one line saying what the page is for, and the page's primary
   action on the right. Every screen. Before this, six screens started
   six different ways and none of them told you what you were looking
   at. */
.pagehead{
  display:flex;align-items:flex-end;justify-content:space-between;
  gap:var(--s4);flex-wrap:wrap;
  padding-bottom:var(--s4);margin-bottom:var(--s5);
  border-bottom:1px solid var(--line);
}
.pagehead .ph-text{flex:1 1 320px;min-width:0}
.pagehead .ph-text p{margin:var(--s1) 0 0;color:var(--ink-2);font-size:var(--t-sm);max-width:62ch}
.pagehead .ph-act{flex:none;display:flex;gap:var(--s2);flex-wrap:wrap;align-items:center}
.pagehead .ph-act .btn{margin-top:0}

/* A titled region inside a page, without drawing a box around it.
   Most of what used to be a .card is really just a band. */
.band{padding:var(--s5) 0;border-top:1px solid var(--line)}
.band:first-child{border-top:0;padding-top:0}
.band > h2{margin-bottom:var(--s3)}

/* ==================================================================
   cards
   A card is for something that is genuinely a separate object — a
   form, a panel that can be acted on, a sign-in box. It is not for
   "this text is important".
   ================================================================== */
.card{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  padding:var(--s5);margin:var(--s5) 0;box-shadow:var(--lift);
}
.card > h2:first-child,.card > h3:first-child{margin-top:0}
.card.narrow{max-width:430px;width:100%;margin:0}

/* 3.9.45 — Simon, 17 Sep: "one page instead of six." The register-and-
   report panel (_occurrence.php) still draws the same .card sections it
   always has — .card.teaching, .card.violins, .card.record and the rest
   keep every id, every class, every modifier style they had, because
   this changes nothing about what each one IS, only how the group of
   them sits on the page. .occpanel wraps that group (whichever of them
   actually render — a cancelled date draws only one) and turns the gaps
   between adjacent cards into a single hairline, under one shared
   shadow and one shared pair of rounded corners, so it reads as one
   page rather than a stack of boxes. */
.occpanel{margin:var(--s5) 0;box-shadow:var(--lift);border-radius:var(--r-md)}
.occpanel .card{margin:0;border-radius:0;box-shadow:none}
.occpanel .card:first-of-type{border-radius:var(--r-md) var(--r-md) 0 0}
.occpanel .card:last-of-type{border-radius:0 0 var(--r-md) var(--r-md)}
.occpanel .card + .card{border-top:0}

/* 3.9.51 — Simon, 17 Sep: "I need each class to be in ONE box." Every
   check on the MARKUP said this was already true — one wrapper, opened
   once and closed once, every card correctly nested inside it — and it
   was: the bug was never the nesting. .occpanel itself has never had a
   background of its own; only the .cards inside it do. Between "Who is
   teaching this" and "Class materials" sits one paragraph that is not a
   .card — "Report due by midnight…" — and with nowhere to get a
   background from, it showed the page's own colour straight through,
   splitting one continuous panel into two boxes with a visible gap,
   exactly at that paragraph. Same shape of bug as 3.9.46's .blocked
   seam, in a plainer element. Fixed at the wrapper rather than the one
   paragraph, so nothing dropped into .occpanel directly (now or later)
   can ever show the page through it again: it shares the same surface
   as the cards, and a direct-child paragraph gets the cards' own side
   padding so its text lines up with theirs instead of touching the
   panel's edge. */
.occpanel{background:var(--surface)}
.occpanel > p{margin:0;padding:var(--s4) var(--s5)}

/* 3.9.57 — Simon, 17 Sep, still: "borders still aren't right here" — after
   3.9.51 above had already fixed the GAP (the paragraph now shares the
   panel's background, so the page never shows through). What was left is
   a different fault in the same seam: a .card's own border-top has never
   been stripped when a plain <p> comes before it — every other neighbour
   a .card can have inside .occpanel already gets that (.card + .card,
   .blocked + .card, .pagehead + .card, all just above and below this
   rule) — so "Who is teaching this" ends in its own bottom border, then
   "Report due…" sits in its padding with no border of its own, then
   "Class materials" opens with ITS OWN top border: two hairlines close
   together where every other seam in this panel shows exactly one. Fixed
   the same way as its neighbours — the border that is stripped is the
   one on the element AFTER the paragraph, never the one before it. */
.occpanel > p + .card{border-top:0}

/* 3.9.46 — Simon, 17 Sep: the loose end named in the 3.9.45 note itself.
   The "N still to mark" warning (.blocked) is not a .card, so when it
   sits between two cards inside .occpanel — before you start, then the
   warning, then Register — the seam on either side of it showed a
   visible border and a square corner instead of the panel's usual
   hairline. Scoped strictly to .occpanel: every other .blocked in the
   app ("That did not save" and the rest, on a dozen other pages) is
   completely untouched — same border, same background, same radius,
   same margin they've always had. */
.occpanel .blocked{margin:0;border-radius:0}
.occpanel .card + .blocked{border-top:0}
.occpanel .blocked + .card{border-top:0}

/* 3.9.52 — Simon, 17 Sep, pointing at the exact spot: "the register and
   report header section is still above the white box, not in it." The
   per-class title bar (_occurrence.php's <header class="pagehead">) is
   now the first element inside .occpanel (moved there in that file;
   nothing about the header itself changed). .pagehead is used all over
   the app as a plain, unboxed title with a bottom rule, so this is
   scoped strictly to one sitting directly inside .occpanel: everywhere
   else keeps the exact spacing and border it has always had. Here it
   gets the panel's own surface (transparent, so 3.9.51's background
   shows through), the cards' own side padding, and the panel's top
   corners, since it is now the top of the box; its own border-bottom is
   kept on purpose as the divider before whichever card comes first, so
   the seam still reads as one continuous rule rather than a doubled
   line — matching border-top:0 on the .card right after it, the same
   way two adjacent .cards already avoid a doubled border between them. */
.occpanel > .pagehead{
  margin:0;padding:var(--s5) var(--s5) var(--s4);
  background:transparent;border-bottom:1px solid var(--line);
  border-radius:var(--r-md) var(--r-md) 0 0;
}
.occpanel > .pagehead + .card{border-top:0}
.occpanel > .pagehead ~ .card:first-of-type{border-top-left-radius:0;border-top-right-radius:0}
.mark{font-family:Georgia,serif;font-size:var(--t-2xl);font-weight:400;
      margin:0 0 var(--s1);text-align:center}
.sub{
  text-align:center;font-size:var(--t-xs);letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink-2);margin:0 0 var(--s5);
}
.signin-tenant{
  text-align:center;font-size:var(--t-sm);color:var(--ink-2);margin:calc(var(--s1) * -1) 0 var(--s4);
}
.signin-tenant strong{color:var(--ink)}

/* ==================================================================
   forms
   ================================================================== */
label{display:block;font-size:var(--t-sm);color:var(--ink-2);margin:var(--s4) 0 var(--s1)}
label.check{
  display:flex;gap:var(--s2);align-items:flex-start;
  color:var(--ink);font-size:var(--t-base);margin:var(--s2) 0;
  min-height:24px;
}
label.check input{margin-top:4px;flex:none;width:18px;height:18px}
input[type=text],input[type=email],input[type=password],input[type=search],input[type=tel],
input[type=date],input[type=number],select,textarea{
  width:100%;padding:var(--s2) var(--s3);
  border:1px solid var(--line-2);border-radius:var(--r-sm);
  background:var(--surface);color:var(--ink);font:inherit;font-size:var(--t-base);
  min-height:40px;
}
textarea{resize:vertical;min-height:72px;line-height:1.55}
fieldset{border:1px solid var(--line);border-radius:var(--r-md);
         padding:var(--s3) var(--s4) var(--s4);margin:var(--s5) 0}
legend{padding:0 var(--s1);font-size:var(--t-sm);color:var(--ink-2)}
fieldset.content legend{font-weight:600;color:var(--ink)}
.row{display:flex;gap:var(--s3);align-items:flex-end;flex-wrap:wrap;margin-top:var(--s4)}
.row label{margin-bottom:var(--s1)}
.row > div{display:flex;flex-direction:column}
.row label{margin-top:0}
.row .grow{flex:1 1 220px;min-width:0}
form.inline{display:inline}
.checkgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:0 var(--s5)}
.checkgrid label.check{margin:var(--s1) 0}

/* ==================================================================
   buttons
   One primary per screen region. Everything else is secondary, and
   secondary is a bordered surface — not a second violet.
   ================================================================== */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s2);
  padding:var(--s2) var(--s4);min-height:40px;
  border:1px solid var(--line-2);border-radius:var(--r-sm);
  background:var(--surface);color:var(--ink);
  font:inherit;font-size:var(--t-sm);font-weight:500;
  text-decoration:none;cursor:pointer;margin-top:var(--s4);
  transition:border-color .12s,background-color .12s;
}
.btn:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-wash)}
.btn.primary{
  background:var(--accent);color:var(--accent-ink);border-color:var(--accent);font-weight:600;
}
.btn.primary:hover{background:var(--accent-hover);border-color:var(--accent-hover);color:var(--accent-ink)}
.btn.small{margin-top:0;padding:var(--s1) var(--s3);min-height:32px;font-size:var(--t-sm)}
/* 3.9.5 — a button's top margin belongs to the layout around it, not to
   the button. Inside a table cell, an inline form or a page header the
   margin pushed the control below its row's baseline, which read as
   uneven spacing everywhere buttons sat beside text (Simon, 5 Sep). */
td .btn,form.inline .btn,.pagehead .btn,.crumbs .btn,.rail .btn{margin-top:0}
.btn[disabled],.btn.off{opacity:.5;cursor:default}
.linkish{
  background:none;border:0;color:var(--accent);font:inherit;font-size:var(--t-sm);
  cursor:pointer;padding:var(--s1) var(--s2);text-decoration:underline;border-radius:var(--r-sm);
}
.linkish:hover{color:var(--accent-hover)}

/* A row of buttons where only one can be on is a select wearing a
   costume — except where the choices are few, where a segmented
   control is quicker to hit and reads at a glance. */
.seg{display:inline-flex;flex-wrap:wrap;border:1px solid var(--line-2);
     border-radius:var(--r-sm);overflow:hidden}
.seg .btn,.seg button{
  margin:0;border:0;border-right:1px solid var(--line);border-radius:0;
  padding:var(--s2) var(--s3);min-height:36px;font-size:var(--t-sm);
  background:var(--surface);color:var(--ink-2);
}
.seg > *:last-child{border-right:0}
.seg .btn:hover,.seg button:hover{background:var(--accent-wash);color:var(--accent)}
.seg .btn.primary,.seg button.primary{
  background:var(--accent);color:var(--accent-ink);font-weight:600;
}
.seg button:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;position:relative;z-index:1}
.seg .n{
  display:inline-block;margin-left:var(--s1);padding:0 var(--s1);border-radius:var(--r-full);
  background:var(--surface-2);color:var(--ink-2);font-size:var(--t-xs);
  font-variant-numeric:tabular-nums;
}
.seg .btn.primary .n,.seg button.primary .n{background:rgba(255,255,255,.22);color:var(--accent-ink)}

/* The tri-state availability control. The one place a state colour is
   allowed on a button, because the button IS the state. */
.seg.tri button{padding:var(--s1) var(--s3);font-size:var(--t-sm)}
.seg.tri button.yes.primary{background:var(--good);border-color:var(--good);color:#fff}
.seg.tri button.maybe.primary{background:var(--attn);border-color:var(--attn);color:#fff}
.seg.tri button.no.primary{background:var(--prob);border-color:var(--prob);color:#fff}
.unanswered{font-size:var(--t-xs);color:var(--attn);display:block;margin-top:var(--s1)}
/* 3.9.3 — the row you just answered. The list no longer re-sorts on a
   click, so this only has to say WHICH row moved under your answer, not
   compensate for it having jumped. Left border only: colour here is
   state, not decoration. */
.cards tr.justdone > td{background:var(--accent-wash)}
.cards tr.justdone > td:first-child{box-shadow:inset 3px 0 0 var(--accent)}

/* ==================================================================
   toolbar — one row, replacing three rows of buttons
   Simon, 1 Sep 2026: "the selections are really useful, but they're
   way too big and take up way too much space."
   ================================================================== */
.toolbar{
  display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;
  padding:var(--s2) var(--s3);margin:0 0 var(--s4);
  border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface);
}
.toolbar form.inline{display:inline-flex;align-items:center;gap:var(--s2)}
.toolbar .btn,.toolbar select,.toolbar input{margin-top:0}
.toolbar select,.toolbar input[type=text],.toolbar input[type=search]{
  width:auto;padding:var(--s1) var(--s2);min-height:36px;font-size:var(--t-sm);
}
.toolbar input[type=search]{min-width:150px}
.toolbar .count{
  margin-left:auto;font-size:var(--t-sm);color:var(--ink-3);
  font-variant-numeric:tabular-nums;white-space:nowrap;
}
.toolbar .sep{width:1px;align-self:stretch;background:var(--line);margin:0 var(--s1)}

/* The old .filters block, now matching the toolbar rather than
   inventing its own padding and radius. */
.filters{
  display:flex;align-items:flex-end;gap:var(--s3);flex-wrap:wrap;
  padding:var(--s3);margin:0 0 var(--s4);
  border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface);
}
.filters label{font-size:var(--t-xs);color:var(--ink-3);display:block;margin:0 0 var(--s1);
               letter-spacing:.06em;text-transform:uppercase;font-weight:600}
.filters input,.filters select{padding:var(--s1) var(--s2);font:inherit;font-size:var(--t-sm);min-height:36px}

.viewnav{display:flex;gap:var(--s2);flex-wrap:wrap;align-items:center;margin:0 0 var(--s4)}
.viewnav .btn{margin-top:0}
.viewnav form.inline{display:flex;gap:var(--s2)}
.viewnav .tag{margin-left:var(--s1)}

.weeknav{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;margin:0 0 var(--s3)}
.weeknav .range{color:var(--ink-2);font-size:var(--t-sm)}
.weeknav .btn{margin-top:0}

/* ==================================================================
   messages and tags
   ================================================================== */
.flash{
  padding:var(--s3) var(--s4);border-radius:var(--r-sm);font-size:var(--t-sm);
  margin:0 0 var(--s4);border-left:3px solid transparent;
}
.flash.ok{background:var(--good-wash);color:var(--good);border-left-color:var(--good)}
.flash.warn{background:var(--attn-wash);color:var(--attn);border-left-color:var(--attn)}
.flash.bad{background:var(--prob-wash);color:var(--prob);border-left-color:var(--prob)}

.tag{
  display:inline-block;padding:2px var(--s2);border-radius:var(--r-full);
  font-size:var(--t-xs);font-weight:600;letter-spacing:.02em;vertical-align:middle;
  background:var(--surface-2);color:var(--ink-2);
}
.tag.ok{background:var(--good-wash);color:var(--good)}
.tag.warn{background:var(--attn-wash);color:var(--attn)}
.tag.bad{background:var(--prob-wash);color:var(--prob)}
.tag.off{background:var(--surface-2);color:var(--ink-3)}

/* ==================================================================
   tables
   One treatment. Head is quiet and small; the data is the loud part.
   ================================================================== */
.tblwrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
/* 3.9.68 — .tablewrap was a second spelling of the same thing, used on the
   Day page and Staff this day, and it had NO rule at all: those tables did
   not even scroll sideways, they simply ran off the screen. Both spellings
   now behave, so a table can never be unreachable because of which word
   somebody typed. The markup uses .tblwrap; this keeps the other safe. */
.tablewrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
table{border-collapse:collapse;width:100%;font-size:var(--t-sm)}
th,td{text-align:left;padding:var(--s2) var(--s3);border-bottom:1px solid var(--line);
      vertical-align:top}
th{
  font-size:var(--t-xs);text-transform:uppercase;letter-spacing:.07em;
  color:var(--ink-3);font-weight:600;
  border-bottom:1px solid var(--line-2);white-space:nowrap;
}
tbody tr:hover{background:var(--surface-2)}
table.register td{vertical-align:middle}
table.register input[type=radio]{width:20px;height:20px}
tr.decision{background:var(--accent-wash)}
tr.mine{background:var(--accent-wash)}
tr.mine:hover{background:var(--accent-wash)}
tr.offerrow td{border-bottom:1px solid var(--line);padding-top:0;color:var(--ink-2)}
tr.offerrow .btn{margin-top:0;padding:var(--s1) var(--s3);min-height:30px;font-size:var(--t-sm)}
tr.offerrow:hover{background:transparent}

/* key/value block on a person */
table.kv{width:auto;font-size:var(--t-sm)}
table.kv th{
  text-align:left;font-weight:600;color:var(--ink-3);text-transform:uppercase;
  letter-spacing:.06em;font-size:var(--t-xs);
  padding:var(--s1) var(--s5) var(--s1) 0;white-space:nowrap;vertical-align:top;
  border-bottom:0;
}
table.kv td{padding:var(--s1) 0;border-bottom:0;color:var(--ink)}

.balance{font-variant-numeric:tabular-nums;font-weight:600}
.balance .of{color:var(--ink-3);font-weight:400}
.due{font-size:var(--t-sm);color:var(--ink-2)}
.due strong{color:var(--ink)}
.late{color:var(--prob);font-weight:600}

.w-num{width:64px}
.w-reason{width:150px;max-width:100%}
.col-share{width:34%}

/* ==================================================================
   dashboard tiles
   A number and what it means. Each one is a link to the screen that
   does something about it — a tile you cannot act on is decoration.
   ================================================================== */
.tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(158px,1fr));
       gap:var(--s3);margin:0 0 var(--s5)}
.tile{
  display:flex;flex-direction:column;gap:2px;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  padding:var(--s4);text-decoration:none;color:var(--ink);box-shadow:var(--lift);
  transition:border-color .12s,transform .12s;
}
.tile:hover{border-color:var(--accent);color:var(--ink)}
.tile .n{font-family:Georgia,serif;font-size:var(--t-xl);line-height:1.1;
         font-variant-numeric:tabular-nums}
.tile .l{font-size:var(--t-sm);color:var(--ink-2);line-height:1.35}
.tile.ok   .n{color:var(--good)}
.tile.warn .n{color:var(--attn)}
.tile.bad  .n{color:var(--prob)}
.tile.off  .n{color:var(--ink-3)}

/* ==================================================================
   sessions and slots
   ================================================================== */
.sessions{list-style:none;padding:0;margin:0}
.session{
  display:flex;gap:var(--s5);flex-wrap:wrap;align-items:flex-start;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  padding:var(--s4);margin-bottom:var(--s2);box-shadow:var(--lift);
}
.session .when{min-width:150px}
.session .date{display:block;font-weight:600}
.session .time{color:var(--ink-2);font-size:var(--t-sm)}
.session .what{flex:1;min-width:210px}
.session .level{font-weight:600;margin-right:var(--s1)}
.session .where{color:var(--ink-2);font-size:var(--t-sm);margin-top:2px}
.session .note{color:var(--accent);font-size:var(--t-sm);margin-top:var(--s1)}
.session .act .btn{margin-top:0}

.slot{
  display:flex;gap:var(--s5);flex-wrap:wrap;align-items:center;
  border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface);
  padding:var(--s3) var(--s4);margin-bottom:var(--s2);
}
.slot-when{min-width:150px;line-height:1.35}
.slot-what{flex:1;min-width:220px}
.slot-what .tag{margin-left:var(--s1)}
.slot-state{min-width:120px}
.slot-go .btn{margin-top:0}

.daycard{margin:0 0 var(--s5)}
.daycard h2{border-bottom:1px solid var(--line);padding-bottom:var(--s2)}

.namelist,.picklist{list-style:none;padding:0;margin:var(--s3) 0}
.namelist li{padding:var(--s1) 0;border-bottom:1px solid var(--line);font-size:var(--t-sm)}
.picklist li{padding:0;border-bottom:1px solid var(--line)}
.picklist a{display:block;padding:var(--s3) var(--s1);text-decoration:none;color:var(--ink);
            min-height:44px}
.picklist a:hover{background:var(--accent-wash);color:var(--accent)}

.tokenbox{
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--t-sm);
  background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:var(--s3);word-break:break-all;
}

/* Something that cannot be done yet, and why. A state, so it takes a
   state colour — but a left rule rather than a full tinted box, so it
   does not shout louder than the thing it is about. */
.blocked{
  border:1px solid var(--line);border-left:3px solid var(--prob);
  background:var(--prob-wash);border-radius:var(--r-sm);
  padding:var(--s3) var(--s4);margin:0 0 var(--s4);
}
.blocked h3{margin:0 0 var(--s1);font-size:var(--t-base);font-weight:600;color:var(--prob)}

/* ==================================================================
   schedule
   The schedule table is long; every row costs a term.
   Simon, 1 Sep 2026: "the schedule page is nicely laid out but it
   takes up way too much space." A term is a hundred rows. Anything
   spent per row is spent a hundred times.
   ================================================================== */
table.sched td{padding:var(--s1) var(--s2);vertical-align:middle}
table.sched th{padding:var(--s1) var(--s2)}
table.sched td.when{white-space:nowrap;line-height:1.35}
table.sched td.when .t{display:block;color:var(--ink-2);font-size:var(--t-xs)}
table.sched .btn.small{margin-top:0;padding:var(--s1) var(--s2);min-height:30px;font-size:var(--t-xs)}
table.sched .seatalt{margin-top:2px}
table.sched .seatalt button{
  background:none;border:0;padding:0;font:inherit;font-size:var(--t-xs);
  color:var(--ink-2);text-decoration:underline;cursor:pointer;
}
table.sched .seatalt button:hover{color:var(--accent)}
table.sched tr.offerrow td{padding-top:0;padding-bottom:var(--s1)}

/* Week bands. The columns this needs — term_week, iso_week_no — have
   been on class_occurrence since 001. Nothing new had to be stored. */
tr.weekband td{
  background:var(--surface-2);border-bottom:1px solid var(--line-2);
  padding:var(--s2) var(--s3);font-size:var(--t-xs);font-weight:600;
  letter-spacing:.07em;text-transform:uppercase;color:var(--ink-2);
}
tr.weekband:hover td{background:var(--surface-2)}
tr.weekband .wk-sub{font-weight:400;color:var(--ink-3);letter-spacing:0;text-transform:none}
tr.weekband.half td{background:var(--attn-wash);color:var(--attn)}
tr.weekband.half:hover td{background:var(--attn-wash)}

/* The staffing cell. C44's neighbour: a select and two buttons inside
   one nowrap cell overflowed it and collided with whatever sat
   alongside. */
td.seatcell{white-space:normal;min-width:150px}
/* form.inline{display:inline} is 0,1,1 and was beating a bare .seat at
   0,1,0, so the Save button wrapped onto its own line and every
   schedule row was twice as tall as it needed to be. Match it. */
form.inline.seat,.seat{display:flex;gap:var(--s1);align-items:center;flex-wrap:nowrap}
.seat select{
  flex:1 1 auto;min-width:0;width:auto;max-width:170px;
  padding:var(--s1) var(--s1);min-height:32px;font-size:var(--t-sm);border-radius:var(--r-sm);
}
.seat .btn{margin-top:0;flex:none}
.seatnote{display:block;font-size:var(--t-xs);color:var(--ink-3);margin-top:2px}

/* Violins to hand out before the class. A state, so amber. */
.card.violins{border-color:var(--attn);border-left:3px solid var(--attn);background:var(--attn-wash)}
.card.violins h2{color:var(--attn)}
.card.violins table,.card.violins td{background:transparent}
.card.violins tbody tr:hover{background:transparent}
.card.violins .btn{margin-top:0;margin-right:var(--s1)}

/* ==================================================================
   workload bars
   Solid = hours delivered, tint = hours still to come. Two tones
   rather than two bars, because the question is "how much, and how
   much of it has already happened".
   ================================================================== */
.bar{background:var(--surface-2);border-radius:var(--r-full);height:10px;
     overflow:hidden;min-width:120px}
.bar-fill{display:block;height:100%;background:var(--accent-wash)}
.bar-done{display:block;height:100%;background:var(--accent)}

/* Widths that used to be inline (3.5.0, C45). `style-src 'self'`
   forbids a style attribute as firmly as it forbids an inline script,
   and the browser drops it in silence — the workload bars had been
   rendering at zero width on every screen since the CSP was added. A
   computed width cannot be a class name, so it is rounded to the
   nearest 5%; the exact figure is printed beside the bar in words. */
.pw0{width:0%}    .pw5{width:5%}    .pw10{width:10%}  .pw15{width:15%}
.pw20{width:20%}  .pw25{width:25%}  .pw30{width:30%}  .pw35{width:35%}
.pw40{width:40%}  .pw45{width:45%}  .pw50{width:50%}  .pw55{width:55%}
.pw60{width:60%}  .pw65{width:65%}  .pw70{width:70%}  .pw75{width:75%}
.pw80{width:80%}  .pw85{width:85%}  .pw90{width:90%}  .pw95{width:95%}
.pw100{width:100%}

.adjust{display:flex;gap:var(--s1);align-items:center;flex-wrap:nowrap}
.adjust input{padding:var(--s1) var(--s2);min-height:32px;font-size:var(--t-sm)}
.adjust .btn{margin-top:0;padding:var(--s1) var(--s3);min-height:32px;font-size:var(--t-sm)}

/* ==================================================================
   a person
   The learner page used to be a thirteen-row property table where
   every row weighed the same, so "Grade 7 as a teenager, targeting
   grade 6" sat at exactly the weight of "City". It is now a briefing:
   who they are, where they stand and why, then what they told us,
   then the reference fields behind a disclosure.
   ================================================================== */
.person{display:flex;align-items:baseline;gap:var(--s3);flex-wrap:wrap}
.person .ref{font-size:var(--t-sm);color:var(--ink-3);font-variant-numeric:tabular-nums}
.person-state{
  display:flex;align-items:baseline;gap:var(--s2);flex-wrap:wrap;
  margin-top:var(--s2);
}
.person-why{color:var(--ink-2);font-size:var(--t-sm)}

/* What we know, in prose, above the reference data. */
.brief{
  font-size:var(--t-md);line-height:1.55;color:var(--ink);
  max-width:66ch;margin:0 0 var(--s4);
}
.brief .q{display:block;font-size:var(--t-xs);letter-spacing:.07em;text-transform:uppercase;
          color:var(--ink-3);font-weight:600;margin-bottom:2px}

/* The reference fields, as a wrapping list rather than a table. */
.facts{display:flex;flex-wrap:wrap;gap:var(--s3) var(--s6);margin:0;padding:0;list-style:none}
.fact{min-width:120px}
/* 3.9.13 — WHY THIS IS TWO SELECTORS AND NOT ONE.
   Feedback rendered "WhoSimon Hewitt Jones", "Version3.9.10", "Emailedyes,
   to support@nomisere.com". Nothing was missing from the markup: the
   label and the value were there, adjacent, and both were inline
   elements with no rule between them, so the browser did the only thing
   it could and ran them together.

   The cause is that this block styled a label by its CLASS. The person
   page writes <span class="k">, so it worked there; Feedback and
   Enquiries write a bare <span> and a <b>, which are the obvious
   spelling of "label" and "value" and matched nothing at all. A
   convention only one of three screens knows about is not a convention.

   So the label and the value are now matched by their POSITION as well
   — first child and second child of a .fact — which is what they
   actually are. Any of the three spellings lays out correctly, and a
   fourth screen written next month cannot reintroduce this by picking
   the wrong tag. The .k/.v classes still work and no view had to
   change; they simply stopped being load-bearing. */
.fact .k,.fact > :first-child{display:block;font-size:var(--t-xs);letter-spacing:.07em;
         text-transform:uppercase;color:var(--ink-3);font-weight:600}
.fact .v,.fact > :first-child ~ *{display:block;font-size:var(--t-sm);color:var(--ink);
         font-weight:400;overflow-wrap:anywhere}

/* The one card on a person's page where a human makes the call. */
.card.outcome{border-left:3px solid var(--attn)}
.card.outcome h2{color:var(--attn)}

/* ==================================================================
   the contact timeline
   The centre of 3.6.0. One entry per interaction, newest first,
   because the question somebody has when they open a person's page is
   almost always "what happened last time".
   ================================================================== */
ol.timeline{list-style:none;padding:0;margin:var(--s4) 0 0}
ol.timeline li{
  display:flex;gap:var(--s4);padding:var(--s3) 0 var(--s3) var(--s3);
  border-left:2px solid var(--line);border-bottom:1px solid var(--line);
}
ol.timeline li:last-child{border-bottom:0;padding-bottom:0}
ol.timeline li.tl-in{border-left-color:var(--accent)}
ol.timeline li.tl-out{border-left-color:var(--line-2)}
ol.timeline li.tl-note{border-left-color:var(--line)}
ol.timeline li.owed{background:var(--attn-wash);border-left-color:var(--attn)}
.tl-when{flex:0 0 140px;font-size:var(--t-xs);line-height:1.5;color:var(--ink-3)}
.tl-when .d{display:block;font-weight:600;font-size:var(--t-sm);color:var(--ink)}
.tl-when .c{display:block;color:var(--ink-3)}
.tl-what{flex:1;min-width:0}
.tl-detail{margin-top:var(--s1);font-size:var(--t-sm);line-height:1.55;color:var(--ink-2)}
.tl-action{
  margin-top:var(--s2);padding:var(--s2) var(--s3);border-radius:var(--r-sm);
  background:var(--surface-2);font-size:var(--t-sm);
  display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap;
}
.tl-action .btn{margin-top:0;padding:var(--s1) var(--s2);min-height:30px;font-size:var(--t-xs)}
li.owed .tl-action{background:var(--surface)}

/* ==================================================================
   disclosures
   ================================================================== */
/* A disclosure that does not look like one gets ignored. */
details.explain{margin:calc(var(--s1) * -1) 0 var(--s3)}
details.explain > summary{
  cursor:pointer;font-size:var(--t-sm);color:var(--ink-2);list-style:none;
  display:inline-block;padding:var(--s1) var(--s2);margin-left:calc(var(--s2) * -1);
  border-radius:var(--r-sm);
}
details.explain > summary:hover{background:var(--accent-wash);color:var(--accent)}
details.explain > summary::before{content:"▸ ";color:var(--ink-3)}
details.explain[open] > summary::before{content:"▾ "}
details.explain > summary::-webkit-details-marker{display:none}
details.explain .fineprint{margin-top:var(--s1);max-width:76ch}

/* The two forms that write to the timeline. Both are disclosures,
   because the page is read far more often than it is written to. */
details.addcontact,details.addperson,details.changeask{margin:0}
details.addperson{margin:0 0 var(--s4)}
details.addcontact > summary,details.addperson > summary,details.changeask > summary{
  cursor:pointer;list-style:none;
  display:inline-flex;align-items:center;gap:var(--s2);
  font-size:var(--t-sm);font-weight:600;color:var(--accent);
  padding:var(--s2) var(--s3);min-height:40px;
  border:1px solid var(--line-2);border-radius:var(--r-sm);background:var(--surface);
}
details.addcontact > summary::-webkit-details-marker,
details.addperson > summary::-webkit-details-marker,
details.changeask > summary::-webkit-details-marker{display:none}
details.addcontact > summary::before,details.addperson > summary::before,
details.changeask > summary::before{content:"+";font-size:var(--t-md);line-height:1}
details.addcontact[open] > summary::before,details.addperson[open] > summary::before,
details.changeask[open] > summary::before{content:"–"}
details.addcontact > summary:hover,details.addperson > summary:hover,
details.changeask > summary:hover{
  border-color:var(--accent);background:var(--accent-wash);
}
details.addcontact form,details.addperson form,details.changeask form{margin-top:var(--s3)}
details.addperson form.card{margin:var(--s3) 0 0}

/* ==================================================================
   footer — provenance left, version right
   Simon, 30 Aug 2026: the version number belongs in the bottom right
   corner of every screen, so that a bug report can always say which
   build it came from without anybody having to go and look.
   ================================================================== */
.foot{
  max-width:1100px;margin:0 auto;padding:var(--s5);
  border-top:1px solid var(--line);color:var(--ink-3);font-size:var(--t-xs);
  display:flex;gap:var(--s5);flex-wrap:wrap;align-items:baseline;
}
/* 3.9.46 — Simon, 17 Sep: "the feedback button blocks the version
   number." The 30 Aug design intent above still holds — the version
   belongs in the bottom-right corner, visible without going to look for
   it — but 3.9.10's feedback button (.fb) is fixed to that exact same
   corner and sits on top of it once a page is scrolled to the bottom.
   Extra clearance under the footer, roughly the closed button's own
   height plus its gap from the edge, so the corner it's pinned to is
   never the one carrying the text. Harmless on the pages that don't
   draw a feedback button (feedback_panel() decides that per role) —
   just a little empty space at the foot of those. */
.foot{padding-bottom:64px}
.foot-l{flex:1;min-width:220px}
/* 3.9.6: the footer carries links now; a link is a target (WCAG 2.2, 24px). */
.foot a{display:inline-block;padding:var(--s2) var(--s1);margin:calc(var(--s2) * -1) 0}
.foot-r{margin-left:auto;text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
.foot-r .ver{font-weight:600;color:var(--ink-2)}

/* ==================================================================
   tables that become cards
   Every <td> in a table.cards carries data-label. Below 640px the
   head is taken away from sighted readers (but left for screen
   readers) and each row becomes a labelled block.
   ================================================================== */
@media (max-width:640px){
  table.cards thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
  table.cards,table.cards tbody{display:block}
  table.cards tr{
    display:block;border:1px solid var(--line);border-radius:var(--r-md);
    background:var(--surface);padding:var(--s3);margin-bottom:var(--s2);
  }
  table.cards tbody tr:hover{background:var(--surface)}
  table.cards td{
    display:flex;gap:var(--s3);align-items:baseline;
    border:0;padding:2px 0;white-space:normal;
  }
  table.cards td::before{
    content:attr(data-label);flex:0 0 88px;
    font-size:var(--t-xs);letter-spacing:.07em;text-transform:uppercase;color:var(--ink-3);
    font-weight:600;
  }
  table.cards td[data-label=""]::before{display:none}
  table.cards tr.weekband{
    padding:var(--s2) var(--s3);border:0;border-radius:var(--r-sm);
    margin:var(--s5) 0 var(--s2);background:var(--surface-2);
  }
  table.cards tr.weekband.half{background:var(--attn-wash)}
  table.cards tr.weekband td{display:block;padding:0}
  table.cards tr.weekband td::before{display:none}
  table.cards tr.weekband .wk-sub{display:block;margin-top:2px}
  td.seatcell{min-width:0}
  /* The seat cell holds two forms. As flex items they sat on one line
     and the second one ran off the right edge of the card. */
  table.cards td.seatcell{flex-wrap:wrap}
  table.cards td.seatcell .seatalt{flex:0 0 100%;margin-left:98px;margin-top:2px}
  table.cards td.seatcell .seat{flex:1 1 auto;min-width:0}
  /* The toolbar's dividers mean nothing once it has wrapped. */
  .toolbar .sep{display:none}

  /* 3.9.68 — THE MOBILE PASS. Simon, 19 Sep, from a phone while
     travelling: "some pages are not properly readable."

     A card cell is a flex row of label + content, and neither half could
     give way: a long tag, a select, or a form with two controls in it
     pushed the card wider than the screen, and the row scrolled sideways
     inside its wrapper — which on a phone means the last column simply
     cannot be reached. Three rules, in order of how much they give:
     content may wrap onto its own line under the label, nothing may be
     wider than the card, and a form inside a cell takes a line of its
     own and wraps inside itself. */
  table.cards td{flex-wrap:wrap}
  table.cards td > *{max-width:100%;min-width:0}
  table.cards td form{flex:1 1 100%;min-width:0;display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center}
  /* A form is often inside a <details> ("Edit this term"), which is then
     the flex item and was being squeezed to sixty pixels. */
  table.cards td details{flex:1 1 100%;min-width:0}
  table.cards td details form{display:block}
  table.cards td select,table.cards td input,table.cards td textarea{max-width:100%}
  /* A tag is a phrase, not a word: below this width it wraps rather than
     holding the whole card open. */
  table.cards td .tag{white-space:normal}

  /* 3.9.68 — a thumb is not a mouse pointer. The word-sized controls in a
     table cell ("Edit", "Suspend", "Setup link", "Remove") were 17 pixels
     high, which is half of what anybody can hit while walking. They keep
     their appearance and gain a target. */
  table.cards td .linkish,table.cards td a.small,table.cards td .btn.small{
    display:inline-flex;align-items:center;min-height:34px;
  }
  table.cards td .sep{display:none}
  /* An actions cell is right-aligned on a desk, where it is the last
     column. In a card it is a line of its own and reads from the left
     like everything above it. */
  table.cards td.acts{text-align:left;justify-content:flex-start}
}

/* 3.9.68 — the same stack for the "who teaches this" table wherever it is
   drawn. The rules below at 720px were written for the class panel and
   named .card.teaching in every selector, so the copy on the Day page kept
   four rigid columns and ran its Save button off the edge. */
@media (max-width:720px){
  table.teachnow,table.teachnow tbody,table.teachnow tr,
  table.teachnow th,table.teachnow td{display:block;width:auto}
  table.teachnow th{padding:var(--s3) 0 0}
  table.teachnow td.who{white-space:normal;padding:0 0 var(--s1)}
  table.teachnow td.act{display:flex;flex-wrap:wrap;gap:var(--s2);padding-bottom:var(--s3)}
  table.teachnow td.act select,table.teachnow td.act .btn,
  table.teachnow td.act .seat{max-width:100%}
  table.teachnow td.act .seat{flex-wrap:wrap}
}

/* ==================================================================
   everything else, by size
   ================================================================== */
@media (max-width:860px){
  main{padding:var(--s5) var(--s4) var(--s7)}
  h1{font-size:var(--t-lg)}
  .pagehead{padding-bottom:var(--s3);margin-bottom:var(--s4)}
}
@media (max-width:640px){
  /* 3.9.6: horizontal padding shrinks on a phone; vertical does not,
     so the header is one height at every phone width (D-35). */
  .top{padding:var(--s3) var(--s3);gap:var(--s3)}
  .brand{font-size:var(--t-md)}
  .tenant,details.tenant{padding-left:var(--s3)}
  details.tenant .tname{font-size:var(--t-sm)}
  .tenant-pop{left:auto;right:0;min-width:220px}
  .toolbar{gap:var(--s2);padding:var(--s2)}
  .toolbar .count{margin-left:0;width:100%;order:9}
  /* The filter form is one inline-flex row. On a phone its three
     controls were squeezed until the two selects read "ar" and "ar".
     They wrap and take a real share of the width instead. */
  .toolbar form.inline{flex-wrap:wrap;width:100%}
  .toolbar form.inline > *{flex:1 1 140px}
  .toolbar form.inline > .btn{flex:0 0 auto}
  .toolbar input[type=search]{min-width:0}
  .tiles{grid-template-columns:repeat(auto-fit,minmax(132px,1fr));gap:var(--s2)}
  .tile{padding:var(--s3)}
  .tile .n{font-size:var(--t-lg)}
  .card{padding:var(--s4);border-radius:var(--r-sm)}
  table.kv{width:100%}
  table.kv th{padding-right:var(--s3)}
  .checkgrid{grid-template-columns:1fr}
  .session{flex-direction:column;gap:var(--s2)}
  .session .act{width:100%}
  .session .act .btn{width:100%}
  .slot{flex-direction:column;align-items:stretch;gap:var(--s2)}
  .slot-go .btn{width:100%}
  .foot{flex-direction:column;gap:var(--s2)}
  .foot-r{margin-left:0;text-align:left}
  .adjust{flex-wrap:wrap}
  /* Turning the header into a column turns `flex:1 1 320px` on .ph-text
     into a 320px BASIS ON THE HEIGHT, which left a phone-sized hole
     between the title and the toolbar. Found by measuring the boxes,
     not by looking at them — 320px of nothing is easy to read as
     deliberate. */
  .pagehead{align-items:stretch;flex-direction:column;gap:var(--s3)}
  .pagehead .ph-text{flex:none;width:100%}
  .pagehead .ph-act{width:100%}

  /* Seven filter chips do not fit on a phone in one line, and a
     segmented control that runs off the edge is a control with items
     nobody can reach. It wraps, and the rows share the width. */
  .toolbar .seg{display:flex;width:100%}
  .toolbar .seg > *{flex:1 1 auto;justify-content:center}
  ol.timeline li{flex-direction:column;gap:var(--s1)}
  .tl-when{flex:none;display:flex;gap:var(--s2);flex-wrap:wrap;align-items:baseline}
  .tl-when .d,.tl-when .c{display:inline}
  .facts{gap:var(--s3) var(--s5)}
}
@media (max-width:420px){
  main{padding:var(--s4) var(--s3) var(--s6)}
  .top{padding:var(--s2) var(--s3)}
  .brand{font-size:var(--t-base)}
  .tenant .tlabel{display:none}
  .seg .btn,.seg button{padding:var(--s2)}
  .toolbar{width:100%}
  .toolbar form.inline,.toolbar .seg,.toolbar select{width:100%}
  .toolbar .seg{justify-content:stretch}
  .toolbar .seg > *{flex:1;text-align:center}
  .pagehead .ph-act .btn{flex:1 1 auto}
}

/* Very wide screens: the 1100px column is right for reading, but the
   schedule and the learner list are dense tables that earn more room. */
@media (min-width:1500px){
  main.wide,body.wide main{max-width:1440px}
  .foot{max-width:1440px}
}

/* Somebody who has asked for less movement gets less movement. */
@media (prefers-reduced-motion: reduce){
  *{transition:none !important;animation:none !important}
}

/* Somebody who has asked for more contrast gets stronger rules. */
@media (prefers-contrast: more){
  :root{--line:#b8afaa;--line-2:#8c8078;--ink-2:#463f45;--ink-3:#5f5760}
}

/* ==================================================================
   3.9.0 — import corrections, and the activity log

   Both screens are built out of components that already existed:
   .tiles/.tile for the counters, table.cards for the tables so they
   reflow instead of scrolling sideways, .toolbar/.seg for the filters,
   details.addcontact for the explanatory panel. Everything below is the
   handful of things those components could not already do.

   No new spacing values, no new type sizes, no new radii. If a rule
   here needs a number, it comes from a token.
   ================================================================== */

/* A tile whose value is a word rather than a number. Georgia at
   --t-xl is right for "34"; it is far too big for "content-calendar",
   which then wrapped to three lines and made one tile twice the height
   of its neighbours. */
.tile .n.topn{
  font-family:inherit;font-size:var(--t-md);font-weight:600;line-height:1.25;
  word-break:break-word;
}

/* The explanatory panel. `details.addcontact` gives it the +/− summary
   and the bordered box; this is only the body, which that pattern never
   needed because its own body is a form. */
.notebody{margin-top:var(--s3);font-size:var(--t-sm);color:var(--ink-2);max-width:74ch}
.notebody p{margin:0 0 var(--s3)}
.notebody p:last-child{margin-bottom:0}
.notebody strong{color:var(--ink)}
details.whatis{margin-top:var(--s5)}

/* Inline code — column names, field names. Not a code block: these are
   single tokens inside a sentence. */
code{
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--t-sm);
  background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:1px var(--s1);
}

/* ---- the import form ---- */
/* 3.9.26 — the Fetch-from-Shopify box above the paste box. Bordered so it
   reads as a different way IN, not as part of the paste. */
/* 3.9.26 — the two rulings on a paid-but-unrecorded order, on To do. The
   "not a learner" form is inside <details> so the reason box only appears
   when somebody has chosen that ruling, and the row reads as one line
   until then. No JavaScript (D-61). */
.actions.tight{margin-top:var(--s2);gap:var(--s2)}
details.inline{display:inline-block;vertical-align:middle}
details.inline>summary{list-style:none;cursor:pointer;display:inline-block}
details.inline>summary::-webkit-details-marker{display:none}
details.inline[open]>summary{margin-bottom:var(--s2)}
.stack.tight{gap:var(--s2);max-width:34rem}
.fetchbox{border:1px solid var(--line);border-radius:8px;padding:14px 16px;margin-bottom:12px;background:var(--panel,transparent)}
.fetchbox input[type=date]{max-width:14rem}
.impform .field{display:block;margin:0}
.impform .field .lab{display:block;font-weight:600;font-size:var(--t-sm)}
.impform .field .opt{font-weight:400;color:var(--ink-3);font-size:var(--t-xs)}
.impform .field .hint{
  display:block;color:var(--ink-2);font-size:var(--t-sm);margin:2px 0 var(--s2);max-width:74ch;
}
.impform textarea{
  width:100%;min-height:220px;resize:vertical;
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--t-sm);line-height:1.5;
  padding:var(--s3);border:1px solid var(--line-2);border-radius:var(--r-sm);
  background:var(--surface);color:var(--ink);
}
.impform input[type=text]{
  width:100%;max-width:520px;padding:var(--s2) var(--s3);min-height:40px;font:inherit;
  font-size:var(--t-sm);border:1px solid var(--line-2);border-radius:var(--r-sm);
  background:var(--surface);color:var(--ink);
}
.impform input[type=file]{font-size:var(--t-sm);color:var(--ink-2)}
.actions{display:flex;gap:var(--s3);flex-wrap:wrap;align-items:center;margin-top:var(--s5)}
.actions .btn{margin-top:0}

h2.sect{
  font-size:var(--t-md);margin:var(--s6) 0 var(--s3);
  padding-bottom:var(--s2);border-bottom:1px solid var(--line);
}

/* The confirmation step. A left rule in the accent, because confirming
   is the interactive act on this page — not a state, and not a warning:
   nothing has gone wrong, and colouring it red would say it had. */
.confirm{
  margin-top:var(--s5);padding:var(--s4);
  border:1px solid var(--line);border-left:3px solid var(--accent);
  border-radius:var(--r-sm);background:var(--surface);
}
.confirm p{margin:0;font-size:var(--t-sm);color:var(--ink-2);max-width:74ch}
.confirm .actions{margin-top:var(--s4)}

/* ---- the diff ---- */
table.diff td{vertical-align:top;padding:var(--s2)}
table.diff td.num{font-variant-numeric:tabular-nums;color:var(--ink-3);width:52px}
table.diff td.who{font-weight:600}
table.diff td.who .muted{font-weight:400;font-size:var(--t-xs);display:block}
/* The old value is struck through and quiet; the new one is plain ink.
   No colour on either: a correction is not a state, and green-for-new
   would collide with the one thing green is allowed to mean. */
table.diff td.wasval{color:var(--ink-3);text-decoration:line-through}
table.diff td.newval{font-weight:600}
/* The first row of each learner's block carries the line and the name;
   the rest are that learner's other fields. A rule above the group is
   what makes five rows read as one person. */
table.diff tr.grp td{border-top:1px solid var(--line-2)}
table.diff.skipped td.who{font-weight:400;color:var(--ink-2)}

/* ---- the activity log ---- */
table.actlog td{padding:var(--s2);vertical-align:middle}
table.actlog td.num{font-variant-numeric:tabular-nums}
table.actlog td.when{white-space:nowrap;font-variant-numeric:tabular-nums;color:var(--ink-2)}
table.actlog td.who{font-weight:600}
table.actlog td.addr{
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--t-xs);
  color:var(--ink-3);word-break:break-all;
}

@media (max-width:640px){
  /* On a card, the struck-through old value and the new one sit on
     consecutive labelled lines, which reads correctly without needing
     the columns. */
  table.diff tr.grp td{border-top:0}
  .impform textarea{min-height:180px;font-size:var(--t-xs)}
  .actions .btn{flex:1 1 auto}
  .confirm .actions .btn{width:100%}
}


/* ==================================================================
   3.9.6 — profile, accounts, staff, the front page, the restricted mark
   ================================================================== */

/* ---- avatar: initials until a photo exists; the photo is a JPEG served
   through ?p=avatar, never a public path ---- */
.avatar{
  width:32px;height:32px;border-radius:var(--r-full);flex:none;overflow:hidden;
  background:var(--accent-wash);color:var(--accent);
  display:inline-flex;align-items:center;justify-content:center;
  font-size:var(--t-xs);font-weight:600;letter-spacing:.02em;line-height:1;
}
.avatar img{width:100%;height:100%;object-fit:cover;display:block}
.avatar.sm{width:26px;height:26px}
.avatar.big{width:96px;height:96px;font-size:var(--t-xl)}
.who a.me{
  display:flex;align-items:center;gap:var(--s2);text-decoration:none;color:var(--ink);
  padding:var(--s1) var(--s2) var(--s1) var(--s1);border-radius:var(--r-full);min-width:0;
}
.who a.me:hover{background:var(--accent-wash)}
.who a.me[aria-current="page"]{background:var(--accent-wash)}
.avatar-row{display:flex;gap:var(--s4);align-items:flex-start;flex-wrap:wrap}
.avatar-row > div{flex:1;min-width:220px}
.avatar-row form.inline{margin-right:var(--s2)}

/* ---- view-as banner (D-30): persistent, unmistakable, on every page ---- */
.viewas{
  background:var(--attn-wash);color:var(--attn);border-bottom:1px solid var(--line-2);
  padding:var(--s2) var(--s5);font-size:var(--t-sm);
  display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap;
}
.viewas .linkish{color:var(--attn);font-weight:600}

/* ---- the restricted mark (A10) ---- */
.restricted{
  display:inline-flex;align-items:center;gap:6px;margin:0 0 var(--s2);
  font-size:var(--t-xs);font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-3);border:1px solid var(--line-2);border-radius:var(--r-full);padding:2px 9px;
}
.restricted i{width:7px;height:7px;border-radius:var(--r-full);background:var(--attn);display:inline-block}
.restricted.office i{background:var(--accent)}
.restricted.admin i{background:var(--prob)}

/* ---- accounts and staff tables: every row one height, dates in
   tabular figures, actions in one column (Simon, 6 Sep 2026) ---- */
table.accounts td{vertical-align:middle;height:52px;line-height:1.3}
table.accounts td.av,table.accounts th.av{width:34px;padding-right:0}
table.accounts td.num,table.accounts th.num{text-align:right;font-variant-numeric:tabular-nums}
table.accounts td.acts,table.accounts th.acts{text-align:right}
table.accounts .sep{color:var(--ink-3);margin:0 var(--s1)}
table.accounts .tag{white-space:nowrap;vertical-align:middle}
table.accounts form.inline{display:inline;margin:0}
table.accounts .linkish,table.accounts details.del > summary{padding:0;line-height:1.3;display:inline}
table.accounts tr.dim td{color:var(--ink-3)}
table.accounts tr.dim td .tag{opacity:.7}
details.del{display:inline}
details.del > summary{display:inline;cursor:pointer;color:var(--accent);text-decoration:underline;font-size:var(--t-sm)}
details.del[open] > summary{color:var(--prob)}
details.del form{display:inline-flex;gap:var(--s2);align-items:center;flex-wrap:wrap;margin-left:var(--s2)}
.btn.sm{padding:var(--s1) var(--s2);font-size:var(--t-xs)}
.btn.danger{border-color:var(--prob);color:var(--prob)}
.btn.danger:hover{background:var(--prob-wash)}

/* ---- forms: three fields across, one column on a phone ---- */
.grid3{display:grid;grid-template-columns:1fr 1fr 1.4fr;gap:var(--s3) var(--s4)}
.grid3 label:first-child{margin-top:0}
.grid3 .span2{grid-column:span 2}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:var(--s5)}
.grid2.align-top{align-items:start}
@media (max-width:760px){.grid3,.grid2{grid-template-columns:1fr}}

/* ---- the Schedule's day list is one card (A13) ---- */
.card.daylist .weekband:first-child{margin-top:0}
.card.daylist .dayrow:last-child{padding-bottom:0}

/* ---- the front page (Q20, Option A) ---- */
body.front{display:flex;flex-direction:column;min-height:100vh}
body.front .top{flex-wrap:nowrap}
body.front .hero{
  flex:1;max-width:1040px;width:100%;margin:0 auto;padding:var(--s7) var(--s5);
  display:grid;grid-template-columns:1.2fr 1fr;gap:var(--s7);align-items:start;
}
body.front .pitch .mark{text-align:left;font-size:var(--t-2xl);margin:0 0 var(--s3)}
body.front .lede{font-size:var(--t-md);color:var(--ink-2);max-width:32em;line-height:1.55}
body.front .signin{margin:0}
body.front .signin h2{margin-bottom:var(--s3)}
.btn.block{display:block;width:100%;text-align:center;margin-top:var(--s4)}
details.lost{margin-top:var(--s4)}
details.lost > summary{cursor:pointer;color:var(--accent);font-size:var(--t-sm);text-decoration:underline}
.lost-panel{
  margin-top:var(--s3);padding:var(--s3) var(--s4);background:var(--surface-2);
  border-radius:var(--r-sm);font-size:var(--t-sm);line-height:1.55;
}
body.front .foot{width:100%}
@media (max-width:760px){
  body.front .hero{grid-template-columns:1fr;gap:var(--s5);padding:var(--s5) var(--s4)}
  body.front .pitch .mark{font-size:var(--t-xl)}
}

/* 3.9.7 (C80) - take an added-by-name row off the register. The form
   lives outside the table (form= attribute); the button sits by the tag. */
.hiddenform{display:none}
.who .remove{margin-left:8px;color:var(--ink-3);font-size:var(--t-xs)}
.who .remove:hover{color:var(--prob)}

/* 3.9.7 (S-1..S-3) - the Schedule's class view in three sections. Each
   section is a card with a heading row: the name, a small pill saying
   the kind, one line of why, and its own count on the right. */
.card.group{padding:0;overflow:hidden}
.card.group .tblwrap{margin:0}
.card.group table.cards{margin:0}
.ghead{display:flex;align-items:baseline;flex-wrap:wrap;gap:var(--s2) var(--s3);padding:var(--s3) var(--s4);border-bottom:1px solid var(--line)}
.ghead h2{margin:0;font-size:var(--t-md)}
.ghead .gk{font-size:var(--t-xs);font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);padding:2px 8px;border-radius:var(--r-full);background:var(--surface-2)}
.ghead .gk.ev{background:var(--accent-wash);color:var(--accent)}
.ghead .why{font-size:var(--t-sm);color:var(--ink-2)}
.ghead .stat{margin-left:auto;font-size:var(--t-sm);color:var(--ink-2);white-space:nowrap;font-variant-numeric:tabular-nums}
.ghead .stat .gap{color:var(--prob)}
@media (max-width:760px){.ghead .stat{margin-left:0;width:100%}}

/* 3.9.7 - "Or pick from the list": the addable names as buttons, for
   browsers whose datalist hides. */
.picklist{margin:var(--s2) 0 0}
.picklist summary{cursor:pointer;color:var(--accent);text-decoration:underline}
.picklist .chips{display:flex;flex-wrap:wrap;gap:var(--s2);padding:var(--s3) 0 var(--s1)}
.chip{font:inherit;font-size:var(--t-sm);padding:var(--s1) var(--s3);border:1px solid var(--line-2);border-radius:var(--r-full);background:var(--surface);color:var(--ink);cursor:pointer;line-height:1.5}
.chip:hover{border-color:var(--accent);background:var(--accent-wash)}
.chip .muted{font-size:var(--t-xs)}

/* 3.9.7 - somebody booked on the other class this evening (came early
   for this one, or stayed on after it). The name goes a shade quieter so
   the pill is what the eye lands on; nothing about their marks changes. */
.who .nm.crossed{color:var(--ink-2)}
.tag.cross{background:var(--accent-wash);color:var(--accent)}

/* 3.9.7 - the class record. */
.record .rec-head{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;margin-bottom:var(--s3)}
.record .rec-head h2{margin:0}
.record .rec-btn{margin-left:auto;display:inline-flex;align-items:center;gap:8px}
.record .rec-btn .dot{width:10px;height:10px;border-radius:var(--r-full);background:var(--prob);display:inline-block}
.reclist{list-style:none;margin:0 0 var(--s4);padding:0}
.reclist .rec{display:flex;gap:var(--s3);align-items:flex-start;padding:var(--s3) 0;border-top:1px solid var(--line)}
.reclist .kind{flex:none;width:86px;font-size:var(--t-xs);font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);padding-top:4px}
.reclist .body{flex:1;min-width:0;display:flex;flex-direction:column;gap:var(--s1)}
.reclist .title{font-weight:600;overflow-wrap:anywhere}
.reclist audio{width:100%;max-width:560px;display:block;margin:var(--s1) 0}
.reclist .thumb img{max-width:220px;max-height:160px;border-radius:var(--r-sm);border:1px solid var(--line);display:block}
.reclist .notetext{margin:0;white-space:normal}
.reclist .caption{margin:0;color:var(--ink-2)}
.reclist .meta a{color:var(--ink-3)}
.reclist details.del{flex:none}
.reclist details.del summary{list-style:none}
.reclist details.del form{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap;margin-top:var(--s1)}
.rec-add{border-top:1px solid var(--line);padding-top:var(--s3)}
.rec-add textarea{width:100%;font:inherit;padding:var(--s2) var(--s3);border:1px solid var(--line-2);border-radius:var(--r-sm)}
.rec-add .actions{margin:var(--s3) 0 var(--s1)}
@media (max-width:640px){.reclist .rec{flex-wrap:wrap}.reclist .kind{width:auto}}

/* 3.9.7 - the recorder window (the one page with a script). */
/* [hidden] has to outrank .btn's own display, or a button the script
   has hidden is still on the page - which on the recorder meant Stop
   visible before anything was recording. */
[hidden]{display:none !important}
.recorder .clock{font-size:var(--clock);font-variant-numeric:tabular-nums;margin:var(--s3) 0 0;font-family:Georgia,serif}
.recorder .state{margin:0 0 var(--s3)}
.recorder .actions{display:flex;gap:var(--s3);flex-wrap:wrap;align-items:center;margin:var(--s3) 0}
.recorder .btn.big{padding:var(--s3) var(--s5);font-size:var(--t-md)}
.recorder audio{width:100%;max-width:560px;display:block;margin:var(--s3) 0 var(--s2)}
.recorder #done{border-top:1px solid var(--line);margin-top:var(--s4);padding-top:var(--s3)}
.recorder #done h2{margin-top:0}
/* 3.12.1 — the recorder can see what it hears, and says when the phone took the microphone away */
.recorder .rec-level{display:flex;align-items:center;gap:var(--s2);margin:0 0 var(--s2)}
.recorder .rec-level meter{width:100%;max-width:320px;height:14px}
.recorder .rec-away{font-weight:700;font-size:var(--t-md)}
.recorder .rec-tip{margin:var(--s2) 0 0}

/* 3.9.7 - ticking a website error off the To do list. */
.tickoff{margin-left:var(--s2)}
.fixedlist{margin-top:var(--s3)}
.fixedlist summary{cursor:pointer;color:var(--ink-3)}
.fixedlist ul{margin:var(--s2) 0 0;padding-left:var(--s5)}
.fixedlist li{padding:2px 0}


/* 3.9.7 - the register's rows run the full width of the table: one line
   per row, unbroken from the name to the last mark. */
table.register td.who{display:table-cell;vertical-align:middle}
table.register td,table.register th{border-bottom:1px solid var(--line)}
table.register tr:last-child td{border-bottom:0}
@media (max-width:640px){
  table.register td.who{display:block}
  table.register td,table.register th{border-bottom:0}
}

/* ==================================================================
   3.9.9 — the funnel: Enquiries, Introductory Learners, Closed.

   No new colour and no new type size. The stage counts are ink on
   paper; the only accent is which group you are looking at, because
   accent means interactive and a selected filter is interactive.
   "Late" is the one state colour here, and it is earned: it means
   nobody has spoken to a real person in a fortnight.
   ================================================================== */
/* 3.9.43 — Simon, 17 Sep: "we need to lose those" (the two rows of stage
   counts on Enquiries and Introductory). Nothing in src/views/*.php
   references .funnel/.fstage/.fs-k/.fs-v any more (enquiries.php was the
   only user) — left here, unused, rather than deleted, on the same
   reasoning schema/README-ORDER.md gives for not dropping a table: it
   costs nothing to leave and there is no reason yet to trust every last
   place that might still reference it by name. */
.funnel{display:grid;grid-template-columns:repeat(auto-fit,minmax(118px,1fr));
        gap:var(--s2);margin:0 0 var(--s2)}
.funnel.exits{margin-bottom:var(--s5)}
.fstage{border:1px solid var(--line);border-radius:var(--r-sm);padding:var(--s3);
        background:var(--surface);min-width:0}
.fstage.on{border-color:var(--accent);background:var(--accent-wash)}
.fstage.needs{border-color:var(--attn);background:var(--attn-wash)}
.fstage.needs .fs-v{color:var(--attn)}
.fs-k{display:block;font-size:var(--t-xs);color:var(--ink-3);line-height:1.35;
      min-height:2.7em;overflow-wrap:anywhere}
.fs-v{display:block;font-size:var(--t-xl);line-height:1.1;font-weight:600;
      font-variant-numeric:tabular-nums}

/* A row. <details> so it opens with no script (D-61). */
.erow{border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface);
      margin-bottom:var(--s2)}
/* 3.9.16 sizes the last three columns. Same fault as .classplans and
   .printlist: a stage label, a day count and an advisor's name are all
   different lengths from row to row, and while they were `auto` the
   NAME — the column somebody actually reads down — started in a
   different place on every line. The advisor's name is the one that can
   genuinely be long, so it takes a fraction and an ellipsis rather than
   a width it might not fit in. */
.erow>summary{list-style:none;cursor:pointer;display:grid;
      grid-template-columns:minmax(150px,1.3fr) minmax(0,1fr) 108px 104px minmax(0,0.9fr);
      gap:var(--s3);align-items:center;padding:var(--s3) var(--s4)}
.erow>summary::-webkit-details-marker{display:none}
.erow>summary::marker{content:''}
.erow>summary:hover{background:var(--surface-2)}
.erow>summary:focus-visible{outline:none;box-shadow:var(--focus);border-radius:var(--r-sm)}
.erow[open]{border-color:var(--line-2)}
.erow[open]>summary{border-bottom:1px solid var(--line);background:var(--surface-2)}
.e-name{font-weight:600;font-size:var(--t-sm);overflow-wrap:anywhere}
.e-act{font-size:var(--t-sm);color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;
       white-space:nowrap}
.e-stage{font-size:var(--t-xs);color:var(--ink-3);white-space:nowrap}
.e-days{font-size:var(--t-xs);color:var(--ink-3);white-space:nowrap;
        font-variant-numeric:tabular-nums}
.e-days.late{color:var(--prob);font-weight:600}
.e-who{font-size:var(--t-xs);color:var(--ink-3);white-space:nowrap;
       overflow:hidden;text-overflow:ellipsis}
.epanel{padding:var(--s4)}
.epanel .stack{border-top:1px solid var(--line);padding-top:var(--s3);margin-top:var(--s3)}
.epanel label{display:block;font-size:var(--t-xs);color:var(--ink-3);margin-bottom:var(--s1)}
.epanel input[type=text],.epanel select{width:100%;max-width:44rem;font:inherit;
      font-size:var(--t-sm);padding:var(--s2);min-height:38px;margin-bottom:var(--s2)}

/* NOTHING SCROLLS SIDEWAYS (the 3.5.0 rule): below 720 the row stops
   being a table and becomes a stack, rather than growing a scrollbar. */
@media (max-width:720px){
  .erow>summary{grid-template-columns:1fr;gap:var(--s1)}
  .e-act{white-space:normal}
  .funnel{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* ==================================================================
   the feedback panel  (3.9.10, F-1..F-5)

   Bottom right of every page, one click to open, always in the same
   place. A <details>, like every other disclosure here: it opens with
   no script (D-61), it is keyboard-operable and screen-reader-announced
   for free, and there is nothing in it that can break.

   The accent is used because the whole control IS interactive - it is a
   button - which is the one thing the accent is allowed to mean.

   It never grows wider than the window: at every width the open panel
   is capped against the viewport, so nothing scrolls sideways. On a
   phone it becomes a sheet across the bottom, because a 360px card with
   a text box in it is not something anybody can type into.
   ================================================================== */
.fb{position:fixed;right:var(--s4);bottom:var(--s4);z-index:40;width:auto;
    max-width:calc(100vw - var(--s5))}
.fb > summary{
  list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:var(--s2);
  background:var(--accent);color:var(--accent-ink);border-radius:var(--r-full);
  padding:10px 18px;font-size:var(--t-sm);font-weight:700;box-shadow:var(--lift-2);
}
.fb > summary::-webkit-details-marker{display:none}
.fb > summary::marker{content:''}
.fb > summary:hover{background:var(--accent-hover)}
.fb[open]{width:360px;max-width:calc(100vw - var(--s5));background:var(--surface);
  border:1px solid var(--line-2);border-radius:var(--r-md);box-shadow:var(--lift-2);
  overflow:hidden}
.fb[open] > summary{border-radius:var(--r-md) var(--r-md) 0 0;box-shadow:none;
  width:100%;justify-content:space-between;padding:var(--s3) var(--s4)}
.fb .panel{padding:var(--s4);border-top:1px solid var(--line)}
.fb label{display:block;font-size:var(--t-xs);text-transform:uppercase;letter-spacing:.1em;
  color:var(--ink-3);margin-bottom:var(--s2)}
.fb textarea{width:100%;min-height:104px;font-size:var(--t-sm);background:var(--surface-2)}
.fb .foot{display:flex;align-items:flex-start;gap:var(--s3);margin-top:var(--s3)}
.fb .send{flex:none;background:var(--accent);color:var(--accent-ink);border:0;
  border-radius:var(--r-sm);padding:9px 18px;font:inherit;font-size:var(--t-sm);
  font-weight:700;cursor:pointer;min-height:40px}
.fb .send:hover{background:var(--accent-hover)}
.fb .hint{font-size:var(--t-xs);color:var(--ink-3);line-height:1.45}
.fb .close{font-size:var(--t-lg);line-height:1;color:var(--accent-ink);opacity:.8}
.fb .lbl-shut{display:none}
.fb[open] .lbl-open{display:none}
.fb[open] .lbl-shut{display:inline}

/* The sheet. Deliberately ABOVE the thumb line rather than under it, so
   the shut button never sits on top of Save register. */
@media (max-width:640px){
  .fb{right:var(--s3);bottom:var(--s3)}
  /* Only the OPEN panel spans the width. A full-width shut control
     would be an invisible strip across the bottom of every page,
     swallowing taps meant for whatever is underneath it. */
  .fb[open]{left:var(--s3);right:var(--s3);width:auto;max-width:none}
  .fb .foot{flex-direction:column;gap:var(--s2)}
}

/* The thank-you, in the window of its own that F-2 chose. */
.thanks{max-width:44rem}

/* =====================================================================
   3.9.10 — AWAY DATES, BULK APPLY, AND THE ACKNOWLEDGEMENT THAT GOES
   =====================================================================
   Simon, 8 Sep 2026: "it's great to have that confirmation, however it's
   very frustrating to keep losing my place in the page... could we have
   a quick green acknowledgement message that disappears?"

   Two changes answer that. The page now returns you to the row you
   answered rather than the top (see redirect() in render.php), so the
   acknowledgement moved OFF the top of the page and ON to the row —
   a banner at the top is a message you would never see from halfway
   down a long list. And it fades on its own.

   The fade is CSS, not JavaScript. D-61 is untouched: nothing here
   scripts anything, it is one animation on one element. The lit button
   stays behind as the permanent record; only the "just now" goes.
   ================================================================== */
.av-done{display:block;margin-top:var(--s1);font-size:var(--t-xs);font-weight:600;
  color:var(--good);animation:av-fade 5s ease-out forwards}
@keyframes av-fade{0%,55%{opacity:1}100%{opacity:0}}
/* Somebody who has switched motion off gets the message and keeps it,
   rather than having it flash past. Better a line that stays than an
   acknowledgement they never saw. */
@media (prefers-reduced-motion: reduce){
  .av-done{animation:none}
}
.av-prov{display:block;margin-top:2px;font-size:var(--t-xs);color:var(--ink-3)}
tr.justdone{background:var(--good-wash)}

.avaway{margin:0 0 var(--s5)}
.avaway>summary{font-weight:600;cursor:pointer}
.avcards{display:grid;grid-template-columns:1fr 1fr;gap:var(--s4);margin-top:var(--s4)}
/* Nothing scrolls sideways, ever. Below 720px the two cards stack. */
@media (max-width:720px){.avcards{grid-template-columns:1fr}}
.avcards .card{padding:var(--s4)}
.avcards h3{font-size:var(--t-base);margin:0 0 var(--s3)}
.avcards label{display:inline-flex;align-items:center;gap:var(--s2);
  font-size:var(--t-sm);color:var(--ink-2);margin:0 var(--s3) var(--s3) 0}
.avcards input[type=date],.avcards select{max-width:100%}
.avcards .fine{margin:var(--s2) 0 0;font-size:var(--t-sm);color:var(--ink-2)}
.awaylist{margin-top:var(--s4);border-top:1px solid var(--line);padding-top:var(--s3)}
.awayrow{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s3);
  font-size:var(--t-sm);padding:var(--s2) 0;border-bottom:1px solid var(--line)}
.awayrow:last-child{border-bottom:0}
.awayrow .d{font-weight:600}
.awayrow form{margin-left:auto}

/* =====================================================================
   3.9.13 — ANSWERING FOR SOMEBODY ELSE

   Simon, 9 September 2026: "Andrew Samarasekara has sent me his
   provisional availability by email. How do I access the 'what can I
   cover' tool for another tutor?"

   Two marks, and both are STATE rather than decoration, which is why
   both are amber and neither is the accent.

   THE BANNER is the view-as banner's treatment on purpose (D-30). The
   failure it exists to prevent is identical — somebody acting as
   somebody else and forgetting they are — and answering the same
   question twice with two different pieces of design would mean neither
   one taught you to read the other. It is full width, above the
   heading, and it cannot be missed at any width, because the mistake it
   prevents is silent: nothing later in the day would tell you that the
   Tuesdays you just answered were not yours.

   THE ROW MARK says an answer was entered by somebody else. Amber for
   the same reason the away line beside it is quiet ink: "the office
   filled this in" is a fact about the state of the row that the teacher
   may need to act on, where "you are away that week" is merely where
   the answer came from.

   NOTHING SCROLLS SIDEWAYS. The banner wraps; the picker is the .ph-act
   row, which already wraps and stacks; a display name inside either can
   be long and breaks rather than pushing the page wide.
   ===================================================================== */
.answerfor{
  background:var(--attn-wash);color:var(--attn);border:1px solid var(--line-2);
  border-radius:var(--r-sm);padding:var(--s3) var(--s4);margin:0 0 var(--s4);
  font-size:var(--t-sm);line-height:1.5;
  display:flex;gap:var(--s2) var(--s3);align-items:baseline;flex-wrap:wrap;
}
/* The sentence is one flex child and the way out is the other, so the
   gap between them never lands in the middle of the prose. */
.answerfor > span{flex:1 1 260px;min-width:0}
.answerfor strong{overflow-wrap:anywhere}
.answerfor .linkish{color:var(--attn);font-weight:600;margin-left:auto;flex:0 0 auto}

/* The "For" picker. A label, a select and a button on one line, which
   wraps to two on a phone rather than growing the page. */
.forpick{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2)}
.forpick label{font-size:var(--t-sm);color:var(--ink-2);font-weight:600}
.forpick select{max-width:100%}

.av-byother{display:block;margin-top:2px;font-size:var(--t-xs);color:var(--attn);
  font-weight:600;overflow-wrap:anywhere}

/* =====================================================================
   3.9.11 — CLASS PLANS AND TEACHING MATERIALS
   =====================================================================
   Simon, 9 September 2026: "I need Teachers to be able to see at a
   glance everything they need to print and teach."

   So the print list is a LIST, not a gallery of thumbnails. A person
   reading this is standing next to a printer deciding what to send to
   it, and four columns of plain text — name, what it is for, how many
   pages, how to get it — is the fastest thing to scan there is. A grid
   of file cards would be prettier and slower.

   No new colour. The accent appears only where it always does, on the
   links; "every week" and "for learners too" are tags in ink, because
   neither is a state — they are facts about where a document came from
   and who it is meant for. The one thing that borrows a state colour is
   a class with nothing to print, and it borrows the quiet one.

   NOTHING SCROLLS SIDEWAYS. Below 720px both lists stop being rows of
   columns and become stacks. A document title is a file name and file
   names are long, so they wrap rather than pushing the page wide.
   ================================================================== */
.plan .plan-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s3);
  margin-bottom:var(--s3)}
.plan .plan-head h2{margin:0}
.plan h3.printhead{margin:var(--s5) 0 var(--s2);font-size:var(--t-sm);
  text-transform:uppercase;letter-spacing:.1em;color:var(--ink-3)}
.plan h3.printhead:first-of-type{margin-top:0}

/* The print list. Four columns on a desk, one stack on a phone.
 *
 * 3.9.16 gives the last two columns a size for the reason set out at
 * .classplans below: "3 pages" and "pages not given" are different
 * widths, so an `auto` track made the two columns before them start
 * somewhere different on every line. */
/* 3.9.21 — THREE COLUMNS NOW, BECAUSE EACH ROW LEADS WITH A PICTURE.
   Preview, then everything you read about the file, then the controls.
   The name, what it is FOR and how many pages are one block rather than
   three columns spread across the width: Simon asked for what a document
   is for to sit under its name, and "one per learner" is the second
   thing a teacher needs to know, not the fourth. */
.printlist{list-style:none;margin:0;padding:0;border-top:1px solid var(--line)}
.printlist li{display:grid;
  grid-template-columns:44px minmax(0,1fr) minmax(0,1.2fr);
  gap:var(--s3);align-items:center;
  padding:var(--s2) 0;border-bottom:1px solid var(--line)}
.pl-body{display:flex;flex-direction:column;gap:1px;min-width:0}
.pl-name{font-weight:600;overflow-wrap:anywhere}
/* 3.9.53 — Simon, 17 Sep: class materials Option C ("class details -
   let's go with C for now"), approved after "This is all fine but it
   takes up too much real estate." Purpose and page count used to be two
   full-width lines under the name; .pl-meta is now one, joined with a
   middle dot in the markup, and the thumbnail shrank from 76px to 44px
   to match — still enough to recognise a page, not a small poster. */
.pl-meta{font-size:var(--t-sm);color:var(--ink-2);overflow-wrap:anywhere}
.pl-get{font-size:var(--t-sm);display:flex;flex-wrap:wrap;align-items:baseline;
  gap:var(--s3);justify-content:flex-end}
.pl-get .del{display:inline}

/* THE PREVIEW. A fixed box so a column of them lines up whatever shape
   the pages are, and the picture sits inside it rather than filling it —
   a landscape worksheet and a portrait one are both recognisable and
   neither is cropped or stretched into a lie about what it looks like.
   3.9.53: shrunk from 76x100 to 44x58 as part of the same space-saving
   pass that merged the two metadata lines into one — see .pl-meta above. */
.pl-thumb{display:block;width:44px}
.pl-thumb a{display:flex;align-items:center;justify-content:center;
  width:44px;height:58px;border:1px solid var(--line-2);border-radius:var(--r-sm);
  background:var(--surface-2);overflow:hidden;text-decoration:none}
.pl-thumb .thumbimg{max-width:100%;max-height:100%;width:auto;height:auto;display:block}

/* AND WHEN THERE IS NO PICTURE. Not a grey rectangle pretending to be a
   page: the kind of file, in words, large enough to read across a desk,
   with a second line saying plainly that there is no preview. Nothing
   here is carried by colour — the words say the whole of it. */
.pl-thumb .tile{flex-direction:column;gap:2px;color:var(--ink-2)}
.pl-thumb .tile .tk{font-size:var(--t-md);font-weight:700;letter-spacing:.02em;
  color:var(--ink)}
.pl-thumb .tile .tn{font-size:var(--t-xs);color:var(--ink-3);text-align:center}

/* The row somebody has just added. Marked so that a person returned to
   the middle of a long list can see which one is new — the C120 rule
   that an acknowledgement belongs where the reader is. The tag beside
   the name says "just added" in words; this only puts a quiet ground
   under it, so the meaning never rests on the colour. */
.printlist li.just{background:var(--good-wash)}
.plan .plantext{margin:0 0 var(--s2);max-width:70ch}
.plan .planedit{margin-top:var(--s5);border-top:1px solid var(--line);padding-top:var(--s3)}
.plan .planedit>summary{cursor:pointer;font-size:var(--t-sm)}

/* A level and its standing pack. Open when it has one, because a pack
   that is there is the answer to the question the page was opened with;
   shut when it is empty, so five empty levels are five lines and not
   five screens. */
.levelpack{border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--surface);margin-bottom:var(--s3);padding:0 var(--s4)}
.levelpack>summary{list-style:none;cursor:pointer;display:flex;flex-wrap:wrap;
  align-items:baseline;gap:var(--s3);padding:var(--s3) 0}
.levelpack>summary::-webkit-details-marker{display:none}
.levelpack>summary::marker{content:''}
.levelpack>summary:focus-visible{outline:none;box-shadow:var(--focus);border-radius:var(--r-sm)}
.lp-name{font-weight:600}
.levelpack[open]>summary{border-bottom:1px solid var(--line)}
.levelpack .printlist{border-top:0}
.levelpack .packadd{margin:var(--s4) 0;padding-top:var(--s3);border-top:1px solid var(--line)}
.levelpack .empty{margin:var(--s3) 0}

/* One class, on the Class plans screen.
 *
 * 3.9.16 — WHY THE TRACK WIDTHS ARE WRITTEN OUT AND NOT LEFT ON `auto`.
 *
 * Simon, 9 Sep 2026: "this formatting needs to be consistent — second
 * column shouldn't change place based on what else is in the other
 * columns." He was describing exactly what this rule did.
 *
 * Each LI is its own grid container, so its tracks were sized from its
 * own contents and nothing else. Three of the five were `auto`, and two
 * of those hold text that differs from row to row — "nothing to print"
 * against "3 to print", "no plan written" against "plan written". A
 * shorter word in the fourth column left more room for the first two, so
 * the level name started in a different place on every line and the eye
 * had nothing to run down.
 *
 * Making the UL the grid and the rows `display:contents` would align
 * them, at the cost of the row box that carries the today tint and the
 * rule underneath it. Subgrid would do it properly and is a newer floor
 * than this product has agreed to stand on. So the two columns that vary
 * are simply given a width: every row then resolves identically, because
 * there is nothing left in a row for the resolution to depend on. The
 * last column is left `auto` deliberately — it holds one Open button and
 * is the same width in every row by construction. */
.classplans{list-style:none;margin:0;padding:0;border-top:1px solid var(--line)}
.classplans li{display:grid;
  grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) 108px 108px auto;
  gap:var(--s3);align-items:center;
  padding:var(--s3) 0;border-bottom:1px solid var(--line)}
.classplans li.today{background:var(--accent-wash)}
.cp-when{font-size:var(--t-sm)}
.cp-level{font-weight:600;overflow-wrap:anywhere}
.cp-docs,.cp-plan{font-size:var(--t-xs);color:var(--ink-2);white-space:nowrap}
/* "Nothing to print" and "no plan written" are not failures — a class
   may legitimately need neither — so they are quiet rather than red.
   Red here would mark two thirds of the term as broken. */
.cp-docs.none,.cp-plan.none{color:var(--ink-3)}
.cp-go{justify-self:end}

@media (max-width:720px){
  /* The preview keeps its column and the words move alongside it; the
     controls drop to a full-width line underneath. At 400px that is a
     44px box (3.9.53) and a text column that can shrink to nothing, so
     nothing ever pushes the page sideways. */
  .printlist li{grid-template-columns:44px minmax(0,1fr);gap:var(--s2) var(--s3)}
  .pl-get{grid-column:1 / -1;justify-content:flex-start}
  .classplans li{grid-template-columns:1fr auto;gap:var(--s1) var(--s3)}
  .cp-when,.cp-level{grid-column:1}
  .cp-go{grid-row:1 / span 2;grid-column:2;align-self:start}
  .cp-docs,.cp-plan{grid-column:1;white-space:normal}
}

/* =====================================================================
   3.9.12 — the whole learner record, and Mailchimp from inside Arcanté

   Two panels on the person page, and between them they add one shape
   the sheet did not already have: a TAG CHIP with a control on it.
   Everything else here is the existing card, fieldset, row and table
   vocabulary, because a new screen that invents its own spacing is the
   thing 3.7.0's token system exists to stop.

   COLOUR. Nothing below introduces one. The chips are ink on paper with
   a rule round them; the only accent is on the buttons, which are
   interactive; the only green, amber and red are on <span class="tag">
   saying whether Mailchimp confirmed something, which is state. A tag
   that cannot be removed is quieter, not redder — it is not a problem,
   it is simply not yours to switch off.

   NOTHING SCROLLS SIDEWAYS. Tag names are somebody else's strings and
   can be 90 characters long, so every one of them wraps inside its own
   chip (overflow-wrap:anywhere) and the chips themselves wrap onto new
   lines. The record's fieldsets are .row, which already wraps and
   stacks. There is no fixed width anywhere in this block.
   ===================================================================== */

/* The move-through-the-funnel line: where they are, and what that means. */
.stagenow{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s2) var(--s3);
  margin:0 0 var(--s4)}

/* Every stage move, with who made it. The shared .tl-* spans are laid
   out here rather than in .reclist, which is the class records' list and
   has a different shape. */
.stagelog li{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s1) var(--s3);
  padding:var(--s2) 0;border-top:1px solid var(--line);font-size:var(--t-sm)}
.stagelog .tl-when{flex:0 0 auto}
.stagelog .tl-what{flex:1 1 220px;min-width:0;overflow-wrap:anywhere}
.stagelog .tl-detail{flex:0 0 auto;margin-top:0}

/* A Mailchimp tag. A chip, because a tag IS a chip everywhere else in
   the world and calling it something else would help nobody. */
.mctags{display:flex;flex-wrap:wrap;gap:var(--s2);list-style:none;margin:var(--s3) 0;padding:0}
.mctags li{display:flex;align-items:center;flex-wrap:wrap;gap:var(--s2);min-width:0;max-width:100%;
  border:1px solid var(--line-2);border-radius:var(--r-full);
  padding:var(--s1) var(--s3);background:var(--surface);font-size:var(--t-sm)}
.mctags .n{min-width:0;overflow-wrap:anywhere}
.mctags form{display:inline-flex;margin:0}
/* The remove control. Small, bordered, and NOT red: taking a tag off is
   an ordinary edit, not a destructive act to be warned about. */
.mctags button.x{
  border:1px solid var(--line-2);border-radius:var(--r-full);background:var(--surface-2);
  color:var(--ink-2);font:inherit;font-size:var(--t-xs);line-height:1;
  padding:var(--s1) var(--s2);min-height:24px;cursor:pointer;
}
.mctags button.x:hover{border-color:var(--accent);color:var(--accent)}
.mctags button.x:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* The one that cannot be taken off. Quieter, not louder. */
.mctags li.locked{background:var(--surface-2);border-style:dashed;color:var(--ink-2)}
.mctags .why{font-size:var(--t-xs);color:var(--ink-3);overflow-wrap:anywhere}

.mcadd{margin:var(--s4) 0 0}
/* A merge field that is shown and not offered. Reads as a value, not as
   a disabled input, because a greyed-out box invites people to click it. */
.mfread{margin:var(--s1) 0 0;padding:var(--s2) var(--s3);
  background:var(--surface-2);border-radius:var(--r-sm);overflow-wrap:anywhere}
.mcname{overflow-wrap:anywhere}
.card.mailchimp h3,.card.record h3{margin:var(--s5) 0 var(--s2);
  text-transform:uppercase;letter-spacing:.1em;color:var(--ink-3)}
/* "Mailchimp is not connected on this server" and its two neighbours.
   Deliberately NOT .blocked, which is the red refusal panel. Nothing is
   wrong when there is no API key — it is a fact about this server, and
   dressing a fact in the colour reserved for state is how red stops
   meaning anything. An inset well, ordinary ink, and the sentence does
   the work. */
.mcoff{margin:var(--s3) 0;padding:var(--s3) var(--s4);
  background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-sm);
  color:var(--ink-2);font-size:var(--t-sm);line-height:1.6}
.mcoff strong{color:var(--ink)}

/* =====================================================================
   3.9.14 — the Curriculum and Repertoire Library

   Almost nothing new. A curriculum level is a .card, a piece is the
   .levelpack <details> the Class plans screen already uses, the
   materials under both are the .printlist that screen already draws, and
   a piece's facts are the .facts / .fact pair the learner record and the
   Enquiries screen already draw. What is genuinely new is four things:
   two prose blocks at the top of a level, two lists (what it covers,
   and what you must be able to do to leave), and one control — a select
   and a button for putting a sheet onto a class.

   COLOUR. Nothing below introduces one, and nothing below borrows a
   state colour. The accent appears only where it always does, on links
   and on the one primary button. "in development", "for learners too"
   and "marked for ViolinSchool.com" are tags in ink, deliberately: none
   of them is a state, they are facts about what a document says and who
   it is meant for, and an empty Advanced course is not an error — it is
   what the Curriculum Journey says. Red there would tell a teacher the
   system had lost something.

   THE PROGRESSION GATE'S TICK IS A MARKER AND NOT A COLOUR. The source
   document draws it in green. Here it is a ✓ in ordinary ink, because
   green in this product means a state somebody is in, and a criterion
   nobody has been assessed against is not a state anybody is in.

   NOTHING SCROLLS SIDEWAYS. The two lists are a 2-up grid that becomes
   one column at 720px. A topic is a whole sentence and a criterion is a
   longer one, so both wrap. The jump row wraps — the source document's
   own version of it scrolls sideways on a phone, which is the thing
   this product does not do at any width. The "add to a class" control
   holds a select whose options are dates and level names of unknown
   length, so it wraps too and the select is allowed to shrink
   (min-width:0), which is the one thing a flex child will not do by
   itself.
   ===================================================================== */

/* The jump row. Wraps, and the label sits with the links rather than
   above them, so it costs one line and not two. */
.viewnav.jumps{gap:var(--s2) var(--s2);margin-bottom:var(--s5)}

/* One curriculum level. */
.curlevel{margin-bottom:var(--s5)}
.curlevel .plan-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s3);
  margin-bottom:var(--s2)}
.curlevel .plan-head h2{margin:0}
/* How the level runs: length, ear or notation, how you get in. Small and
   quiet — it is the subtitle to the name, not a second heading. */
.curformat{margin:0 0 var(--s3);font-size:var(--t-sm);color:var(--ink-2)}
/* The Curriculum Journey's own paragraph about the level. An inset well,
   the same one the Mailchimp panel uses for a fact about the server:
   this is quoted material and not Arcanté talking. */
.curcontext{margin:0 0 var(--s4);padding:var(--s3) var(--s4);max-width:70ch;
  background:var(--surface-2);border-radius:var(--r-sm);
  color:var(--ink-2);font-size:var(--t-sm);line-height:1.6}

/* What the level covers, and what you must show to leave it. Two
   columns on a desk because the lists are long and a single column of
   twenty-four one-line items is a page of scrolling; one column on a
   phone because two would be four words wide. */
.topiclist,.gatelist{list-style:none;margin:0 0 var(--s4);padding:0;
  display:grid;grid-template-columns:1fr 1fr;gap:0 var(--s6)}
.topiclist li,.gatelist li{position:relative;padding:var(--s1) 0 var(--s1) var(--s4);
  font-size:var(--t-sm);line-height:1.55;overflow-wrap:anywhere}
/* A dot for a topic. */
.topiclist li::before{content:'';position:absolute;left:var(--s1);top:11px;
  width:4px;height:4px;border-radius:var(--r-full);background:var(--ink-3)}
/* A tick for a criterion — the thing a learner must be able to DO. Ink,
   not green: see the note at the top of this block. */
.gatelist li::before{content:'\2713';position:absolute;left:0;top:var(--s1);
  font-size:var(--t-xs);color:var(--ink-3)}

/* The upload form, tucked behind a summary so six levels are six lines
   rather than six forms. */
.packadd-wrap{margin:var(--s4) 0 0}
.packadd-wrap>summary{cursor:pointer}
.packadd-wrap>summary:focus-visible{outline:none;box-shadow:var(--focus);border-radius:var(--r-sm)}

/* Who a level or a piece is for, once it is switched on. A row, so the
   label, the select and the button read as one sentence; wrapping, so
   they still do on a phone. */
.vispick{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2) var(--s3);
  margin:var(--s4) 0 0;padding-top:var(--s3);border-top:1px solid var(--line)}
.vispick label{font-size:var(--t-xs);letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-3);font-weight:600;margin:0}
.vispick select{min-width:0;max-width:100%;font:inherit;font-size:var(--t-sm);
  padding:var(--s1) var(--s2);min-height:36px}
.vispick .btn{margin-top:0}
.vispick .fineprint{flex:1 1 100%;margin-top:0}

/* THE NO-JAVASCRIPT DRAG. A select of the classes this person may
   change, and a button. It is the fourth column of a .printlist row on a
   desk and a full-width line underneath on a phone. */
.pl-toclass{grid-column:1 / -1;margin-top:var(--s2)}
.toclass{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2);margin:0}
.toclass label{font-size:var(--t-xs);letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-3);font-weight:600;margin:0}
/* A select will not shrink below its widest option unless it is told it
   may, and these options are dates plus level names plus times. Without
   min-width:0 one long class name pushes the whole page wide. */
.toclass select{flex:1 1 220px;min-width:0;max-width:100%;font:inherit;font-size:var(--t-sm);
  padding:var(--s1) var(--s2);min-height:36px}
.toclass .btn{margin-top:0}

/* One piece of repertoire. The Class plans levelpack, with three more
   things on the summary line. */
.piece .facts{margin:var(--s3) 0 var(--s4)}
.pc-level{font-weight:600}
.pc-key{font-variant-numeric:tabular-nums}
.piece>summary{gap:var(--s2) var(--s3)}
.piece .printhead{margin:var(--s4) 0 var(--s2)}
.piece>.del,.piece .fineprint{margin-top:var(--s3)}
.piece{padding-bottom:var(--s3)}

@media (max-width:720px){
  .topiclist,.gatelist{grid-template-columns:1fr}
  .vispick{align-items:flex-start;flex-direction:column;gap:var(--s2)}
  .vispick .btn{margin-top:0}
  .toclass{align-items:stretch;flex-direction:column}
  .toclass select,.toclass .btn{width:100%}
}

/* =====================================================================
   3.9.15 — the register that goes somewhere, the picker that explains
   itself, and the way back into the past

   Four small things, and between them they add exactly one new shape to
   the sheet: a ROW OF CHIPS WITH A REASON ON EACH. Everything else here
   is an existing pattern given one more place to appear.

   COLOUR. Nothing below introduces one and nothing below borrows a
   state colour. The learner's name on a register becomes a link, so it
   takes the accent — that is the accent doing its only job, marking
   something you can operate. "Past classes" is not a state anybody is
   in and is not amber; it is a fact about which way you are facing, so
   it is said in words, in the page's own heading, and drawn in ink.

   NOTHING SCROLLS SIDEWAYS. A chip now carries a name AND a sentence
   about that person, and both are somebody else's strings — so a chip
   wraps inside itself and the row of them wraps as well. The search row
   wraps, and its input is allowed to shrink (min-width:0), which is the
   one thing a flex child will not do unless it is told it may.
   ===================================================================== */

/* The name on a register, now that it goes to the person page. It is a
   link and looks like one; the "came early / stayed on" case keeps its
   quieter weight without giving up the underline, because a link that
   is not obviously a link is a link nobody presses. */
.who a.nm{color:var(--accent);text-decoration:underline}
.who a.nm.crossed{color:var(--ink-2)}
.who a.nm:hover{color:var(--accent-hover)}

/* 3.9.53 — Simon, 17 Sep: "all of these additional people / add more
   people options should be hidden within an accordion." The whole
   "Somebody else in the room" panel (_add_by_name.php — the free-text
   box, the likely-to-be-here chips, the search-everyone details, the
   fineprint) now sits behind one plain trigger, same visual weight as
   the register's other "→" triggers. */
details.addanother{margin:var(--s3) 0 0}
details.addanother > summary{font-size:var(--t-base)}
details.addanother[open] > summary{margin-bottom:var(--s3)}

/* The likely-to-be-here list. Its chips are the 3.9.7 chips; only the
   flex row is repeated here, because those chips used to exist solely
   inside .picklist and this list sits outside it. */
.pickgroup{margin:var(--s3) 0 0}
.pickgroup .chips{display:flex;flex-wrap:wrap;gap:var(--s2);padding:var(--s2) 0 var(--s1)}
/* A chip is a name plus a reason now, so it has to be allowed to be two
   lines on a phone rather than one long line that widens the page. */
.chip{max-width:100%;text-align:left;overflow-wrap:anywhere}

/* Search the whole school. A GET form, so it is a link with a box on
   it: no script, and the result can be reloaded or bookmarked. */
.findrow{display:flex;flex-wrap:wrap;align-items:flex-end;gap:var(--s2) var(--s3);
  margin:var(--s3) 0 var(--s2)}
.findrow label{flex:1 1 100%;margin:0;color:var(--ink-3);
  font-size:var(--t-xs);letter-spacing:.06em;text-transform:uppercase;font-weight:600}
.findrow input{flex:1 1 220px;min-width:0;max-width:100%;font:inherit;
  padding:var(--s2) var(--s3);min-height:40px}
.findrow .btn{margin-top:0}
/* .picklist a is the reports index's block list item, and this Clear is
   an ordinary button that happens to live inside one. Said here rather
   than by loosening that rule, which another screen depends on. */
.picklist .findrow a.btn{display:inline-flex;padding:var(--s2) var(--s4);
  color:var(--ink);text-decoration:none}
.picklist .findrow a.btn:hover{color:var(--accent);background:var(--accent-wash)}

/* A day that has already happened, in the Schedule's day list. A rule
   down the left rather than a tint: the page already says "Past
   classes" in its heading, and this only has to keep saying it while
   somebody scrolls past the heading. */
.daylist .dayrow.past{border-left:2px solid var(--line-2);padding-left:var(--s4)}

/* C125, 3.9.15. "Save register" and the sentence beside it. This was an
   inline style attribute, and style-src 'self' means the browser refused
   it — so the row never centred and nothing said so. A rule in the
   stylesheet is a rule that runs. */
.row.saverow{align-items:center}

/* =====================================================================
   3.9.16 — STAFFING, and the row of learner links

   ONE NEW SHAPE ON THE SHEET: A JOB. It is a card with a heading line, a
   well full of chips, and a row of controls — every part of which this
   file already draws somewhere. What is new is that the chips are FORMS,
   because pressing one appoints somebody, and a form is the only thing
   that can do that without a script (D-61).

   COLOUR. Nothing here invents one and nothing borrows a state colour to
   decorate. Red is a class nobody is teaching, which is the only state
   on the page that costs money; amber is a second teacher missing, which
   costs less; the Assign button is the accent because the accent means
   "you can operate this" and that is precisely what it is for. A "maybe"
   is a DASHED OUTLINE and not a colour: it is worth more than silence
   and it is not a yes, and giving it amber would put it in the same
   language as a class that is short a teacher.

   NOTHING SCROLLS SIDEWAYS. A chip carries somebody else's name, their
   state and their hours, so it wraps inside itself and the row of chips
   wraps as well. The "somebody who has not answered" select holds names
   of unknown length, so it is allowed to shrink (min-width:0) — the one
   thing a flex child will not do unless it is told it may.
   ===================================================================== */

/* The filter row asks two questions — which jobs, and how far ahead — so
   it carries the toolbar's hairline between them. It disappears on a
   phone, where the row is already wrapping and a vertical rule in the
   middle of a wrapped row means nothing. */
.viewnav .sep{width:1px;align-self:stretch;background:var(--line);margin:0 var(--s1)}

/* One teaching job. The rule down the left says which kind at a glance
   while somebody scrolls, and the tag on the row says it in words —
   colour is never the only carrier of a fact. */
.job{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  padding:var(--s4);margin:0 0 var(--s3);box-shadow:var(--lift)}
.job.anchor{border-left:4px solid var(--prob)}
.job.second,.job.ratio{border-left:4px solid var(--attn)}
.jobhead{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s2) var(--s3);
  margin-bottom:var(--s3)}
.jobhead .when{font-weight:600}
.jobhead .cls{color:var(--ink-2);min-width:0;overflow-wrap:anywhere}
/* Pushed to the end on a desk; on a phone it simply wraps to its own
   line, which is why this is margin-left and not a fixed column. */
.jobhead .need{margin-left:auto}
.jobwhy{margin:0 0 var(--s3);font-size:var(--t-sm);color:var(--ink-2);max-width:70ch}

/* The offers. An inset well, because these are answers that came from
   somewhere else — the same treatment a quoted paragraph gets. */
.job .offers{background:var(--surface-2);border-radius:var(--r-sm);
  padding:var(--s3);margin-bottom:var(--s3)}
.job .offers .lbl{display:block;margin-bottom:var(--s2);
  font-size:var(--t-xs);text-transform:uppercase;letter-spacing:.1em;color:var(--ink-3)}
.job .offers p{margin:0}
/* "and two others said they are not free" is a sentence, so it gets a
   line. Left trailing the last chip, its first word — which is the
   number — is orphaned onto the line above. */
.job .offers .also{display:block;margin-top:var(--s1)}

/* A person who has offered, and the button that appoints them. It is a
   form, so it is laid out as one: the name, what they said, and Assign. */
.job .offer{display:inline-flex;flex-wrap:wrap;align-items:center;gap:var(--s2);
  max-width:100%;margin:0 var(--s2) var(--s2) 0;
  padding:var(--s1) var(--s1) var(--s1) var(--s3);
  background:var(--surface);border:1px solid var(--line-2);border-radius:var(--r-full)}
.job .offer .nm{font-size:var(--t-sm);font-weight:600;min-width:0;overflow-wrap:anywhere}
.job .offer .st{font-size:var(--t-xs);color:var(--ink-3)}
.job .offer .btn{margin-top:0}
/* A maybe. Dashed, and nothing else — see the note at the top. */
.job .offer.maybe{border-style:dashed}

.job .actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2) var(--s3);margin-top:0}
.job .actions form.inline{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2)}
.job .actions .btn{margin-top:0}
.job .actions label{margin:0;font-size:var(--t-xs);letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-3);font-weight:600}
.job .actions select{flex:1 1 200px;min-width:0;max-width:100%;
  font:inherit;font-size:var(--t-sm);padding:var(--s1) var(--s2);min-height:36px}

/* Who is carrying what. The Workload bar at card size, so the two
   screens draw the same fact the same way. */
.load{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));
  gap:var(--s3);margin:var(--s3) 0 0}
.ld{border:1px solid var(--line);border-radius:var(--r-sm);padding:var(--s3)}
.ld .nm{display:block;font-weight:600;font-size:var(--t-sm);overflow-wrap:anywhere}
.ld .hrs{display:block;font-size:var(--t-xs);color:var(--ink-2);
  font-variant-numeric:tabular-nums}
.ld .bar{margin-top:var(--s2)}

/* The learner row. It is the ordinary .viewnav; this only stops it
   sitting tight against the heading above it on the one screen that
   never had one. */
.learnernav{margin-top:var(--s2)}

@media (max-width:720px){
  .viewnav .sep{display:none}
  /* On a phone the tag stops being pushed to the end, because there is
     no end to push it to — it is simply the third line of the heading. */
  .jobhead .need{margin-left:0}
  .job .actions{align-items:stretch;flex-direction:column}
  .job .actions form.inline,.job .actions select,.job .actions .btn{width:100%}
  .job .offer{width:100%;justify-content:space-between;border-radius:var(--r-md)}
}

/* =====================================================================
   3.9.16 — HOW MANY LEARNERS, AND TWO MORE PASTES

   Three small additions and not one new idea. The head count is a column
   in lists that already exist; the two new imports are the import screen
   with a different table in the middle; the tags they show are the
   .mctags chip, borrowed and made read-only.

   COLOUR. Nothing here invents one and nothing borrows a state colour to
   decorate. A head count is INK — it is a number, not a state, and a
   room of six is not "good". The only colour in this block arrives
   through .tag.warn, on a class that is over the 8:1 ratio, which IS a
   state and is the one thing on these rows that costs money. It says
   "over 8:1" in words as well, because colour is never the only carrier
   of a fact.

   NOTHING SCROLLS SIDEWAYS. The day list grows a fourth column, so every
   track is sized and the count wraps under the class name on a phone
   exactly as the teacher's name already does. The order preview is a
   six-column table, which is what .tblwrap is for. A tag chip carries
   somebody else's string — "FUNDAMENTALS: Attended First Introductory
   Class" is 47 characters — so it wraps inside itself.
   ===================================================================== */

/* THE DAY LIST, with a fourth column. The three that were there are
   unchanged; this only makes room. Sized, like its neighbours, because
   an `auto` track resolves per row and that is what used to make the
   column beside it move as the eye ran down the page. */
.daycls li{grid-template-columns:104px minmax(0,1.3fr) minmax(0,0.9fr) minmax(0,1fr)}
.daycls li .n{color:var(--ink-2);font-variant-numeric:tabular-nums;min-width:0;
  overflow-wrap:anywhere}
.daycls li .n .tag{margin-left:var(--s1)}

/* The head count in the two schedule tables. Tabular figures so a column
   of them lines up, and the tag beneath rather than beside it on a
   narrow screen. */
.heads{font-variant-numeric:tabular-nums}
.heads .t{display:block;font-size:var(--t-xs);color:var(--ink-3)}
.heads .tag{margin-top:var(--s1);max-width:100%;overflow-wrap:anywhere}

@media (max-width:640px){
  /* Both extra spans join the second column, under the class name — the
     same thing .w already does, for the same reason: at this width there
     is one column of content and a row of four would be four words wide.

     3.9.68 — and the TEMPLATE has to be restated here. The four-column
     rule above is not in a media query and comes later in the file, so it
     was quietly winning over the two-column rule written for phones: on a
     360px screen every class ran in a 66px column and read "Fundamenta…".
     Simon, 19 Sep, from a phone: "some pages are not properly readable."
     Everything now sits in one column beside the time, and a long word
     breaks rather than being cut off. */
  .daycls li{grid-template-columns:96px minmax(0,1fr);row-gap:2px}
  .daycls li .l,.daycls li .w,.daycls li .n{grid-column:2;min-width:0;overflow-wrap:anywhere}
}

/* The row that says there are three imports. The ordinary .viewnav; this
   only stops it sitting tight under the page heading. */
.importnav{margin-top:var(--s2)}

/* A class an imported order would land on. One per line, because an
   order can reach two classes on a day that runs the same level twice
   and a comma between them would read as one long class name. */
.orders .lands{display:block;overflow-wrap:anywhere}
.orders .muted{display:block;font-size:var(--t-xs)}

/* A tag, shown and not operable. The .mctags chip with its controls
   taken away: same shape, so a tag looks like a tag wherever it appears,
   and no button, because this screen changes nothing in Mailchimp. */
.mctag{display:inline-block;max-width:100%;margin:0 var(--s1) var(--s1) 0;
  padding:var(--s1) var(--s3);border:1px solid var(--line-2);border-radius:var(--r-full);
  background:var(--surface);font-size:var(--t-xs);overflow-wrap:anywhere}
/* The protected one, marked the way the person's own page marks it:
   dashed and quieter, never louder. */
.mctag.locked{background:var(--surface-2);border-style:dashed;color:var(--ink-2)}
.mcdiff .tag{margin-right:var(--s1)}

/* The one tick on the order preview. A checkbox and a sentence, laid out
   as a sentence with a box in front of it — the box is the control and
   the words are what it does, so they sit on one line at the top and the
   explanation runs on underneath. */
.tickbox{display:flex;align-items:flex-start;gap:var(--s3);margin:var(--s3) 0;
  padding:var(--s3);background:var(--surface-2);border-radius:var(--r-sm);
  font-size:var(--t-sm);line-height:1.55}
.tickbox input{margin-top:3px;flex:0 0 auto;width:18px;height:18px}
.tickbox span{min-width:0;overflow-wrap:anywhere}

/* =====================================================================
   3.9.17 — C127. A DISCLOSURE THAT DOES NOT LOOK LIKE ONE.
   =====================================================================
   Simon, 9 Sep 2026, on What can you cover?: "there's no background
   colour on the page, so it's very hard to know that the 'away, or
   answering several' thing is actually clickable."

   He was right, and the cause is three rules up at C63. To stop Firefox
   drawing an inconsistent triangle, every `summary` in Arcanté has its
   marker removed — `list-style:none`, `::-webkit-details-marker` and
   `::marker` all suppressed. The school switcher and the Office menu
   each draw their own chevron afterwards, so they read as controls. Any
   OTHER disclosure got the marker taken away and nothing put back, and
   has been rendering as a bold line of text ever since.

   So this is not "style the away panel". It is: the house disclosure
   pattern has been missing its affordance since 3.9.6, on every screen
   that used it without knowing it had to supply its own arrow. Fixed at
   the pattern, not at the one screen Simon happened to be looking at.

   THE RULE: a summary that carries no chevron of its own gets one here.
   `.tenant`, `.office` and `.learners` opt out because they draw a
   `.car` themselves.

   Colour is not doing this job on its own — there is a triangle, a
   border, a hover and a focus ring, so it reads as a control in
   greyscale and to somebody who cannot see the accent at all.
   ================================================================== */
details:not(.tenant):not(.office):not(.learners) > summary{
  cursor:pointer;
  display:flex;
  align-items:center;
  gap:var(--s2);
  border-radius:var(--r-sm);
}
details:not(.tenant):not(.office):not(.learners) > summary::before{
  content:'\25B8';                 /* ▸ — rotates to ▾ when open */
  display:inline-block;
  font-size:var(--t-sm);
  line-height:1;
  color:var(--ink-3);
  transition:transform .12s ease;
  flex:none;
}
details[open]:not(.tenant):not(.office):not(.learners) > summary::before{
  transform:rotate(90deg);
}
details:not(.tenant):not(.office):not(.learners) > summary:hover{
  color:var(--accent);
}
details:not(.tenant):not(.office):not(.learners) > summary:hover::before{
  color:var(--accent);
}
/* Keyboard users must see where they are. The global reset removed the
   marker; it must not also remove the only sign of focus. */
details > summary:focus-visible{
  outline:2px solid var(--accent);
  outline-offset:2px;
}
@media (prefers-reduced-motion: reduce){
  details > summary::before{transition:none}
}

/* The away panel specifically: a real card, so it reads as a thing you
   open rather than a heading you have scrolled past. It was carrying
   `.band`, which draws a section rule across the page — the visual
   language of a divider, which is the opposite of what it is. */
.avaway{
  border:1px solid var(--line-2);
  border-radius:var(--r-md);
  background:var(--surface);
  padding:var(--s3) var(--s4);
  margin:0 0 var(--s5);
}
.avaway > summary{font-weight:600;padding:var(--s1) 0}
.avaway[open]{padding-bottom:var(--s4)}
.avaway[open] > summary{
  margin-bottom:var(--s3);
  padding-bottom:var(--s3);
  border-bottom:1px solid var(--line);
}

/* =====================================================================
   3.9.17 — THE LEARNERS HUB

   A list of people where every row opens where it stands, and the same
   markup serves two readers: the office, with five columns, and a
   teacher, with four different ones. One block of CSS and two grid
   declarations, because they are two views of one person and not two
   screens.

   IT IS NOT A TABLE, and that is a decision rather than an oversight.
   Every row is a <details> and a <details> cannot be a <tr>; a table
   whose rows expand needs either JavaScript or a second row per person
   that is empty most of the time. So the row is a grid, the column heads
   are a matching grid above it, and below 760px both stack — the heads
   disappear and each cell carries its own words.

   COLOUR. Nothing here invents one. The accent appears on exactly two
   things and both are interactive: the chosen chip, and the focus ring.
   The state colours arrive only through .tag, which is the house pill
   and already carries a word inside it. The "nobody has spoken to them"
   line is the one place a number could have been left to a colour, and
   it is not: it reads "last spoken to 63 days ago" or "nobody has ever
   logged contact" in full, and the red is on top of the sentence rather
   than instead of it.

   NOTHING SCROLLS SIDEWAYS. Every column that carries somebody's typed
   text is a minmax() with a zero floor and wraps inside itself — a next
   action is 255 characters of free text and one of them will be a URL.
   ===================================================================== */

/* Search, alone on its line and first on the page. */
.lhfind{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap;margin:0 0 var(--s3)}
.lhfind input[type=search]{flex:1 1 260px;min-width:0;margin:0}
.lhfind .btn{margin-top:0}

/* The state chips. A row of links, not a segmented control: they are
   five separate destinations and dressing them as one control is what
   made "not converted" look like a sixth state. */
.lhchips{display:flex;gap:var(--s2);flex-wrap:wrap;align-items:center;margin:0 0 var(--s3)}
.lhchips .lab{font-size:var(--t-xs);text-transform:uppercase;letter-spacing:.1em;
  color:var(--ink-3);font-weight:700}
.lhchips .chip{text-decoration:none;white-space:normal;overflow-wrap:anywhere;max-width:100%}
.lhchips .chip.on{background:var(--accent);color:var(--accent-ink);border-color:var(--accent);
  font-weight:700}
.lhchips .chip .n{font-variant-numeric:tabular-nums;opacity:.75;margin-left:var(--s1)}

.lhmore{margin:0 0 var(--s4);font-size:var(--t-sm)}
/* WCAG 2.2 target size: a control somebody taps on a phone is at least
   24px tall. A bare line of 13px text with a chevron in front of it is
   21px, which is a control you miss. */
.lhmore > summary{padding:var(--s2) 0;min-height:24px}
.lhmore .lhnarrow{display:flex;gap:var(--s2);flex-wrap:wrap;align-items:center;
  margin:var(--s3) 0}
.lhmore .lhnarrow select{margin:0}
.lhmore .lhnarrow .btn{margin-top:0}

/* ---- the list ---- */
.lhlist{border-top:1px solid var(--line);margin:var(--s4) 0 0}

/* THE HOUSE DISCLOSURE PATTERN HAS TO BE OUT-SPECIFIED HERE, and the
   selector says so rather than pretending. C127 makes every summary in
   Arcanté a flex row and draws it a chevron, because the global reset
   removed the browser's own marker and a disclosure with no affordance
   reads as a bold line of text. A row on this list is a grid of columns
   instead — so these rules carry one :not() more than they look as
   though they need, to match that rule's weight and win on order.

   THE CHEVRON STAYS. It is the affordance, it is the one thing on the
   row that says "this opens", and it gets a column of its own at the
   front rather than being suppressed. The heads carry an empty first
   cell so the two grids line up. */
.lhhead,
.lhlist details.lrow:not(.tenant) > summary{
  display:grid;
  gap:var(--s3);
  align-items:center;
  padding:var(--s3) var(--s2);
}
/* EVERY COLUMN IS SIZED, AND NOT ONE OF THEM IS `auto`. Each row is its
   own grid, so an `auto` track resolves against that row's content and
   the columns after it start somewhere different on every line — which
   is the fault 3.9.16 fixed on Class plans and on Enquiries, and which
   C130 has just had to fix on Enquiries a second time. The name is the
   column somebody reads down; it must not move.

   Every track that carries typed text has a zero floor as well, so a
   255-character next action wraps rather than widening the page. The
   14px at the front is the chevron; the 56px at the end is a number. */
.lhlist.office .lhhead,
.lhlist.office details.lrow:not(.tenant) > summary{
  grid-template-columns:14px minmax(0,1.6fr) minmax(0,1.1fr) 104px minmax(0,1.4fr) 56px;
}
.lhlist.teach .lhhead,
.lhlist.teach details.lrow:not(.tenant) > summary{
  grid-template-columns:14px minmax(0,1.7fr) minmax(0,1.2fr) minmax(0,0.9fr) 56px;
}
.lhhead{
  font-size:var(--t-xs);text-transform:uppercase;letter-spacing:.1em;color:var(--ink-3);
  border-bottom:1px solid var(--line-2);background:var(--surface-2);
}
.lrow{border-bottom:1px solid var(--line)}
.lhlist details.lrow:not(.tenant) > summary:hover{background:var(--surface-2)}
.lhlist details.lrow[open]:not(.tenant) > summary{background:var(--surface-2)}

.lrow .c-name{min-width:0}
.lrow .nm{display:block;font-weight:600}
.lrow .sub{display:block;font-size:var(--t-xs);color:var(--ink-3);overflow-wrap:anywhere}
.lrow .c-on,.lrow .c-owed{min-width:0;font-size:var(--t-sm);color:var(--ink-2);
  overflow-wrap:anywhere}
.lrow .c-on b,.lrow .c-owed b{display:block;color:var(--ink);font-weight:600}
.lrow .c-att{font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}
.lrow .c-inst,.lrow .c-state{min-width:0}
.lrow .c-inst .tag,.lrow .c-state .tag{max-width:100%;overflow-wrap:anywhere}

/* How long since anybody logged speaking to them (E-6). The words carry
   the fact; the colour only agrees with them. */
.lrow .since{display:block;font-size:var(--t-xs);color:var(--ink-3)}
.lrow .since.late{color:var(--prob);font-weight:700}

/* ---- the panel a row opens into ---- */
.lpanel{padding:var(--s3) var(--s2) var(--s5);background:var(--surface-2);
  border-top:1px solid var(--line);font-size:var(--t-sm)}
.lpanel .lfacts{display:grid;grid-template-columns:auto minmax(0,1fr);
  gap:var(--s1) var(--s4);margin:0 0 var(--s3)}
.lpanel .lfacts dt{color:var(--ink-3);font-size:var(--t-xs);text-transform:uppercase;
  letter-spacing:.07em;white-space:nowrap}
.lpanel .lfacts dd{margin:0;min-width:0;overflow-wrap:anywhere}
.lpanel .lact{display:flex;gap:var(--s2);align-items:flex-end;flex-wrap:wrap;
  margin:var(--s3) 0 0}
.lpanel .lact label{margin:0;font-size:var(--t-xs);color:var(--ink-3);
  text-transform:uppercase;letter-spacing:.07em;flex:1 0 100%}
.lpanel .lact input[type=text]{flex:1 1 220px;min-width:0;margin:0}
.lpanel .lact .btn{margin-top:0}
/* The one control on an open row that leaves the page, and it says so. */
.lpanel .lgo{display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap;
  margin:var(--s4) 0 0}
.lpanel .lgo .btn{margin-top:0}

.lhfoot{padding:var(--s3) var(--s2);font-size:var(--t-xs);color:var(--ink-3);
  background:var(--surface-2);border-top:1px solid var(--line)}

@media (max-width:760px){
  /* One column of content, and the heads go: at this width a row of five
     labels would be five words wide, and every cell already says what it
     is in its own words. The chevron keeps its column so the stack has
     something to hang off and the row still looks like a control. */
  .lhhead{display:none}
  .lhlist.office details.lrow:not(.tenant) > summary,
  .lhlist.teach details.lrow:not(.tenant) > summary{
    grid-template-columns:14px minmax(0,1fr);
    gap:var(--s1) var(--s3);
    align-items:start;
  }
  .lhlist details.lrow:not(.tenant) > summary > span{grid-column:2}
  .lrow .c-att{text-align:left}
  .lpanel .lfacts{grid-template-columns:minmax(0,1fr)}
  .lpanel .lfacts dt{margin-top:var(--s2)}
  .lpanel .lact input[type=text]{flex:1 1 100%}
}


/* =====================================================================
   3.9.18 — TICKING PEOPLE, AND THE BAR THAT ACTS ON THEM.

   Simon, 10 Sep 2026: "I need to be able to select all the enrolled
   learners in Arcanté, and mark them as 'active learners'."

   THE TICK BOX IS BESIDE THE ROW, NOT IN IT. A <details> hides
   everything but its summary, so a box inside the row would have to live
   in the summary — where a click is also a click on the thing that opens
   the row. Sixty ticks would be sixty open panels. So each row becomes a
   two-column grid: the box, then the whole disclosure. The heads carry a
   matching empty cell so the columns still line up down the page, which
   is the fault 3.9.16 fixed twice and C130 fixed again.

   The rule under a row moves to the wrapper for the same reason a
   register row's rule has to be unbroken: a border on the disclosure
   alone would stop short of the tick box and leave a notch in every
   line.
   ===================================================================== */
.lhlist.pick .lpickrow{
  display:grid;
  grid-template-columns:34px minmax(0,1fr);
  align-items:start;
  border-bottom:1px solid var(--line);
}
.lhlist.pick .lpickrow .lrow{border-bottom:0}
/* A generous target, because this is a box somebody hits forty times in
   a row. The whole cell is the label, so the miss is forgiving. */
.lhlist.pick .lpick{
  display:flex;align-items:center;justify-content:center;
  align-self:stretch;min-height:44px;
  margin:0;cursor:pointer;
}
/* 24px, which is the WCAG 2.2 AA target size and what the browser suite
   holds every control on this page to. The house default for a tick box
   is 18px inside a label.check, and that is right for a form somebody
   fills in once; this one is hit forty times down a list on a phone, and
   a mis-tap here puts a tag on the wrong person. */
.lhlist.pick .lpick input{margin:0;width:24px;height:24px}
.lhlist.office.pick .lhhead{
  grid-template-columns:34px 14px minmax(0,1.6fr) minmax(0,1.1fr) 104px minmax(0,1.4fr) 56px;
}
.lhlist.teach.pick .lhhead{
  grid-template-columns:34px 14px minmax(0,1.7fr) minmax(0,1.2fr) minmax(0,0.9fr) 56px;
}

/* ---- the bar under the list ---- */
.lhbulk{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  padding:var(--s5);margin:var(--s5) 0;box-shadow:var(--lift);
}
.lhbulk > h2:first-child{margin-top:0}
.lhbulk .lead{color:var(--ink-2);font-size:var(--t-sm);line-height:1.6;margin:0 0 var(--s4)}
.lhbulk select,.lhbulk input[type=text]{margin:0}
.lhbulk .bwhat{margin:var(--s4) 0 0}
/* Same 24px floor as the tick boxes, and for the same reason: this pair
   decides whether a tag goes ON sixty people or comes OFF them. */
.lhbulk .bwhat label.check input{width:24px;height:24px;margin-top:0}
/* The two buttons that write, side by side and wrapping rather than
   ever pushing the page sideways. */
.lhbulk .bgo{display:flex;gap:var(--s3);flex-wrap:wrap;margin:var(--s5) 0 var(--s2)}
.lhbulk .bgo .btn{margin-top:0}
/* WHAT THE SECOND BUTTON WILL ACTUALLY DO, in words, before it is
   pressed. It is a bordered well rather than a colour, because a
   sentence somebody has to read before acting on sixty people should not
   depend on seeing an accent. */
.lhbulk .bsays{
  background:var(--surface-2);border:1px solid var(--line-2);border-radius:var(--r-sm);
  padding:var(--s3);margin:0;font-size:var(--t-sm);line-height:1.6;color:var(--ink-2);
}
.lhbulk .bexport{display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap;
  margin:var(--s5) 0 0}
.lhbulk .bexport .btn{margin-top:0}
.lhbulk .bexport span{flex:1 1 260px;min-width:0}
/* The queue. Its own rule above it, because it is a different job from
   everything above: it sends nothing new. */
.lhbulk .lhwait{
  border-top:1px solid var(--line);margin:var(--s5) 0 0;padding:var(--s4) 0 0;
}
.lhbulk .lhwait p{font-size:var(--t-sm);line-height:1.6;margin:0 0 var(--s3)}
.lhbulk .lhwait .btn{margin-top:0}

@media (max-width:760px){
  /* The row stacks into one column at this width and the tick box keeps
     its own, so the stack still has something to hang off — the same
     decision the chevron column gets six rules up. */
  .lhlist.pick .lpickrow{grid-template-columns:30px minmax(0,1fr)}
  .lhbulk{padding:var(--s4)}
  .lhbulk .bgo .btn{flex:1 1 100%}
}

/* =====================================================================
   3.9.17 — C130. THE SUMMARIES THAT ARE THEIR OWN LAYOUT.

   C127, thirty lines up, gave every disclosure in Arcanté a chevron and
   made its summary a flex row so the chevron sits beside the words. That
   was right, and it fixed a real fault, and it also silently took the
   layout away from three summaries that had one of their own — because
   its selector carries three :not() classes and theirs carried one class
   each, so it out-specifies them wherever they appear.

   The visible consequence was on ENQUIRIES, which is the sales tracker
   and is used every day: each row is a five-column grid so that the
   names line up down the page, and it had quietly become a flex row in
   which the second column started somewhere different on every line.
   That is precisely the fault 3.9.16 fixed on this screen and on Class
   plans, arriving again through the back door.

   Found by the browser suite on 10 September — and only then, because
   the suite had been crashing earlier in its run since C128 and never
   reached this check. Two lessons, both worth writing down: a global
   rule about `display` reaches further than the thing it was written
   for, and a test suite that stops early is a test suite that is not
   running.

   THE FIX IS NOT TO WEAKEN C127. Every one of these keeps its chevron;
   they simply take their own display back, and the grid ones give the
   chevron a column of its own rather than letting it consume one meant
   for content. The selectors carry the same weight as C127's on purpose
   and win on order, which is stated here rather than left to be
   rediscovered by whoever moves this block.
   ===================================================================== */

/* Enquiries: five columns, and now a sixth at the front for the arrow. */
details.erow:not(.tenant):not(.office) > summary{
  display:grid;
  grid-template-columns:14px minmax(150px,1.3fr) minmax(0,1fr) 108px 104px minmax(0,0.9fr);
}
@media (max-width:720px){
  /* The stack, with the arrow keeping its column so the row still reads
     as a control rather than as a paragraph. */
  details.erow:not(.tenant):not(.office) > summary{
    grid-template-columns:14px minmax(0,1fr);
    align-items:start;
  }
  details.erow:not(.tenant):not(.office) > summary > span{grid-column:2}
}

/* Delete, on the Accounts table: a word in a sentence, not a row of its
   own. It was inline before C127 and it is inline again. */
details.del:not(.tenant):not(.office) > summary{display:inline}

/* =====================================================================
   3.9.19 — WHO IS TEACHING THIS

   Simon, 10 September 2026: "I'm trying to take Javier out of the class
   tonight... I can't find where to do that ANYWHERE. The obvious place
   would be to go to the class or the day itself."

   So the staffing control is now on the class and on the day, at the top
   of the occurrence panel, and on Staffing's "Already staffed" list. All
   three are the same two forms and reuse .seat, which has laid out a
   select-and-a-button on one line since 3.8.0 — there is nothing new
   here about how a seat is set, only about where the reader finds it.

   No colour of its own. The panel is a card like every other card; the
   only colour on it is the amber over-ratio tag, which is a state, and
   the words beside it carry the same fact for anybody who cannot see it.
   ===================================================================== */
.card.teaching table.teachnow{width:100%;border-collapse:collapse}
.card.teaching table.teachnow th{
  text-align:left;white-space:nowrap;width:1%;
  padding:var(--s2) var(--s3) var(--s2) 0;
  color:var(--ink-2);font-size:var(--t-sm);font-weight:600;vertical-align:middle;
}
.card.teaching table.teachnow td{padding:var(--s2) 0;vertical-align:middle}
.card.teaching table.teachnow td.who{padding-right:var(--s4);white-space:nowrap}
/* The two forms in the second-teacher row: side by side while there is
   room, wrapping onto their own lines rather than off the edge. */
.card.teaching table.teachnow td.act{
  display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap;
}
.card.teaching table.teachnow tr + tr{border-top:1px solid var(--line)}

@media (max-width:720px){
  /* Four rigid columns will not fit a phone, and nothing in this product
     scrolls sideways. Each row becomes a small stack: the label, the
     name, then the control under both. */
  .card.teaching table.teachnow,
  .card.teaching table.teachnow tbody,
  .card.teaching table.teachnow tr,
  .card.teaching table.teachnow th,
  .card.teaching table.teachnow td{display:block;width:auto}
  .card.teaching table.teachnow th{padding:var(--s3) 0 0}
  .card.teaching table.teachnow td.who{white-space:normal;padding:0 0 var(--s1)}
  .card.teaching table.teachnow td.act{padding-bottom:var(--s3)}
  .card.teaching table.teachnow td.act .seat{flex-wrap:wrap}
}

/* =====================================================================
   3.9.19 — STAFFING: EVERYTHING, THE WHOLE TERM IN ONE LIST

   Simon, 10 September 2026: "I should still have the option to show ALL
   classes/events so that I can just change the staffing there."

   WHY THIS IS NOT A TABLE, WHICH IS THE ONLY INTERESTING DECISION HERE.
   The list it replaced was a six-column table.cards, and table.cards
   turns into stacked cards below 640px — which is right for a table of
   facts and wrong for this one. Every row here carries TWO selects and
   up to three buttons, and between 640px and about 900px those columns
   cannot be made to fit: a table would have kept its shape and pushed
   the controls off the right-hand edge into .tblwrap's sideways
   scrollbar. A sideways scrollbar is exactly what this product does not
   do (see the top of this file), and "it only scrolls inside the box"
   is the excuse that lets it in.

   So each row is its own grid instead. A grid track can be told to be
   no wider than its content allows — minmax(0,Nfr) — which means the
   row cannot be forced wider than the page by anything inside it, and
   it collapses to one column at the width where four stop fitting
   rather than at the width a table happens to break. Everything that
   holds a string somebody else typed (a venue, a level, a teacher's
   name on a button face) is allowed to break inside itself.

   COLOUR IS NEVER ALONE HERE. The left bar is red for a date with
   nobody on it and amber for one still wanting somebody, and every one
   of those rows also carries a tag that says so in words.
   ===================================================================== */

/* The jump row. Fragment links to the month headings — the whole of
   "how do I get to tonight's class in two hundred rows" without a line
   of script. */
.alljump{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2);
  margin:0 0 var(--s4);padding:var(--s2) var(--s3);
  background:var(--surface-2);border-radius:var(--r-sm)}
.alljump .lbl{font-size:var(--t-xs);text-transform:uppercase;letter-spacing:.1em;
  color:var(--ink-3);font-weight:600}
/* A link, so accent — and a target somebody can hit (WCAG 2.2 AA). */
.alljump a{display:inline-flex;align-items:center;gap:var(--s1);
  min-height:24px;padding:var(--s1) var(--s2);font-size:var(--t-sm)}
.alljump a .tag{margin:0}

/* The month heading. The counts sit on it for the C128 reason: a piece
   of work somebody can picture finishing. */
.allmonth{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s2) var(--s3);
  margin:var(--s6) 0 var(--s3);font-size:var(--t-md);
  padding-bottom:var(--s2);border-bottom:1px solid var(--line)}
.allmonth .muted{font-size:var(--t-sm);font-weight:400}
.allmonth .tag{margin-left:auto}

.everylist{list-style:none;margin:0;padding:0}
.everylist .allrow{
  display:grid;
  grid-template-columns:112px minmax(0,1fr) minmax(0,1.1fr) minmax(0,1.7fr);
  gap:var(--s2) var(--s4);align-items:start;
  padding:var(--s3);margin-bottom:var(--s2);
  border:1px solid var(--line);border-left:3px solid var(--line);
  border-radius:var(--r-md);background:var(--surface);
}
/* State, and never the only carrier of it — the tag beside it says the
   same thing in words. */
.everylist .allrow.needs{border-left-color:var(--prob)}
.everylist .allrow.wants{border-left-color:var(--attn)}
/* An event is not a taught class and has nothing to set, so it is
   quieter than its neighbours. That is weight, not colour. */
.everylist .allrow.isevent{background:var(--surface-2)}

.everylist .ar-when{font-size:var(--t-sm);min-width:0}
.everylist .ar-when strong{display:block}
.everylist .ar-when .t{display:block;font-size:var(--t-xs);color:var(--ink-3);
  font-variant-numeric:tabular-nums}
.everylist .ar-what{min-width:0;overflow-wrap:anywhere}
.everylist .ar-what strong{display:block;font-size:var(--t-sm)}
/* NOT .sub — that is the sign-in page's caption and it is UPPERCASE.
   Two screens sharing a two-letter class name is how a sentence comes
   out shouting; the browser suite caught this one reading back
   "NOBODY IS TEACHING THIS DATE." off a row. */
.everylist .ar-sub{display:block;margin-top:2px;font-size:var(--t-xs);color:var(--ink-2)}
.everylist .ar-state{min-width:0}
.everylist .ar-state .tag{max-width:100%;overflow-wrap:anywhere}

/* The controls. Two seats and up to three buttons, wrapping as they
   need to rather than being held on one line by the .seat rule they
   share with the Schedule. */
.everylist .ar-act{display:flex;flex-wrap:wrap;align-items:center;
  gap:var(--s2);min-width:0}
.everylist .ar-act form.inline{display:flex;flex-wrap:wrap;align-items:center;
  gap:var(--s1);min-width:0;max-width:100%}
.everylist .ar-act select{flex:1 1 132px;min-width:0;max-width:100%;
  font-size:var(--t-sm);padding:var(--s1) var(--s2);min-height:32px}
/* A button face that carries a teacher's name is as long as the name.
   It wraps rather than widening the row. */
.everylist .ar-act .btn{margin-top:0;max-width:100%;
  text-align:left;white-space:normal;overflow-wrap:anywhere}
.everylist .ar-links{display:flex;flex-wrap:wrap;gap:var(--s2);min-width:0}

@media (max-width:900px){
  /* Four tracks stop fitting here — well before a table would have
     admitted it. One column, and the controls go under the words they
     belong to. */
  .everylist .allrow{grid-template-columns:1fr;gap:var(--s1)}
  .everylist .ar-act{margin-top:var(--s2)}
  .everylist .ar-act form.inline,.everylist .ar-links{width:100%}
  /* Stacked, the form is the width of the card — but a name is not
     six hundred pixels long, and a select that wide reads as a mistake. */
  .everylist .ar-act select{flex:1 1 160px;max-width:280px}
  .allmonth .tag{margin-left:0}
}

/* =====================================================================
   3.9.19 — the Curriculum Discussion List, and the two things the
   Curriculum screen now has to say about a gate.

   APPENDED, and nothing above is touched. Every value below is an
   existing token; there is no new colour, no new size and no new radius,
   because a discussion list is not a new kind of object — it is cards,
   prose and a form, all of which this stylesheet already draws.

   COLOUR IS NEVER WHAT TELLS YOU. A question's state is the word "open",
   "being discussed" or "settled", written in the tag; the tag's tint
   agrees with the word and never carries it alone. The same goes for a
   gate under discussion: the sentence says so in full, and the tint on
   the panel is there to help somebody find the sentence again.

   NOTHING SCROLLS SIDEWAYS. There is no table here and no fixed width;
   the one thing that could push a page wide is a pasted line with no
   spaces in it, so every block that holds typed prose gets
   overflow-wrap:anywhere.
   ===================================================================== */

/* A question. The .card is the page's own card; this adds the spacing
   between the parts of one and nothing else. */
.qcard{margin-bottom:var(--s5)}
.qcard .plan-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s3);
  margin-bottom:var(--s2)}
.qcard .plan-head h3{margin:0;font-size:var(--t-md)}
/* Which level, who raised it, when. The line under the title that says
   where in the curriculum the argument is. */
.qmeta{margin:0 0 var(--s3);font-size:var(--t-sm);color:var(--ink-2)}
/* The question itself, at reading width. 70ch is the same measure the
   Curriculum Journey's own paragraphs are set at on the level pages, so
   prose reads the same on both screens. */
.qbody{margin:0 0 var(--s4);max-width:70ch;line-height:1.6;overflow-wrap:anywhere}

/* The discussion. An ordered list because it IS ordered — a conversation
   read out of sequence is a different conversation — with the numbers
   suppressed, because "3." beside a name reads as a ranking. */
.qnotes{list-style:none;margin:0 0 var(--s4);padding:0}
.qnotes li{padding:var(--s3) 0;border-top:1px solid var(--line)}
.qnotes li:first-child{border-top:0;padding-top:0}
.qwho{margin:0 0 var(--s1);font-size:var(--t-sm);font-weight:600}
.qsaid{margin:0;max-width:70ch;font-size:var(--t-sm);line-height:1.6;overflow-wrap:anywhere}

/* What was decided. A well rather than another paragraph: this is the
   answer, and on a settled question it is the thing somebody came to the
   page for. Same inset the Curriculum Journey's quoted prose uses. */
.qdecision{margin:0 0 var(--s4);padding:var(--s3) var(--s4);max-width:70ch;
  background:var(--surface-2);border-radius:var(--r-sm)}
.qdecision h4{margin:0 0 var(--s1);font-size:var(--t-sm);font-weight:600}
.qdecision p{margin:0 0 var(--s2);line-height:1.6;overflow-wrap:anywhere}
.qdecision p:last-child{margin-bottom:0}

/* The three forms: raise, add to the discussion, settle. One rule for
   all three, because they are one shape — a label, a field, a button —
   and three sets of spacing that drifted apart would be three forms that
   look like three different products. */
.qraise{margin:0 0 var(--s5)}
.qraise>summary,.qadd>summary,.qsettle>summary,.qhistory>summary{cursor:pointer}
.qraise>summary:focus-visible,.qadd>summary:focus-visible,
.qsettle>summary:focus-visible,.qhistory>summary:focus-visible{
  outline:none;box-shadow:var(--focus);border-radius:var(--r-sm)}
.qadd,.qsettle,.qhistory{margin-top:var(--s3)}
.qform{margin-top:var(--s3);max-width:70ch}
/* A textarea that will not shrink below the width of the page is the
   single easiest way to make something scroll sideways on a phone.
   max-width:100% and box-sizing settle it at every width. */
.qform textarea,.qform input[type=text],.qform select{
  width:100%;max-width:100%;box-sizing:border-box;font:inherit;font-size:var(--t-sm)}
.qform textarea{line-height:1.6;resize:vertical}
.qform .actions{margin-top:var(--s4)}

/* A settled question, quieter than an open one. The tag says "settled"
   and the heading above it says "Settled" — the left edge is only there
   to help the eye find where one card ends and the next begins. */
.qcard.settled{border-left:3px solid var(--line-2)}

/* THE GATE THAT IS STILL BEING WORKED OUT. On the Curriculum screen,
   above the criteria and never below them: a teacher who has already
   read the list and ticked it has been told too late. */
.gateopen{margin:0 0 var(--s3);padding:var(--s3) var(--s4);max-width:70ch;
  background:var(--attn-wash);color:var(--ink);border-radius:var(--r-sm);
  font-size:var(--t-sm);line-height:1.6}
.gateopen a{color:var(--accent)}

/* The wording a gate USED to have (C85). Behind a disclosure, and set in
   the tertiary ink so that it cannot be mistaken for the live list even
   at a glance — while still clearing 4.5:1, which is why it is --ink-3
   and not a lighter invention. */
.gatewas{margin:0 0 var(--s4)}
.gatewas .gatelist.was li{color:var(--ink-3)}
.gatewas .fineprint{margin:var(--s2) 0 var(--s3);max-width:70ch}

@media (max-width:720px){
  /* The forms are already fluid; what needs saying on a phone is that a
     button spans the line rather than sitting in the middle of it. */
  .qform .actions .btn{flex:1 1 auto}
  .qcard .plan-head{align-items:flex-start;flex-direction:column;gap:var(--s2)}
}

/* =====================================================================
   3.9.19 — THE BETA BANNER on the teachers' Learners screen.

   Simon, 10 September 2026: "just have a giant banner at the top of that
   page saying that it is a BETA version and not yet complete, and that
   Teachers should not use that page until next week."

   GIANT MEANS GIANT. The word BETA is set at --t-2xl, which is the
   largest size in the type scale and larger than the h1 under it — this
   is deliberately the first thing on the page and it is meant to stop
   somebody, not to sit politely beside the heading.

   AMBER, AND THE WORDS SAY IT TOO. --attn is the state colour, used here
   because "this may be wrong" is a state; every fact the colour carries
   is also written out — BETA, "not finished", "do not use it until next
   week" — so nothing is lost to anybody who cannot see the tint.

   NOT DISMISSIBLE. No close control, so no script and no per-viewer
   state to keep. The warning is about whether the data is true, and one
   somebody can put away is one they put away on the first morning and
   never see again on the morning it matters.
   ===================================================================== */
.betabar{
  display:flex;gap:var(--s4);align-items:flex-start;
  margin:0 0 var(--s5);padding:var(--s4) var(--s5);
  background:var(--attn-wash);
  border:2px solid var(--attn);
  border-radius:var(--r-md);
  color:var(--ink);
}
.betabar .bb-tag{
  flex:none;margin:0;
  font-size:var(--t-2xl);line-height:1.05;font-weight:800;letter-spacing:.06em;
  color:var(--attn);
}
.betabar .bb-text{min-width:0}
.betabar p{margin:0 0 var(--s2)}
.betabar p:last-child{margin-bottom:0}
.betabar .bb-lead{
  font-size:var(--t-md);font-weight:700;line-height:1.3;
}
/* The link is the accent, because it is the one thing here to act on. */
.betabar a{color:var(--accent)}

@media (max-width:720px){
  /* The word above the sentence rather than beside it: at 320px a
     34px word and a paragraph on one line leaves the paragraph four
     characters wide, and nothing in this product scrolls sideways. */
  .betabar{flex-direction:column;gap:var(--s2);padding:var(--s3) var(--s4)}
  .betabar .bb-tag{font-size:var(--t-xl)}
}

/* ==================================================================
   3.9.20 — "Doesn't add up": the learners whose record disagrees with
   itself.

   Built on .erow, which is the same disclosure row the four funnel
   lists use, with a grid of its own because the columns are different
   questions: who, what is wrong with them in words, what their stage
   says, what their placement says.

   COLOUR IS NEVER THE ONLY THING SAYING "SERIOUS". The worst kind gets
   a red-toned tag, a heavier left edge and the words "Most serious"
   printed on the row. Take the colour away — a monochrome print, a
   colour-blind reader — and the row still says which one it is.
   ================================================================== */
.mmhead{margin-bottom:var(--s4)}
.mmhead h2{margin:0 0 var(--s1)}

/* The tally: one line per kind, the number first because it is the
   thing being watched go down. */
.mmtally{list-style:none;margin:var(--s4) 0 0;padding:0;display:grid;
      grid-template-columns:repeat(auto-fit,minmax(min(240px,100%),1fr));gap:var(--s3)}
.mmtally-i{border:1px solid var(--line);border-left:3px solid var(--line-2);
      border-radius:var(--r-sm);padding:var(--s3);min-width:0}
.mmtally-i.worst{border-left-color:var(--prob)}
.mmt-v{display:block;font-size:var(--t-xl);font-weight:700;line-height:1.1;
      font-variant-numeric:tabular-nums}
.mmt-k{display:block;font-size:var(--t-sm);font-weight:600;margin-top:var(--s1);
      overflow-wrap:anywhere}
.mmt-h{display:block;font-size:var(--t-xs);color:var(--ink-2);margin-top:var(--s1)}

/* The row. Four columns, and the problem in words takes the most room
   because it is what somebody scanning the page is actually reading. */
.mrow>summary{grid-template-columns:minmax(140px,1fr) minmax(0,1.6fr) minmax(0,0.9fr) minmax(0,0.9fr)}
.mrow.worst{border-left:3px solid var(--prob)}
.m-kind{font-size:var(--t-sm);overflow-wrap:anywhere}
.m-was,.m-is{font-size:var(--t-xs);color:var(--ink-3);overflow-wrap:anywhere}
.m-says{margin:0 0 var(--s4);font-size:var(--t-md);line-height:1.5}
.m-note{margin:var(--s4) 0 0;padding:var(--s3);background:var(--surface-2);
      border-radius:var(--r-sm);font-size:var(--t-sm);line-height:1.6}
.m-note-k{display:block;font-size:var(--t-xs);letter-spacing:.07em;text-transform:uppercase;
      color:var(--ink-3);margin-bottom:var(--s1)}
/* The one-press correction. The button carries a whole sentence, so it
   is allowed to wrap onto two lines rather than being clipped — a
   button whose words are cut off is a button that has stopped saying
   what it will do, which is the whole point of it (3.9.2). */
.m-fix{margin-top:var(--s4)}
.m-fix .btn{white-space:normal;text-align:left;max-width:52rem;line-height:1.4}
.m-nofix{margin-top:var(--s4)}

@media (max-width:720px){
  .mrow>summary{grid-template-columns:1fr}
}

/* 3.9.21 — the ISO week number under the Dashboard greeting. A slightly
   heavier weight than the date beside it, because "which week are we in"
   is the thing somebody is scanning that line for; the ISO year after it
   is quiet, because it only ever matters in the days around New Year. */
.wk{font-weight:600}

/* =====================================================================
   3.9.22 — READING A MESSAGE, AND WHO WILL NOT BE THERE
   =====================================================================
   Nothing new in the system: every rule below is spacing steps, the
   three ink weights and the state colours. The two things that needed
   any rule at all are (1) a proposal row that has to read as a sentence
   with a tick in front of it, and (2) a quoted line, which has to be
   visibly somebody else's words and not the product's.

   Colour is never the only carrier. A proposal that is not ticked says
   "Not ticked:" in words before its reason; the tone on .msgwhy only
   repeats what the words already say. */

/* Who the message matched. */
.msgwho{margin:var(--s2) 0 var(--s3);font-size:var(--t-md);
  display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s2)}
.msgwho .muted{font-size:var(--t-sm)}

/* One proposal: a tick, then a sentence. .tickbox already lays this out;
   these only add the breathing room a stack of them needs and the state
   of one that is already in. */
.msgprop{margin:var(--s2) 0}
.msgprop strong{font-size:var(--t-base)}
.msgprop.done{opacity:.72}
.msgprop.done .tag{margin-top:2px}
/* The reason a box starts unticked. Amber is STATE — "needs attention"
   — which is exactly what an unticked proposal is. */
.msgwhy{color:var(--attn)}

/* Their own words, quoted back. Set apart by an edge and a well rather
   than by italics, which read as emphasis rather than as quotation. */
.msgquote{display:block;margin-top:var(--s1);padding:var(--s2) var(--s3);
  background:var(--surface);border-left:3px solid var(--line-2);
  border-radius:0 var(--r-sm) var(--r-sm) 0;
  color:var(--ink-2);overflow-wrap:anywhere}

/* The first few lines that were NOT read, inside the disclosure. */
.msgign{margin:0;padding-left:var(--s4);color:var(--ink-3);font-size:var(--t-sm)}
.msgign li{margin:var(--s1) 0;overflow-wrap:anywhere}

/* The plan form. Its buttons sit under a stack of ticks, so they need
   the same top rule every other confirm row has. */
.msgplan .actions{margin-top:var(--s5)}

/* ------- who will not be here, on a class page ------- */
.aheadlist{list-style:none;margin:var(--s3) 0;padding:0}
.aheadlist li{padding:var(--s2) 0;border-top:1px solid var(--line);
  display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s1) var(--s3)}
.aheadlist li:first-child{border-top:0}
.ah-who{font-weight:600}
.ah-how{font-size:var(--t-sm);color:var(--ink-3)}
.ah-why{font-size:var(--t-sm);color:var(--ink-2);overflow-wrap:anywhere}

/* One line per person in the "somebody told me" disclosure. It WRAPS
   rather than scrolling: a row of a name, a date picker, a text box and
   a button is wider than a phone, and nothing in Arcanté scrolls
   sideways. min-width:0 on the two controls is what stops a long class
   label pushing the row past the viewport (the same fix .toclass select
   needed in 3.9.16). */
.aheadform{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2);
  padding:var(--s2) 0;border-top:1px solid var(--line)}
.aheadform:first-of-type{border-top:0}
.aheadform .ah-name{font-weight:600;flex:0 0 auto}
.aheadform select{min-width:0;max-width:100%;flex:1 1 14rem}
.aheadform input[type=text]{min-width:0;max-width:100%;flex:1 1 12rem}

/* The active-learner rule, under the Dashboard tiles. */
.activenote{margin:calc(-1 * var(--s2)) 0 var(--s5);max-width:56rem}

@media (max-width:640px){
  .aheadform{flex-direction:column;align-items:stretch}
  .aheadform select,.aheadform input[type=text]{flex:1 1 auto;width:100%}
}

/* ==================================================================
   3.9.23 — the Reports landing list, and framing your own photo
   ================================================================== */

/* A class on the list that has no report filed. It is the THIRD mark on
   the row, not the only one: the cell reads "no report filed" in words
   and carries a red tag, and this is the quiet wash behind them. Colour
   is never the sole carrier of meaning, so removing this line would lose
   emphasis and nothing else. */
tr.owed{background:var(--prob-wash)}
tr.owed:hover{background:var(--prob-wash)}
/* 3.9.73 — a report due today, not yet overdue: amber, not red */
tr.duetoday{background:var(--attn-wash)}
tr.duetoday:hover{background:var(--attn-wash)}

/* ---- framing a photo (D-61: no script, so a form and a preview) ---- */

/* Two columns where there is room, one where there is not. The preview
   is first in the source AND first on a narrow screen, because the thing
   you are looking at has to be above the controls you are changing. */
.framer{display:flex;gap:var(--s5);flex-wrap:wrap;align-items:flex-start;
  margin:var(--s4) 0}
.framer-shows{flex:1 1 220px;min-width:0}
.framer-form{flex:1 1 260px;min-width:0}

/* The three real sizes, on one baseline, so they can be compared. */
.framer-sizes{display:flex;gap:var(--s4);align-items:flex-end;
  margin:0 0 var(--s3)}

/* The whole uploaded picture. max-width keeps it inside its column at
   every width — an 1024px image in a flex child would otherwise be the
   thing that makes the page scroll sideways. */
.framer-whole{display:block;max-width:100%;width:220px;height:auto;
  border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface-2)}

.framer fieldset{border:1px solid var(--line);border-radius:var(--r-sm);
  padding:var(--s3);margin:0 0 var(--s4);min-width:0}
.framer legend{font-size:var(--t-xs);color:var(--ink-3);font-weight:600;
  letter-spacing:.06em;text-transform:uppercase;padding:0 var(--s1)}

/* Nine cells, three across. Each is a real <label> wrapping a real
   radio, so it works from the keyboard and reads correctly aloud; the
   radio is visible rather than hidden, because a hidden control is one
   somebody cannot tell is focused. */
.fg-cells{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s1)}
.fg-cell{display:flex;align-items:center;gap:var(--s1);min-width:0;
  padding:var(--s2);border:1px solid var(--line);border-radius:var(--r-sm);
  font-size:var(--t-xs);color:var(--ink-2);cursor:pointer;line-height:1.2}
.fg-cell span{min-width:0;overflow-wrap:anywhere}
.fg-cell:hover{border-color:var(--accent)}
/* The chosen one is marked by weight and by a border as well as by the
   ticked radio inside it — three things, none of them only colour. */
.fg-cell.on{border-color:var(--accent);background:var(--accent-wash);
  color:var(--accent);font-weight:600}

.framer-steps{display:block}
.fs-step{display:flex;align-items:center;gap:var(--s2);
  padding:var(--s2);border-bottom:1px solid var(--line);
  font-size:var(--t-sm);color:var(--ink-2);cursor:pointer}
.fs-step:last-child{border-bottom:0}
.fs-step.on{color:var(--accent);font-weight:600}

@media (max-width:640px){
  /* Two across rather than three: nine cells carrying words like
     "Bottom right" at three across on a 320px screen is where a page
     starts to scroll sideways, and nothing here does. */
  .fg-cells{grid-template-columns:repeat(2,1fr)}
  .framer-sizes{flex-wrap:wrap}
}

/* ---------------------------------------------------------------------
   3.9.29 — the class screen's new lines, the emergency-only removal, and
   the To do page's equipment list. No colour of its own: every value is
   one of the tokens above, so both themes follow.
   --------------------------------------------------------------------- */
.officesees{margin-top:0}
/* 3.9.53 — Simon, 17 Sep: "it's just too much info where it is right
   now" re the "N still to mark" warning; approved Option C ("red box - C
   please"). It used to be its own .blocked box (the app's red refusal
   panel, shared with a dozen "that did not save" messages elsewhere —
   see the 3.9.46 note above .occpanel .blocked, which stays as written
   for those). Inside Register it is a plain paragraph instead: the bold
   count carries the same weight the box used to, without a border,
   background or its own heading. */
.stillmark{margin:0 0 var(--s3)}
.stillmark strong{color:var(--prob)}
.awaynote{margin:var(--s2) 0;font-size:var(--t-sm)}
/* The flag is a SHAPE as well as a colour, and the words sit beside it. */
.awaysym{font-weight:700;margin-right:var(--s1)}
.tag.away{background:var(--attn-wash);color:var(--attn);border:1px dashed var(--attn)}
.packq .radiorow{display:flex;flex-wrap:wrap;gap:var(--s3)}
.packq .radiorow label.check{margin:0}
label.check.lockup{margin-top:var(--s3);font-weight:600}
details.del.emergency{display:block;margin-top:var(--s1)}
details.del.emergency > summary{display:inline}
.reclist details.del.emergency form.delform,
details.del.emergency form.delform{display:flex;flex-direction:column;align-items:flex-start;
  gap:var(--s1);margin:var(--s2) 0 0;padding:var(--s2);
  border:1px solid var(--prob);border-radius:var(--r-sm);background:var(--prob-wash)}
.delform .delword{max-width:12em}
.equiplist{list-style:none;margin:0;padding:0}
.equiplist li{padding:var(--s2) 0;border-bottom:1px solid var(--line)}
.equiplist li:last-child{border-bottom:0}
.equiplist .eq-what{display:block;margin-top:var(--s1);color:var(--ink-2);overflow-wrap:anywhere}

/* ==================================================================
   3.9.30 — Staff this day (Day page), and a flash of several lines
   ================================================================== */
.flash.lines{white-space:pre-line}
.staffday fieldset{margin:var(--s4) 0 var(--s2)}
.staffday .staffday-off{margin:var(--s2) 0;color:var(--ink-2)}
.staffday label.check .muted{display:block}
table.staffdaylist td{vertical-align:middle}
table.staffdaylist label.check{margin:0}
table.staffdaylist tr.refused td,table.staffdaylist tr.same td{color:var(--ink-2)}
.ar-when .staffdaylink{display:block;margin-top:var(--s1)}

/* ==================================================================
   3.9.30 — the shop's violin answer on the order preview. One fact per
   line (the shop's words, the record's, then the tick), because in a
   narrow card three facts on one line read as one sentence.
   ================================================================== */
td.violin .violin-shop,td.violin .violin-now,td.violin .muted{display:block;overflow-wrap:anywhere}
td.violin .muted{font-size:var(--t-xs)}
td.violin .tickbox.violin-tick{margin:var(--s2) 0 var(--s1);padding:var(--s2)}

/* 3.9.30 — a new buyer on the order preview: two name boxes, then every
   line they bought, one per line. */
.makelist .makename label{display:block;margin-top:var(--s1);font-size:var(--t-xs);color:var(--ink-2)}
.makelist .makename input[type=text]{width:100%;max-width:14rem;min-width:0}
.makelist .makeline{display:block;margin-bottom:var(--s2);overflow-wrap:anywhere}
.makelist .makeline .lands,.makelist .makeline .muted{display:block;font-size:var(--t-xs)}

/* 3.9.32 — the placement an order proposes: what it would set, the facts
   under it one per line, then the tick and (for Starter) the day. */
td.placement .place-to{display:block;font-weight:600;overflow-wrap:anywhere}
td.placement .muted,td.placement .tag{display:block;margin-top:var(--s1);font-size:var(--t-xs);overflow-wrap:anywhere}
td.placement .tag{display:inline-block}
td.placement .tickbox.place-tick{margin:var(--s2) 0 var(--s1);padding:var(--s2)}
td.placement .place-day{display:block;margin-top:var(--s1);font-size:var(--t-xs);color:var(--ink-2)}
td.placement select{max-width:12rem}
.band .placeform select{max-width:12rem}

/* 3.9.34 — change a class's time: the form, and the list of dates to
   confirm. */
details.retime{margin-top:var(--s3)}
details.retime summary{cursor:pointer;font-weight:600}
.retime .retime-times{display:flex;flex-wrap:wrap;gap:var(--s3)}
.retime .field .lab{display:block;font-size:var(--t-sm);font-weight:600}
.retime input[type=time]{max-width:10rem}
.retime fieldset.retime-scope{border:0;margin:var(--s2) 0;padding:0}
.retime-confirm{margin-top:var(--s3);padding:var(--s3);border:1px solid var(--line-2);border-radius:var(--r-sm);background:var(--surface-2)}
.retime-confirm h3{margin:0 0 var(--s2)}
.retime-list{margin:var(--s2) 0;padding-left:var(--s4);overflow-wrap:anywhere}
.retime-list .retime-off{color:var(--ink-2)}

/* 3.9.35 — "Change the time of this class" as its own line on the class
   screen, and as a card on the class's Schedule page.
   3.9.53 — Simon, 17 Sep, on this row sitting beside Move a booking and
   Cancel this date inside the new "Change this" accordion: "I think
   it's a little bit confusing the grey borders... maybe the outside of
   the overall box needs a border, and then the separation between the
   sections could also have a divider but it maybe shouldn't be all the
   way like that." The box these three used to draw round themselves is
   gone — .teachdetail (the "Change this" panel) is now the only box —
   and a plain top hairline separates one row from the next instead,
   matching how every other pair of rows in this panel is divided. Only
   inside .teachdetail: the Schedule's own card use of details.retime is
   untouched. */
details.teachdetail details.retime{padding:var(--s3) 0 0;margin-top:var(--s3);
  border:0;border-top:1px solid var(--line);border-radius:0}
details.retime summary{font-size:var(--t-base)}
.retime-card form.retime{margin-top:var(--s2)}

/* 3.9.36 — Terms, and Add a course. */
table.termlist td{vertical-align:top}
table.termlist .muted{display:block;font-size:var(--t-xs)}
details.termedit{margin-top:var(--s2)}
details.termedit summary{cursor:pointer}
.coursefrm select,.coursefrm input[type=number]{max-width:20rem}

/* 3.9.37 — the learner presets, with the rest under "More filters"; and
   the booking move and customer number lines. */
.learnernav details.morefilters{display:inline-block}
.learnernav details.morefilters summary{cursor:pointer;list-style:none}
.learnernav details.morefilters[open]{display:flex;flex-wrap:wrap;gap:var(--s2);width:100%}
details.movebooking form{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2);margin:var(--s2) 0}
details.movebooking select{max-width:100%}
.shopid{margin-top:var(--s1)}

/* 3.9.38 — Due to move. */
table.duelist td{vertical-align:top}

/* 3.9.39 — cancel a date or a course; link a typed name.
   3.9.53 — inside "Change this" (details.teachdetail), give Cancel this
   date only the same top-hairline treatment as Change the time and Move
   a booking beside it, so the three read as one divided group rather
   than a button next to two boxes. Everywhere else .cancelone keeps its
   plain small top margin, unchanged. */
.cancelone{margin-top:var(--s2)}
details.teachdetail .cancelone{margin-top:var(--s3);padding-top:var(--s3);border-top:1px solid var(--line)}

/* 3.9.53 — "Who will not be here" is now one <details> (heading
   included) rather than an always-open card, so most classes — where
   nobody has told anybody anything — cost one closed row instead of a
   full section. The summary carries the same weight and size as every
   other card's <h2>, so closed it reads exactly like one. */
details.ahead-details > summary{font-size:var(--t-md);font-weight:600;line-height:1.3;cursor:pointer}
details.ahead-details[open] > summary{margin-bottom:var(--s3)}
section.cancelled .flash{margin:0 0 var(--s2)}
.cancel-card form.inline{display:block}

/* 3.9.40 — instant save (public/assets/instant.js): the line on a row that
   says it saved, or did not. The "saved" line fades on its own (CSS, the
   same fade as the cover answer); a failure stays until it is dealt with. */
.instant-status{display:inline-block;margin-left:var(--s1);font-size:var(--t-xs);font-weight:600}
.instant-status:empty{display:none}
.instant-status.is-ok{color:var(--good);animation:av-fade 3s ease-out forwards}
.instant-status.is-bad{color:var(--prob)}
@media (prefers-reduced-motion: reduce){
  .instant-status.is-ok{animation:none}
}
/* 3.9.40 — confirmed first; "may come" folded under the register. */
.headsline{margin:0 0 var(--s2)}
/* 3.9.47 — "Who is teaching this" as one line, matched to the mockup:
   name(s), then a plain "Change" disclosure rather than the full table
   open by default. Nothing new here structurally — .linkish and the
   summary-marker rules above already do the work; this is only spacing
   between the compact line and the toggle beneath it. */
.teachsummary{margin:0 0 var(--s2);font-size:var(--t-base)}
details.teachdetail > summary{display:inline-block}
details.teachdetail[open] > summary{margin-bottom:var(--s3)}
details.maycome{margin-top:var(--s3)}
details.maycome summary{cursor:pointer;font-weight:600}
.revtick{display:block;font-size:var(--t-xs);margin-top:2px}
details.addperson form{margin-bottom:var(--s2)}
details.addperson select{max-width:100%}
/* 3.9.40 — one report box; the four older answers read-only. */
dl.oldanswers{margin:var(--s2) 0;padding:var(--s2);border-left:3px solid var(--line)}
dl.oldanswers dt{font-weight:600;font-size:var(--t-xs)}
dl.oldanswers dd{margin:0 0 var(--s2)}
/* 3.9.40 — report changes waiting, side by side. */
table.rccompare td,table.rccompare th{vertical-align:top}
table.rccompare tr.rcdiff td{background:var(--attn-wash)}
/* 3.9.40 — "Add to classes" lists and "Cancel anyway". */
fieldset.addcls-day{border:0;padding:0;margin:0 0 var(--s2)}
fieldset.addcls-day legend{font-weight:600;font-size:var(--t-xs)}

/* ==================================================================
   3.9.42 — "there should be adequate spacing between all dropdown and
   buttons" (Simon, 17 Sep 2026), on the teaching card and Move a
   booking.

   THE BUG. `.seat` (line ~843) sets gap:var(--s1) — 4px, right for the
   dense Schedule table it was written for. `form.inline.seat` there is
   0,2,1 in specificity, which already beats the later, more targeted
   `details.movebooking form{gap:var(--s2)}` (0,1,2) — more classes beats
   more elements — so that existing rule was silently losing before this
   version and nobody could see why in the rendered page.

   THE FIX is scoped, not a change to `.seat` itself: the Schedule table
   is still meant to be dense. These two selectors are written to beat
   `form.inline.seat` on specificity (three classes, not two) rather than
   relying on source order, which is what lost the last attempt.
   ================================================================== */
.card.teaching form.inline.seat,
details.movebooking form.inline.seat{gap:var(--s3);flex-wrap:wrap}

/* 3.9.42 — "I may need to add more than two teachers (e.g. an observer,
   trainee, etc.)". A note on the register, not a teaching seat — see
   repo_occurrence_extra_staff_add()'s own comment for why this is a
   separate table rather than a third seat column. Prefixed rpt- because
   .card and .chip already mean something else in this file (the card
   above is a general object; a "chip" elsewhere is a clickable filter
   button, not a removable token) and reusing either name here would be
   the same collision under a different name. */
.extrastaff{margin-top:var(--s4)}
.extrastaff h3.printhead{margin:0 0 var(--s2);font-size:var(--t-sm);
  text-transform:uppercase;letter-spacing:.04em;color:var(--ink-2)}
.extrastafflist{list-style:none;margin:0 0 var(--s2);padding:0}
.extrastafflist li{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;
  padding:var(--s1) 0}
.extrastafflist .who{font-weight:500}
.extrastaffadd summary{cursor:pointer}
.extrastaffadd form.inline.seat{margin-top:var(--s2);flex-wrap:wrap}
.extrastaffadd input[type=text]{max-width:220px;flex:1 1 180px}

/* 3.9.42 — the toilets question, asked on its own; and the asterisk on
   the (now required-to-submit) lock-up tick. Reuses .content/.radiorow
   from the follow-up-pack question above (3.9.29) rather than inventing
   a second pattern for the same shape of question. */
fieldset.rpt-toilets .radiorow{display:flex;flex-wrap:wrap;gap:var(--s3)}
fieldset.rpt-toilets .radiorow label.check{margin:0}
.req{color:var(--prob);font-weight:600;margin-left:2px}
details.addcls summary,details.cancelanyway summary{cursor:pointer}

/* 3.9.60 — a class transcript, folded away; long text scrolls inside its own box */
.record details.transcript{margin:var(--s3) 0}
.record .transcript-text{white-space:pre-wrap;max-height:32rem;overflow:auto;padding:var(--s3);border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface-2)}

/* 3.9.67 — "pressing this will:" on the import confirm */
.confirm .willdo-head{margin:0 0 var(--s2)}
.confirm ul.willdo{margin:0 0 var(--s3);padding-left:var(--s5)}
.confirm ul.willdo li{margin:0 0 var(--s1)}

/* 3.9.69 — the dashboard clock: tabular digits so the seconds do not make the line wobble */
.pagehead .clock{font-variant-numeric:tabular-nums}

/* 3.9.69 — the copyable address list under a cohort */
.maillist textarea.mails{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:var(--t-sm);white-space:pre;line-height:1.5}

/* 3.9.71 — typed topics and pieces waiting for the office, on the report
   form; and the review row's inline select on To do. */
p.suggested{display:flex;flex-wrap:wrap;gap:var(--s2);margin-top:var(--s2)}
p.suggested .tag{white-space:normal}
.actions.tight form.inline{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center}
.actions.tight form.inline select{max-width:min(100%,28rem)}
.actions.tight form.inline input.sm{max-width:14rem}

/* 3.9.72 — the report's autosave line. Same colours as the register's
   instant save; it does not fade, because "was that saved?" is asked later. */
.autosave-line{margin:var(--s3) 0 0;min-height:1.4em}
.autosave-status{font-size:var(--t-sm);color:var(--ink-3)}
.autosave-status.is-ok{color:var(--good)}
.autosave-status.is-bad{color:var(--prob);font-weight:600}
.autosave-status.is-held{color:var(--attn)}

/* 3.9.73 — Tick all / Tick none above the order preview */
.tickbar{display:flex;flex-wrap:wrap;gap:.5rem .75rem;align-items:center;margin:1.25rem 0 .5rem}
.tickbar form.inline{margin:0}

/* 3.9.73 — the same purchase written twice, shown as one */
tr.samepurchase td{color:var(--muted)}

/* 3.9.73 — cover and swaps, and the notification bell. */
.btn.danger{background:var(--prob);border-color:var(--prob);color:#fff}
.btn.outline-bad{border-color:var(--prob);color:var(--prob);background:transparent}
ul.plain{list-style:none;margin:0;padding:0}
ul.plain > li{padding:var(--s3) 0;border-top:1px solid var(--line)}
ul.plain > li:first-child{border-top:0}
ul.plain > li form.inline{margin-left:var(--s2)}
.rule{padding:var(--s3);border-radius:var(--r-sm);background:var(--accent-wash)}
.rule.warn{background:var(--attn-wash);color:var(--attn)}
.rule.bad{background:var(--prob-wash);color:var(--prob)}
.card.release.emergency{border-left:4px solid var(--prob)}
.card.release fieldset{border:1px solid var(--line);border-radius:var(--r-sm);padding:var(--s3)}
.card.release fieldset label{display:block;margin:var(--s1) 0}
.card.release .times{display:block;margin-top:var(--s2);font-size:var(--t-sm)}
.card.release label.confirm{font-weight:600}
.top .who .bell{position:relative;display:inline-flex;align-items:center;justify-content:center;
  min-width:32px;min-height:32px;margin-right:var(--s2);text-decoration:none;font-size:18px}
.top .who .bell .count{position:absolute;top:-4px;right:-6px;background:var(--prob);color:#fff;
  border-radius:var(--r-full);font-size:var(--t-xs);padding:0 5px;line-height:16px;font-weight:700}
ul.notes > li.unread{font-weight:600}
.schedreq .choice label{display:block;margin:var(--s1) 0}
details.redate{margin-top:var(--s1)}
details.redate summary{cursor:pointer}
details.redate form{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap;margin-top:var(--s1)}
ul.plain.myclasses > li{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;justify-content:space-between}
ul.plain.myclasses .act{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center}
.shifts{margin-top:var(--s4)}
.shifts .shiftrow{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;margin:var(--s2) 0}
.shifts .shiftrow .nm{min-width:9em;font-weight:600}
fieldset.shift .times{display:block;margin:var(--s1) 0}
/* 3.9.75 — a contact-log line for the ticked */
.lhbulk fieldset.bcontact{border:1px solid var(--line);border-radius:var(--r-sm);padding:var(--s3);margin:var(--s4) 0}
.lhbulk .confirmbox{border-left:4px solid var(--accent);background:var(--accent-wash);padding:var(--s3) var(--s4);margin:var(--s3) 0;border-radius:var(--r-sm)}
/* 3.9.76 — Scales & Arpeggios */
details.skplan{border:1px solid var(--line);border-radius:var(--r-sm);padding:var(--s2) var(--s3);margin:var(--s3) 0}
details.skplan > summary{cursor:pointer}
ul.skgrid > li{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;padding:var(--s2) 0}
ul.skgrid > li label{flex:1 1 14em}
.card.scales details.sklevel{margin:var(--s2) 0}
.card.scales details.sklevel > summary{cursor:pointer}
.card.scales select.sk-fluent{border-color:var(--good);color:var(--good)}
.card.scales select.sk-progress{border-color:var(--attn);color:var(--attn)}
.skstanding{border-top:1px solid var(--line);margin-top:var(--s4);padding-top:var(--s3)}
form.skrow{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;margin:var(--s1) 0}
form.skrow .skorder{width:4.5em}
form.skrow .sktitle{flex:1 1 12em;min-width:0}
/* 3.9.77 — Simon, 23 Sep: a pack row on Class plans ran to the card's edge,
   with the thumbnail touching it and the "just added" ground bleeding out.
   The rows now sit inside the same inset as the level's heading. */
.levelpack .printlist li{padding-left:var(--s3);padding-right:var(--s3)}
.levelpack .printlist li.just{border-radius:var(--r-sm)}
.levelpack .pl-name{font-size:var(--t-base);line-height:1.35}
/* 3.9.77 — the checklist editor rows on one line (the global form rule
   makes every input and select full width, which stacked each item into
   three rows). */
form.skrow input, form.skrow select, form.skrow button{width:auto;margin:0}
form.skrow input.sktitle{flex:1 1 16em;min-width:0}
form.skrow input.skorder{flex:0 0 4.5em;width:4.5em}
form.skrow select{flex:0 0 auto}
form.skrow label.check{display:inline-flex;align-items:center;gap:4px;margin:0}
form.skrow{padding:var(--s1) 0;border-bottom:1px solid var(--line)}
/* 3.9.80 — the teacher's To do */
#todo .todorow{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2) var(--s3);padding:var(--s2) 0;border-bottom:1px solid var(--line)}
#todo .todorow .when{flex:0 0 9em;font-size:var(--t-sm);color:var(--ink-2)}
#todo .todorow .what{flex:1 1 14em;min-width:0}
#todo .todorow .btn{margin:0}
#todo .weekband.late{background:var(--prob-wash);color:var(--prob)}
/* 3.9.80 — "can't make one of your classes", folded to one line */
.card.slim{padding-top:var(--s3);padding-bottom:var(--s3)}
.card.slim details > summary{cursor:pointer;font-weight:600}
.card.slim form.skrow select{flex:1 1 14em}

/* ==================================================================
   3.9.81 — the Day page: where each class starts and ends, and the
   rail said out loud to be jump links.
   ================================================================== */
.rail .rail-label{align-self:center;font-size:var(--t-sm);font-weight:600;color:var(--ink-2);margin-right:var(--s1)}
.rail a .down{color:var(--accent);font-weight:600}
.rail a.done .down{color:var(--ink-3)}
.day-toilets{margin-top:var(--s4);padding-top:var(--s3);border-top:1px solid var(--line)}

.dayclass{--dc:var(--accent);--dc-ink:var(--accent-ink);
  margin:var(--s6, 40px) 0;border-left:6px solid var(--dc);border-radius:var(--r-md);
  background:var(--bg);padding:0 0 0 var(--s3)}
.dayclass.alt{--dc:var(--ink);--dc-ink:var(--bg)}
.dayclass-band{position:sticky;top:0;z-index:5;display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s2) var(--s3);
  background:var(--dc);color:var(--dc-ink);padding:var(--s3) var(--s4);margin-left:calc(-1 * var(--s3));
  border-radius:0 var(--r-md) var(--r-md) 0;box-shadow:0 2px 6px rgba(0,0,0,.12)}
.dayclass-band .dc-count{font-size:var(--t-xs);text-transform:uppercase;letter-spacing:.08em;opacity:.85}
.dayclass-band .dc-name{font-size:var(--t-lg, 1.25rem)}
.dayclass-band .dc-time{font-variant-numeric:tabular-nums}
.dayclass .daypanel{margin-top:0;padding-top:0;border-top:0}
.dayclass .occpanel{margin-top:var(--s3)}
.dayclass-end{display:flex;flex-wrap:wrap;justify-content:space-between;gap:var(--s2);margin:0;
  padding:var(--s3) var(--s4);border-top:2px dashed var(--dc);color:var(--ink-2);font-size:var(--t-sm)}
.dayclass-end span{font-weight:600}
.dayclass-end a{font-weight:600}
@media (max-width:640px){
  .dayclass{padding-left:var(--s2);border-left-width:5px}
  .dayclass-band{margin-left:calc(-1 * var(--s2));padding:var(--s2) var(--s3)}
  .rail .rail-label{width:100%}
}
/* The sticky class band needs the page itself to scroll, and overflow-x:hidden
   on html and body turns body into its own (non-scrolling) box. clip trims
   sideways overflow just the same without doing that. Browsers that don't
   know clip keep hidden, and the band simply doesn't stick. */
html,body{overflow-x:clip}
/* 3.9.82 — the lock-up tick in Done for the day */
.day-lockup{margin:0 0 var(--s4);padding:var(--s3) var(--s4);border:1px solid var(--line-2);border-radius:var(--r-md);background:var(--surface-2)}
.day-lockup .fineprint{margin:var(--s1) 0 0}
/* 3.9.83 — one recording for the whole day */
.wholeday{margin:0 0 var(--s4);padding:var(--s3) var(--s4);border:1px dashed var(--line-2);border-radius:var(--r-md)}
.wholeday h3{margin:0 0 var(--s1)}
.wholeday .wd-have{margin:var(--s1) 0}
.wd-source{max-height:16em;overflow:auto;border:1px solid var(--line);border-radius:var(--r-sm, 6px);padding:var(--s2) var(--s3);margin:var(--s2) 0;background:var(--surface-2)}
.tag.wholeday{background:var(--accent-wash);color:var(--accent)}
.wd-shared{margin:var(--s3) 0;padding:var(--s3) var(--s4);border-left:3px solid var(--accent);background:var(--surface-2);border-radius:var(--r-md)}
.wd-shared h3{margin:0 0 var(--s2);font-size:var(--t-sm)}
.wd-shared .rec{display:flex;flex-direction:column;gap:var(--s1);margin-bottom:var(--s2)}
.wd-shared audio{max-width:100%}
/* 3.9.83 — the saved message, at the bottom of the screen when you're kept in place */
.flash.flash-toast{position:fixed;left:50%;bottom:var(--s4);transform:translateX(-50%);z-index:50;
  width:min(640px, calc(100vw - 32px));margin:0;box-shadow:0 6px 24px rgba(0,0,0,.18);cursor:pointer;transition:opacity .4s}
.flash.flash-toast.gone{opacity:0;pointer-events:none}
/* 3.9.83 — a studio-violin line leaving once answered */
tr.violin-ask{transition:opacity .3s}
tr.violin-ask.violin-gone{opacity:0}
.violin-said .violin-done{color:var(--good);margin-right:var(--s2)}
/* 3.9.83 — Simon, 23 Sep, on the iPad: "the 'before you start' has slightly too much
   padding at the bottom under the toilet check, it should be spaced equally as at the top". */
.stepcard > :last-child,.stepcard fieldset.day-toilets{margin-bottom:0}
.stepcard fieldset.day-toilets > :last-child{margin-bottom:0}
/* 3.9.83 — the scales suggestions, drawn under the box */
.suggest-wrap{position:relative;flex:1 1 16em;display:block}
.suggest-wrap input{width:100%;margin:0}
ul.suggest{position:absolute;left:0;right:0;top:100%;z-index:30;margin:4px 0 0;padding:0;list-style:none;
  background:var(--surface);border:1px solid var(--line-2);border-radius:var(--r-md);box-shadow:0 8px 24px rgba(0,0,0,.14);
  max-height:min(22em,50vh);overflow:auto}
ul.suggest li{padding:10px 12px;border-bottom:1px solid var(--line);cursor:pointer;display:flex;justify-content:space-between;gap:12px}
ul.suggest li:last-child{border-bottom:0}
ul.suggest li span{color:var(--ink-3);font-size:var(--t-xs);white-space:nowrap;align-self:center}
ul.suggest li:hover,ul.suggest li.on{background:var(--accent-wash)}
ul.suggest li.none{color:var(--ink-3);cursor:default}
/* 3.9.83 — the register's explanations, below it */
h2 .regtodo{font-size:var(--t-xs);vertical-align:middle;margin-left:var(--s2)}
.regnotes{margin-top:var(--s4);padding-top:var(--s3);border-top:1px solid var(--line)}
.regnotes > :last-child{margin-bottom:0}
/* 3.9.83 — the things you can do from the register, as buttons under it */
.regactions{display:flex;flex-wrap:wrap;gap:var(--s2);margin:var(--s3) 0 var(--s2)}
.regactions .btn{margin:0}
/* 3.9.83 — Simon: the register's buttons at the size of a section heading */
.regactions .btn{font-size:var(--t-md, 17px);font-weight:600;padding:var(--s2) var(--s4)}

/* ==================================================================
   3.9.85 — class notes (mockup 10) and the teaching list (mockup 9)
   ================================================================== */
.cnotes .notes{list-style:none;margin:var(--s3) 0;padding:0}
.cnotes .note{border:1px solid var(--line);border-radius:var(--r-md);padding:var(--s3);margin-bottom:var(--s3);background:var(--surface)}
.cnotes .note.mine{border-color:var(--accent)}
.cnotes .note.after{border-left:4px solid var(--attn)}
.cnotes .nh{display:flex;align-items:center;gap:var(--s2);font-size:var(--t-sm);color:var(--ink-2);flex-wrap:wrap}
.cnotes .nh b{color:var(--ink)}
.cnotes .nh .t{margin-left:auto;color:var(--ink-3)}
.cnotes .av{width:26px;height:26px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;
  font-size:11px;font-weight:700;background:var(--accent);color:var(--accent-ink)}
.cnotes .nb{margin:var(--s2) 0 0}
.cnotes .nf{display:flex;gap:var(--s3);margin-top:var(--s2);flex-wrap:wrap;align-items:flex-start}
.cnotes .cn-edit[open]{flex-basis:100%}
.cnotes .cn-edit textarea{width:100%;margin:var(--s2) 0}
.cnotes .compose textarea{width:100%}
.cnotes .compose .row{display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap;margin-top:var(--s2)}
.subbox{background:var(--good-wash);border:1px solid var(--good);color:var(--good);border-radius:var(--r-md);padding:var(--s2) var(--s3)}
dl.repro{display:grid;grid-template-columns:max-content 1fr;gap:var(--s1) var(--s4);margin:var(--s3) 0}
dl.repro dt{color:var(--ink-3);font-size:var(--t-sm)} dl.repro dd{margin:0}

.tlist ol.tl{list-style:none;margin:var(--s3) 0;padding:0;counter-reset:tln}
.tlist li.ti{display:grid;grid-template-columns:auto auto 1fr auto;gap:var(--s2) var(--s3);align-items:start;
  padding:var(--s3);border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface);margin-bottom:var(--s2)}
.tlist ol.spare li.ti{grid-template-columns:auto 1fr auto}
.tlist li.ti.drag{border-color:var(--accent);background:var(--accent-wash);box-shadow:0 8px 22px rgba(0,0,0,.14)}
.tlist .grip{cursor:grab;color:var(--ink-3);font-size:18px;line-height:22px;user-select:none;touch-action:none;padding:0 2px}
.tlist .num{counter-increment:tln;font-weight:700;color:var(--accent);font-variant-numeric:tabular-nums;min-width:1.2em}
.tlist .num::before{content:counter(tln)}
.tlist .ti-title{font-weight:600}
.tlist .ti-note{font-weight:500}
.tlist .kind{display:inline-block;font-size:11px;text-transform:uppercase;letter-spacing:.05em;border-radius:var(--r-full);
  padding:1px 8px;margin-right:6px;vertical-align:1px;background:var(--surface-2);color:var(--ink-2)}
.tlist .k-topic .kind{background:#e8eefc;color:#2c4a9a}
.tlist .k-piece .kind{background:#f3e8fb;color:#6a2a91}
.tlist .k-document .kind{background:#eef5ea;color:#2f6a24}
.tlist .k-note .kind{background:var(--attn-wash);color:var(--attn)}
.tlist .every{font-size:11px;color:var(--ink-3);border:1px dashed var(--line-2);border-radius:var(--r-full);padding:0 7px;margin-left:6px;font-weight:400}
.tlist .ti-meta{font-size:var(--t-sm);color:var(--ink-3);margin-top:2px}
.tlist .ti-docs{display:flex;flex-wrap:wrap;gap:6px;margin-top:var(--s2);align-items:flex-start}
.tlist .docchip{display:inline-block;border:1px solid var(--line-2);border-radius:var(--r-full);padding:7px 12px;white-space:nowrap;font-size:var(--t-sm);font-weight:600;text-decoration:none;background:var(--surface);line-height:1.4}
.tlist .ti-acts{display:flex;gap:4px;flex-wrap:wrap;justify-content:flex-end}
.tlist .ti-acts .ib{border:1px solid var(--line-2);background:var(--surface);border-radius:6px;width:32px;height:32px;padding:0;cursor:pointer;margin:0}
.tlist .ti-edit textarea{width:100%;margin:var(--s2) 0}
.tlist .tl-add{margin:var(--s2) 0}
.tlist .tl-more{display:flex;gap:var(--s2);align-items:baseline;flex-wrap:wrap;margin:var(--s2) 0 var(--s4)}
.tlist .tl-upload[open]{flex-basis:100%}
.tlist .tl-upload form{display:flex;flex-wrap:wrap;gap:var(--s2);margin-top:var(--s2)}
.tlist .tl-upload input{width:auto;flex:1 1 12em;margin:0}
.tlist .tl-spare{border:1px solid var(--line);border-radius:var(--r-md);padding:var(--s2) var(--s3);margin:var(--s3) 0}
.tlist ol.tl.order-failed{outline:2px solid var(--bad, #b3261e)}
@media (max-width:640px){
  .tlist li.ti{grid-template-columns:auto 1fr;}
  .tlist .num{display:none}
  .tlist .ti-acts{grid-column:1 / -1;justify-content:flex-start}
}
/* 3.9.85 — the register: one row to add a learner; the extra panels only
   when their button is pressed (Simon: "those buttons should just make those
   things appear underneath"). :target does it without script. */
.addrow-inline{display:flex;gap:var(--s2);align-items:center;margin:var(--s2) 0 var(--s3)}
.addrow-inline .suggest-wrap{flex:1 1 18em}
.addrow-inline .btn{margin:0}
.card.ahead:not(:target){display:none}
details.addperson:not(:target):not([open]){display:none}
.stillmark{margin:0}
/* 3.9.85 — Add to a class, on Repertoire and Curriculum */
.toclass2{margin:var(--s3) 0}
.toclass2 .tc-chips{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center}
.toclass2 .pick{border:1px solid var(--line-2);border-radius:10px;padding:6px 12px;background:var(--surface);font:inherit;font-size:var(--t-sm);cursor:pointer;text-align:left;color:var(--ink)}
.toclass2 .pick b{display:block}
.toclass2 .pick span{font-size:var(--t-xs);color:var(--ink-3)}
.toclass2 .pick.done{border-color:var(--good);background:var(--good-wash);cursor:default}
.toclass2 .row{display:flex;gap:var(--s2);flex-wrap:wrap;margin-top:var(--s2)}
.toclass2 select{width:auto;flex:1 1 16em;margin:0}
.tc-topic{display:inline-block;margin-left:var(--s2)}
.tc-topic[open]{display:block}
.tlist .tl-add{display:flex;gap:var(--s2);align-items:center}
.tlist .tl-add .suggest-wrap{flex:1 1 18em}
.tlist .tl-add .btn{margin:0}
form.skrow .suggest-wrap{flex:1 1 16em;min-width:0}
form.skrow .suggest-wrap input{width:100%}
.tlist form.tl-add{border-bottom:0}
/* 3.9.86 — copy this list to other classes */
.tlist .tl-copyto form{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;margin-top:var(--s2)}
.tlist .tl-copyto select{width:auto;flex:1 1 14em;margin:0}
.tlist .tl-copyto .btn{margin:0}
/* 3.9.87 — the class on its own, drawn like a class on the Day page */
.dayclass.single{margin-top:var(--s3)}
.dayclass .occpanel > .pagehead h1{font-family:"Avenir Next", Lato, "Helvetica Neue", Helvetica, Arial, sans-serif;font-size:17px;font-weight:600;letter-spacing:-0.085px;line-height:22.1px;margin:0}

/* 3.9.88 — the penguin on the Day page. Its own 26px strip; stands still and
   now and then looks the other way; tap it for a kind word. */
.penguin-strip{position:relative;height:26px;margin:0 0 var(--s1);display:flex;justify-content:flex-end;align-items:flex-end;border-bottom:1px solid var(--line)}
.penguin{position:relative}
.penguin > summary{list-style:none;cursor:pointer;width:20px;height:24px;padding:0;margin:0 var(--s2) 0 0}
.penguin > summary::-webkit-details-marker{display:none}
.penguin > summary::marker{content:''}
.penguin svg{display:block;width:20px;height:24px;transform-origin:50% 100%;animation:pg-look 14s steps(1) infinite}
@keyframes pg-look{0%{scale:1 1} 70%{scale:-1 1} 76%{scale:1 1} 84%{scale:-1 1} 88%{scale:1 1}}
.penguin > summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:4px}
.penguin-says{position:absolute;right:0;top:calc(100% + 6px);z-index:20;width:min(300px, calc(100vw - 32px));margin:0;
  padding:var(--s2) var(--s3);background:var(--surface);border:1px solid var(--line-2);border-radius:12px;
  box-shadow:0 8px 22px rgba(0,0,0,.14);font-size:var(--t-sm);color:var(--ink)}
.penguin-says::before{content:'';position:absolute;top:-6px;right:12px;width:10px;height:10px;background:var(--surface);
  border-left:1px solid var(--line-2);border-top:1px solid var(--line-2);transform:rotate(45deg)}
@media (prefers-reduced-motion: reduce){ .penguin svg{animation:none} }
:root[data-theme="dark"] .penguin svg{filter:drop-shadow(0 0 1.5px rgba(255,255,255,.7))}
@media (prefers-color-scheme: dark){ :root:not([data-theme]) .penguin svg{filter:drop-shadow(0 0 1.5px rgba(255,255,255,.7))} }
details.penguin > summary::before, details.penguin[open] > summary::before{content:none !important;display:none !important}
details.penguin > summary{display:block;flex:none}
.penguin-strip{border-bottom:0;margin-top:calc(-1 * var(--s3))}

/* 3.9.89 — toilet check. Yellow until answered; once a choice is made it
   shrinks to one quiet green line (the other answer stays tappable, small). */
fieldset.rpt-toilets{background:var(--ask-wash,#fff1b3);border:1px solid var(--attn);border-radius:8px;padding:var(--s2) var(--s3);margin:0 0 var(--s3)}
fieldset.rpt-toilets legend{color:var(--attn);font-weight:600;padding:0 var(--s1)}
fieldset.rpt-toilets:has(input:checked){background:var(--good-wash);border-color:transparent;padding:var(--s1) var(--s3);display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2)}
fieldset.rpt-toilets:has(input:checked) legend{float:left;color:var(--good);font-weight:400;font-size:var(--t-xs);padding:0;margin:0}
fieldset.rpt-toilets:has(input:checked) legend::before{content:"\2713\00a0"}
fieldset.rpt-toilets:has(input:checked) .radiorow{gap:var(--s2);font-size:var(--t-xs)}
fieldset.rpt-toilets:has(input:checked) label.check:has(input:checked){color:var(--good);font-weight:600}
fieldset.rpt-toilets:has(input:checked) label.check:not(:has(input:checked)){color:var(--ink-3)}
fieldset.rpt-toilets:has(input:checked) .fineprint{margin:0;font-size:0;line-height:1}
fieldset.rpt-toilets:has(input:checked) .fineprint .autosave-status{font-size:var(--t-xs)}
.day-toilets:has(input:checked){margin-top:var(--s3);border-top:0}
/* 3.9.89 — teaching list buttons: drawn icons, always in the ink colour */
.tlist .ti-acts .ib{color:var(--ink);display:inline-flex;align-items:center;justify-content:center;line-height:0}
.tlist .ti-acts .ib svg{display:block;width:16px;height:16px;pointer-events:none}
.tlist .ti-acts .ib:hover{background:var(--accent-wash);color:var(--accent)}

:root{--ask-wash:#fff1b3}
@media (prefers-color-scheme: dark){:root:not([data-theme="light"]){--ask-wash:#3a2f10}}
:root[data-theme="dark"]{--ask-wash:#3a2f10}
fieldset.rpt-toilets:has(input:checked) label.check{font-size:var(--t-sm)}
/* 3.9.90 — Curriculum: the introduction runs the full width; source documents fold away */
.pagehead.wide .ph-text p{max-width:none}
.pagehead details.curver{margin-top:var(--s2)}
.pagehead details.curver > p{margin-top:var(--s1)}
/* 3.9.92 — one history and one "Log a contact" form on Enquiries */
ol.ptl{list-style:none;margin:0 0 var(--s3);padding:0 0 0 var(--s3);border-left:2px solid var(--line-2)}
ol.ptl li{position:relative;padding:0 0 var(--s2) var(--s3);font-size:var(--t-sm)}
ol.ptl li::before{content:"";position:absolute;left:calc(-1 * var(--s3) - 6px);top:5px;width:10px;height:10px;border-radius:50%;background:var(--surface);border:2px solid var(--accent)}
ol.ptl li.st::before{border-color:var(--good)}
ol.ptl .k{display:inline-block;font-size:var(--t-xs);font-weight:700;padding:0 7px;border-radius:var(--r-full);background:var(--accent-wash);color:var(--accent);margin-right:var(--s1)}
ol.ptl li.st .k{background:var(--good-wash);color:var(--good)}
ol.ptl .d{color:var(--ink-2);margin-top:2px;white-space:normal}
ol.ptl .w{font-size:var(--t-xs);color:var(--ink-3)}
form.logc{background:var(--surface-2);border-radius:var(--r-md);padding:var(--s3) var(--s4)}
form.logc h4{margin:0 0 var(--s2)}
form.logc textarea{width:100%}
.howchips{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);margin:0 0 var(--s2)}
.howchips label{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--line-2);border-radius:var(--r-full);padding:4px 12px;background:var(--surface);font-size:var(--t-sm);cursor:pointer;margin:0}
.howchips label:has(input:checked){background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.howchips input{position:absolute;opacity:0;pointer-events:none}
.howchips label:has(input:focus-visible){outline:3px solid var(--accent);outline-offset:2px}
.logc-row{display:flex;flex-wrap:wrap;gap:var(--s3)}
.logc-row > label{flex:1 1 14em;margin:0}
.logc-row input,.logc-row select{width:100%}
/* 3.9.93 — week review (Mockup 16) */
.wr-card{display:flex;flex-wrap:wrap;gap:var(--s3);align-items:center;justify-content:space-between}
.wr-card h2{margin:var(--s1) 0}
.wr-mybrief{border-left:3px solid var(--good)}
.wr-mybrief p{margin:var(--s2) 0 0}
.wr-stats{display:flex;flex-wrap:wrap;gap:var(--s2);margin:0 0 var(--s3)}
.wr-stats div{flex:1 1 7em;background:var(--surface-2);border-radius:var(--r-md);padding:var(--s2) var(--s3);font-size:var(--t-sm);color:var(--ink-2)}
.wr-stats b{display:block;font-size:var(--t-xl);color:var(--ink)}
.wr-stats .ok b{color:var(--good)}.wr-stats .bad b{color:var(--prob)}
.wr-y{color:var(--good);font-weight:800}
a.wr-gap{display:inline-block;background:var(--prob-wash);color:var(--prob);font-weight:700;font-size:var(--t-xs);border-radius:var(--r-full);padding:2px 9px;text-decoration:none}
a.wr-gap.warn{background:var(--attn-wash);color:var(--attn)}
.wr-go{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;margin-top:var(--s3)}
.wr-gapnote{background:var(--attn-wash);color:var(--attn);border-radius:var(--r-md);padding:var(--s2) var(--s3);font-size:var(--t-sm)}
.wr-level{margin:0 0 var(--s4)}
.wr-level h3{margin:0 0 var(--s2)}
.wr-cohorts{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:var(--s2)}
.wr-coh{background:var(--surface-2);border-radius:var(--r-md);padding:var(--s2) var(--s3);font-size:var(--t-sm)}
.wr-coh h4{margin:0 0 var(--s1)}
.wr-coh ul{margin:0;padding-left:1.1em}
.wr-only{background:var(--accent-wash);color:var(--accent);font-size:var(--t-xs);font-weight:700;border-radius:var(--r-full);padding:0 7px}
.wr-focus{border-left:4px solid var(--good);background:var(--good-wash);padding:var(--s2) var(--s3);border-radius:0 var(--r-md) var(--r-md) 0;margin:var(--s2) 0 0;font-size:var(--t-sm)}
.wr-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:var(--s3)}
.wr-brief,.wr-grp,.wr-plan{border:1px solid var(--line);border-radius:var(--r-md);padding:var(--s3);background:var(--surface);margin:0}
.wr-brief textarea,.wr-grp textarea{width:100%;margin:var(--s1) 0 var(--s2);font-size:var(--t-sm)}
.wr-grp h3{margin:0 0 var(--s1);font-size:var(--t-md)}
.wr-plan ol{margin:var(--s2) 0;padding-left:1.3em;font-size:var(--t-sm)}
table.wr-check td{vertical-align:middle}

/* ================= 3.9.94 — recordings on the day, class summaries, last week ================= */
.wkchip{display:inline-block;padding:2px var(--s2);border-radius:var(--r-full);font-size:var(--t-xs);font-weight:600;letter-spacing:.02em;vertical-align:middle;background:var(--surface);border:1px solid var(--line);color:var(--ink-2)}
.wkchip.t{background:var(--accent-wash);border-color:transparent;color:var(--accent)}
h1 .wkchip{font-family:inherit;font-size:var(--t-sm);vertical-align:middle}
/* Last week, above this week, until put away (Mockup 18b). A well, not a
   card: it is the week that has gone. The same eyebrow and tags as every
   other screen. */
.lastweek{position:relative;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-md);padding:var(--s4) var(--s5);margin:var(--s5) 0 var(--s4)}
.lastweek h2{margin:var(--s2) 0 var(--s2)}
.lastweek .lw-x{position:absolute;top:var(--s3);right:var(--s3);margin:0}
.lw-flags{margin:0;padding-right:110px;display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:center}
.lw-flag,.tw-flag{font-size:var(--t-xs);font-weight:600;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-3)}
.tw-flag{color:var(--accent)}
.thisweek{border-top:1px solid var(--line-2);padding-top:var(--s3);margin:var(--s2) 0 var(--s4);display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:center}
.lw-mine{max-width:640px}
.lw-mine td{padding:var(--s1) var(--s2)}
.lw-mine .wr-gap{margin-right:var(--s1)}
.lw-brief{border-left:4px solid var(--accent);background:var(--accent-wash);padding:var(--s2) var(--s3);border-radius:0 var(--r-sm) var(--r-sm) 0;margin:var(--s3) 0}
.lw-brief p{margin:var(--s1) 0 0}
table.pastweeks td,table.wr-sum td{vertical-align:middle}
/* Recordings of the day (Mockups 17, 19) */
.dayrec{margin:0 0 var(--s4);padding:var(--s3) var(--s4);border:1px dashed var(--line-2);border-radius:var(--r-md)}
.dayrec h3{margin:0 0 var(--s1)}
.dayrec h4{margin:var(--s4) 0 var(--s2);font-size:var(--t-md)}
.dayrec h5{margin:0 0 var(--s1);font-size:var(--t-base)}
table.drlist td{vertical-align:top}
table.drlist audio{display:block;width:220px;max-width:100%;height:32px;margin-top:var(--s1)}
.drwho,.drcov{display:block}
input.drtime{width:6.5em}
input.drlen{width:4.5em}
table.drlist select{max-width:14em}
.dradd > summary{list-style:none;cursor:pointer}
.dradd > summary::-webkit-details-marker{display:none}
.dradd[open] form{margin-top:var(--s2);min-width:16em}
.dr-addrow{margin-top:var(--s3)}
.drtl{display:grid;grid-template-columns:130px 1fr;gap:var(--s1) var(--s2);align-items:center;font-size:var(--t-xs)}
.drtl-l{color:var(--ink-2);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.drtl-t{width:100%;height:24px;display:block}
.drtl-n{grid-column:2;display:block;color:var(--ink-3);margin:0}
.drtl-ticks{display:flex;justify-content:space-between}
.drtl .c0,.drbar .c0{fill:var(--accent)} .drbar-k .k.c0{background:var(--accent)}
.drtl .c1,.drbar .c1{fill:var(--good)} .drbar-k .k.c1{background:var(--good)}
.drtl .c2,.drbar .c2{fill:var(--attn)} .drbar-k .k.c2{background:var(--attn)}
.drtl .bg{fill:var(--surface-2)}
.drtl .r{fill:var(--ink-2)}
.drbar .x{fill:var(--line-2)} .drbar-k .k.x{background:var(--line-2)}
.drissue{margin:var(--s2) 0}
.drissue .check.inline{display:inline-flex;margin:0 var(--s2) 0 0}
.drsplit{border-top:1px solid var(--line);margin-top:var(--s4)}
.drbar{width:100%;height:28px;display:block;border-radius:var(--r-sm)}
.drbar-k{margin:var(--s1) 0 var(--s3)}
.drbar-k .k{display:inline-block;width:10px;height:10px;border-radius:2px;margin:0 4px 0 8px;vertical-align:middle}
.drcut{border:1px solid var(--line);border-left:3px solid var(--accent);border-radius:var(--r-sm);padding:var(--s3);margin:0 0 var(--s3);background:var(--surface)}
.drcut.unsure{border-left-color:var(--attn)}
.drctx{font-size:var(--t-sm);background:var(--surface-2);border-radius:var(--r-sm);padding:var(--s2) var(--s3);line-height:1.6;max-height:22em;overflow-y:auto;overscroll-behavior:contain;margin:0;position:relative}
.drsent{display:inline;font:inherit;line-height:inherit;color:var(--ink);background:none;border:0;padding:1px 2px;margin:0;text-align:left;border-radius:3px}
button.drsent{cursor:pointer}
button.drsent:hover,button.drsent:focus-visible{background:var(--accent-wash);color:var(--accent);outline:none}
.drsent.before{color:var(--ink-3)}
.drctx .mark.other{border-top-style:dotted;color:var(--ink-3)}
.drctx .before{color:var(--ink-3)}
.drctx .mark{display:block;border-top:2px dashed var(--accent);margin:var(--s1) 0;padding-top:2px;font-size:var(--t-xs);font-weight:800;color:var(--accent);letter-spacing:.06em;text-transform:uppercase}
.drnudge{display:flex;flex-wrap:wrap;gap:var(--s1);align-items:center;margin-top:var(--s2)}
.drnudge form{margin:0}
.dralt{margin:var(--s2) 0 0}
.drgo{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;margin:var(--s2) 0}
.drmake{border-top:1px solid var(--line);margin-top:var(--s4)}
.drasm{border:1px solid var(--line);border-radius:var(--r-sm);padding:var(--s2) var(--s3);margin:0 0 var(--s2);background:var(--surface)}
.drasm ol{margin:var(--s1) 0 0;padding-left:1.3em}
.daysum{margin:0 0 var(--s4);padding:var(--s3) var(--s4);border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface)}
.daysum h3{margin:0 0 var(--s2)}
/* Class summary (Mockups 17, 17b) */
.cs-two{display:grid;grid-template-columns:1fr 1fr;gap:var(--s3)}
.cs-two label{display:block}
.cs-two textarea{width:100%}
.cs-v{border:1px solid var(--line);border-radius:var(--r-sm);padding:var(--s2) var(--s3);background:var(--surface);font-size:var(--t-sm)}
.cs-v h3{margin:0 0 var(--s1);font-size:var(--t-sm)}
.cs-v ul{margin:var(--s1) 0 0;padding-left:1.2em}
.cs-tail{margin:var(--s2) 0 0}
.cs-trail{list-style:none;margin:var(--s3) 0 0;padding:0;font-size:var(--t-sm)}
.cs-trail li{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;padding:var(--s2) 0;border-top:1px solid var(--line)}
.cs-trail .what{flex:0 0 7.5em;color:var(--ink-3);font-size:var(--t-xs);font-weight:700;text-transform:uppercase;letter-spacing:.06em}
.cs-trail form.inline{display:inline;margin:0}
.cs-role{font-size:var(--t-xs);font-weight:800;border-radius:var(--r-full);padding:1px 8px}
.cs-role.t{background:var(--good-wash);color:var(--good)}
.cs-role.o{background:var(--accent-wash);color:var(--accent)}
.cs-todo{color:var(--attn);font-weight:600}
.cs-oldone{border-top:1px solid var(--line);padding-top:var(--s2);margin-top:var(--s2)}
@media (max-width:760px){
  .cs-two{grid-template-columns:1fr}
  .drtl{grid-template-columns:78px 1fr}
  .lw-flags{padding-right:0}
  .lastweek .lw-x{position:static;margin:0 0 var(--s2)}
  table.drlist thead{display:none}
  table.drlist,table.drlist tbody,table.drlist tr,table.drlist td{display:block;width:auto}
  table.drlist tr{border-bottom:1px solid var(--line);padding:var(--s2) 0}
  table.drlist td{border:0;padding:2px 0}
  table.drlist td[data-label]:not([data-label="File"])::before{content:attr(data-label) ": ";display:inline-block;min-width:6.5em;color:var(--ink-3);font-size:var(--t-xs);font-weight:700;text-transform:uppercase;letter-spacing:.06em}
  table.drlist select{max-width:100%}
}

/* 3.9.96 — a form busy with the AI (instant.js adds .is-busy and the note). */
.busy-note{display:none}
form.is-busy .busy-note{display:block;flex-basis:100%;margin:var(--s2) 0 0;font-size:var(--t-sm);font-weight:600;color:var(--accent)}
form.is-busy .busy-note::after{content:"";display:block;height:3px;margin-top:var(--s2);border-radius:var(--r-full);
  background:linear-gradient(90deg,transparent 0,var(--accent) 40%,transparent 80%) 0 0/200% 100% no-repeat var(--accent-wash);
  animation:busybar 1.4s linear infinite}
form.is-busy button{opacity:.6;cursor:progress}
@keyframes busybar{from{background-position:150% 0}to{background-position:-50% 0}}
@media (prefers-reduced-motion:reduce){form.is-busy .busy-note::after{animation:none;background:var(--accent)}}

/* 3.9.98 — Reports in weeks (Mockup 21): each week's line above its classes, every week folds away. */
details.rweek{border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface);margin:0 0 var(--s3)}
details.rweek > summary{list-style:none;cursor:pointer;display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;padding:var(--s3) var(--s4);background:var(--surface-2);border-radius:var(--r-md)}
details.rweek[open] > summary{border-radius:var(--r-md) var(--r-md) 0 0;border-bottom:1px solid var(--line)}
details.rweek > summary::-webkit-details-marker{display:none}
details.rweek > summary::before{content:"▸";color:var(--ink-3);width:1em}
details.rweek[open] > summary::before{content:"▾"}
.rweek-line b{font-size:var(--t-md)}
.rweek-counts{display:flex;flex-wrap:wrap;gap:var(--s1)}
.rweek-go{margin-left:auto}
details.rweek .tblwrap{margin:0;padding:0 var(--s3) var(--s2)}
table.rweek-classes{margin:0}
.rw-fold{margin:0 0 var(--s2);text-align:right}
.rw-more{text-align:center;margin:var(--s4) 0}

/* 3.9.99 — Make the class transcripts (Mockup 22). */
.dr-steps{display:flex;flex-wrap:wrap;gap:var(--s1);margin:var(--s2) 0 var(--s3);font-size:var(--t-xs)}
.dr-steps span{padding:3px 10px;border-radius:var(--r-full);background:var(--surface-2);color:var(--ink-3);font-weight:600}
.dr-steps span.done{background:var(--good-wash);color:var(--good)}
.dr-steps span.now{background:var(--accent);color:var(--accent-ink, #fff)}
.mk{border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface);margin:0 0 var(--s2);padding:var(--s3);display:grid;grid-template-columns:1fr auto;gap:var(--s1) var(--s3);align-items:start}
.mk h5{margin:0;font-size:var(--t-base)}
.mk-src{margin:2px 0 0;color:var(--ink-2)}
.mk.made{border-left:4px solid var(--good)}
.mk.stale,.mk.wait{border-left:4px solid var(--attn)}
.mk-made{display:inline-block;background:var(--good);color:#fff;font-weight:800;font-size:var(--t-xs);border-radius:var(--r-full);padding:2px 10px;vertical-align:middle}
.mk-act{display:flex;flex-direction:column;gap:var(--s1);align-items:flex-end}
.mk-act form{margin:0}
.mk-remake{background:none;border:0;padding:0;cursor:pointer;color:var(--ink-2);text-decoration:underline;text-underline-offset:3px;font:inherit;font-size:var(--t-sm)}
.btn.mk-warn{border-color:var(--attn);color:var(--attn);background:var(--attn-wash)}
.mk-ends{grid-column:1/-1;background:var(--surface-2);border-radius:var(--r-sm);padding:var(--s2) var(--s3);line-height:1.55}
.mk-ends i{font-style:normal;color:var(--ink-3);font-size:var(--t-xs);font-weight:700;letter-spacing:.06em;text-transform:uppercase;display:inline-block;width:4.5em}
.mk-read{grid-column:1/-1}
.mk-read > summary{cursor:pointer;font-size:var(--t-sm);font-weight:600;color:var(--accent)}
.mk-txt{max-height:14em;overflow:auto;background:var(--surface-2);border-radius:var(--r-sm);padding:var(--s2) var(--s3);font-size:var(--t-sm);line-height:1.6;margin-top:var(--s1)}
.mk-banner{background:var(--good-wash);border-left:4px solid var(--good);border-radius:0 var(--r-sm) var(--r-sm) 0;padding:var(--s2) var(--s3);margin:0 0 var(--s3)}
@media (max-width:760px){.mk{grid-template-columns:1fr}.mk-act{align-items:flex-start}}

/* =====================================================================
   3.10.0 — THE CLASS PAGE WHILE TEACHING (Mockup 23): INFO · PEOPLE ·
   CONTENT · REPORT, a jump bar that stays at the top, one tap per item.
   ===================================================================== */
.occpanel > nav.jump{position:sticky;top:0;z-index:5;display:flex;gap:var(--s1);flex-wrap:wrap;
  padding:var(--s2) var(--s5);background:var(--surface);border-bottom:1px solid var(--line)}
nav.jump a{padding:6px 12px;border-radius:var(--r-full);font-size:var(--t-sm);font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;text-decoration:none;color:var(--ink-2);background:var(--surface-2)}
nav.jump a span{font-weight:500;letter-spacing:0;text-transform:none;color:var(--ink-3)}
nav.jump a:hover{background:var(--accent-wash);color:var(--accent)}
.occpanel > .grouph{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;padding:var(--s4) var(--s5) var(--s2);
  background:var(--surface);border-top:1px solid var(--line);scroll-margin-top:56px}
.occpanel > .grouph > span{font-size:var(--t-xs);font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:var(--accent)}
.occpanel > .grouph + .card{border-top:0}
.recbig{margin-left:auto;display:inline-flex;align-items:center;gap:8px;padding:10px 18px;border-radius:var(--r-full);
  background:var(--prob);color:#fff;font-weight:700;text-decoration:none}
.recbig i{width:10px;height:10px;border-radius:var(--r-full);background:#fff;display:inline-block}
.recbig.live{background:var(--prob-wash);color:var(--prob)}
.recbig.live i{background:var(--prob);animation:recblink 1.2s infinite}
@keyframes recblink{50%{opacity:.25}}

/* Content: Did it · Started it · Not today, and Print / Play */
.tlist li.ti{grid-template-columns:auto auto 1fr auto auto}
.tlist ol.spare li.ti{grid-template-columns:auto 1fr auto auto}
.tlist .ti-do{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap;justify-content:flex-end}
.seg{display:inline-flex;border:1px solid var(--line-2);border-radius:var(--r-full);overflow:hidden;margin:0}
.seg button{border:0;border-left:1px solid var(--line-2);background:var(--surface);color:var(--ink-2);font-size:var(--t-sm);
  font-weight:600;padding:8px 12px;margin:0;cursor:pointer;min-height:38px;border-radius:0}
.seg button:first-of-type{border-left:0}
.seg button.s-did.on{background:var(--good);color:#fff}
.seg button.s-started.on{background:var(--attn-wash);color:var(--attn)}
.seg button.s-not.on{background:var(--surface-2);color:var(--ink-3)}
.tlist li.ti.st-did{border-color:var(--good);background:var(--good-wash)}
.tlist li.ti.st-not .ti-title{color:var(--ink-3);text-decoration:line-through}
a.ico{font-size:var(--t-sm);font-weight:600;text-decoration:none;border:1px solid var(--line-2);border-radius:var(--r-full);padding:7px 12px;white-space:nowrap}
details.play{display:inline-block}
details.play > summary{list-style:none;cursor:pointer;font-size:var(--t-sm);font-weight:600;border:1px solid var(--line-2);
  border-radius:var(--r-full);padding:7px 12px;white-space:nowrap}
details.play > summary::-webkit-details-marker{display:none}
details.play[open]{display:block;flex-basis:100%}
details.play audio{width:100%;min-width:240px;margin-top:var(--s2)}
.tl-carry{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;padding:var(--s2) var(--s3);border:1px dashed var(--line-2);
  border-radius:var(--r-md);margin:0 0 var(--s3);color:var(--ink-2)}
@media (max-width:640px){
  .tlist li.ti, .tlist ol.spare li.ti{grid-template-columns:auto 1fr}
  .tlist .ti-do{grid-column:1 / -1;justify-content:flex-start}
  .seg{display:flex;width:100%}
  .seg button{flex:1;min-height:44px}
}

/* Scales & Arpeggios: its own box, open, one tap per line */
.skbox{border:1px solid var(--line);border-radius:var(--r-md);padding:var(--s3) var(--s4);margin:var(--s3) 0}
.skbox .skh{display:flex;gap:var(--s3);align-items:baseline;flex-wrap:wrap;margin-bottom:var(--s2)}
ul.skrows{list-style:none;margin:0;padding:0}
ul.skrows li.skr{border-top:1px solid var(--line)}
ul.skrows li.skr:first-child{border-top:0}
ul.skrows li.skr form{margin:0}
ul.skrows li.skr button, ul.skrows li.skr > span{display:flex}
ul.skrows li.skr button{width:100%;align-items:center;gap:var(--s3);background:none;border:0;padding:10px 2px;margin:0;
  text-align:left;cursor:pointer;color:var(--ink);font:inherit;border-radius:0;min-height:44px}
ul.skrows .tick{flex:0 0 24px;height:24px;border:2px solid var(--line-2);border-radius:6px;display:inline-flex;
  align-items:center;justify-content:center;font-weight:800;color:#fff}
ul.skrows li.skr.on .tick{background:var(--good);border-color:var(--good)}
ul.skrows .skt{flex:1}
ul.skrows .when{font-size:var(--t-sm);color:var(--ink-3);white-space:nowrap}
ul.skrows li.skr.due .when{color:var(--attn)}
ul.skrows li.skr.on .when{color:var(--good)}
.skbox .skall summary{margin-top:var(--s2)}

/* Report: your note, We need, the three boxes, then Submit */
.cnotes textarea{width:100%;min-height:8.5em}
.needrow{display:flex;gap:var(--s3);align-items:center;margin:var(--s2) 0 var(--s3)}
.needrow label{margin:0;font-weight:700;white-space:nowrap}
.needrow input, .needrow textarea{flex:1;margin:0}
.rstat{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s3);margin:var(--s3) 0}
.rstat .st{border:1px solid var(--line);border-radius:var(--r-md);padding:var(--s3)}
.rstat .st.ask{border-color:var(--attn);background:var(--attn-wash)}
.rstat .sth{font-weight:700;display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap;margin-bottom:var(--s2)}
.rstat .st p{margin:var(--s1) 0}
.rstat .live{display:inline-flex;align-items:center;gap:6px;color:var(--prob);font-weight:700;font-size:var(--t-sm)}
.rstat .live i{width:9px;height:9px;border-radius:var(--r-full);background:var(--prob);display:inline-block;animation:recblink 1.2s infinite}
.rstat details.bk{margin-top:var(--s2)}
.rstat details.bk summary{font-size:var(--t-sm);color:var(--ink-2);cursor:pointer}
.rstat details.bk form{display:flex;flex-direction:column;gap:var(--s2);margin-top:var(--s2)}
.rstat details.play{display:block;margin:var(--s1) 0}
.rfin{border-top:1px solid var(--line);padding-top:var(--s3);margin-top:var(--s3)}
@media (max-width:760px){ .rstat{grid-template-columns:1fr} }

/* 3.10.1 — This date didn't happen / This course isn't happening (superadmin). */
.didnt{display:flex;flex-wrap:wrap;gap:var(--s3);margin-top:var(--s3);padding-top:var(--s2);border-top:1px solid var(--line)}
/* 3.10.1 — Move someone to another class, under PEOPLE. */
.card.moving details.movebooking{margin:0}
/* 3.10.1 — teachers' view of a class summary (Mockup 24). */
.cs-fair{border:1px solid var(--line);border-radius:10px;padding:var(--s3);background:var(--surface-2);margin-top:var(--s3)}
.cs-fair h3{margin:0 0 var(--s2);font-size:1rem}
.cs-fair-row{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:flex-start;margin:var(--s2) 0}
.cs-no{flex:1 1 100%}
.cs-no > summary{list-style:none;display:inline-block;cursor:pointer}
.cs-no > summary::-webkit-details-marker{display:none}
.cs-no[open] > summary{background:var(--prob-wash)}
.cs-no form{margin-top:var(--s2)}
.cs-no textarea{width:100%}
.btn.no{border-color:var(--prob);color:var(--prob)}
.cs-flag{border-left:4px solid var(--prob);background:var(--prob-wash);padding:var(--s2) var(--s3);border-radius:0 8px 8px 0;margin:var(--s3) 0 var(--s2)}
.cs-flag b{display:block}
/* 3.10.1 — Week review: summaries first (Mockup 24). */
.wr-nudge{display:flex;flex-wrap:wrap;gap:var(--s3);align-items:center;background:var(--attn-wash);border-radius:8px;padding:var(--s3);margin:var(--s3) 0 var(--s2)}
.wr-nudge p{margin:0;flex:1 1 260px}
.wr-nudge.ready{background:var(--good-wash);display:block}
.wr-anyway{margin-top:0}
.wr-anyway .linkish{font-weight:600}
.wr-drafting{background:var(--surface-2);border-radius:8px;padding:var(--s3);margin:var(--s3) 0}
.wr-drafting ul{margin:var(--s2) 0}
.wr-drafting li{padding:2px 0}

/* 3.10.4 — the built-in player on a recording's row (Simon, 3 Oct). */
.printlist .pl-audio{display:block;width:100%;max-width:420px;margin-top:var(--s2)}

/* 3.11.0 — Accounts: what else they may do */
.grantrow{display:flex;flex-wrap:wrap;align-items:center;gap:8px 16px;padding:10px 0;border-top:1px solid var(--line)}
.grantrow:first-of-type{border-top:0}
.grantrow .grantname{min-width:10rem}

/* 3.11.0 — outbox: Waiting to go out, Went out, the learner-page "Queued" line and the Dashboard card (Mockup 32). */
.outbox .obgroup{border:1px solid var(--line);border-radius:10px;padding:var(--s3);margin:var(--s3) 0;background:var(--surface)}
.outbox .obghead{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--s2)}
.outbox .obghead h3{margin:0;font-size:1rem}
.outbox .obghead form{margin:0}
.outbox .obrow{border-top:1px solid var(--line);padding:var(--s2) 0;min-width:0}
.outbox .obrow:first-of-type{border-top:0}
.outbox .obwhat{margin:var(--s2) 0 2px;overflow-wrap:anywhere}
.outbox .obrow > .small{margin:0 0 var(--s2);overflow-wrap:anywhere}
.outbox .obact{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:flex-start}
.outbox .obact form{margin:0}
.outbox .obact details{flex:0 1 auto}
.outbox .obact details[open]{flex:1 1 100%}
.outbox .obact summary{list-style:none;cursor:pointer}
.outbox .obact summary::-webkit-details-marker{display:none}
.outbox .obact summary::marker{content:""}
.outbox .obact details[open] > summary{background:var(--ask-wash)}
.outbox .obform{margin-top:var(--s2);padding:var(--s3);border-radius:8px;background:var(--ask-wash);max-width:36rem}
.outbox .obform input[type=text],.outbox .obform select{width:100%;max-width:100%;box-sizing:border-box}
.outbox .obno .obform{background:var(--prob-wash)}
.tag.obmc{background:var(--attn-wash);color:var(--attn);font-weight:700;letter-spacing:.04em}
.outbox .obhistory{margin-top:var(--s4)}
.outbox .obhistory summary{cursor:pointer}
.outbox .obhistory td{overflow-wrap:anywhere}
.outbox .obhistory td form{margin:0}
.outbox .obtrust{margin-top:var(--s3)}
.outbox .obtrust summary{cursor:pointer}
.obqueued{margin:var(--s2) 0}
.obqueued p{margin:2px 0;overflow-wrap:anywhere}
.obcard p{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;margin:var(--s2) 0}
.obcard h2{margin-bottom:0}
/* 3.11.0 — announce: announcements (Mockup 33) and the feedback pill in the corner (Mockup 40) */

/* Dashboard banners, very top, above LAST WEEK. */
.ann-top{display:flex;flex-direction:column;gap:var(--s3);margin:0 0 var(--s5)}
.ann-banner{position:relative;background:var(--accent-wash);border:1px solid var(--line-2);border-left:4px solid var(--accent);
  border-radius:var(--r-md);padding:var(--s4) var(--s5)}
.ann-banner.pinned{border-left-color:var(--attn)}
.ann-banner h2{margin:0 0 var(--s2);font-size:var(--t-md);padding-right:var(--s6)}
.ann-banner p{margin:var(--s2) 0 0;overflow-wrap:anywhere}
.ann-banner.line{padding:var(--s2) var(--s4);border-left-color:var(--good);background:var(--good-wash)}
.ann-banner.line p{margin:0}
.ann-banner.line a{margin-left:var(--s2)}
.ann-x{position:absolute;top:var(--s2);right:var(--s2)}
.ann-x .linkish{font-size:var(--t-lg);line-height:1;min-width:40px;min-height:40px;color:var(--ink-2)}
.ann-answers{display:flex;flex-wrap:wrap;gap:var(--s2);margin-top:var(--s3)}
/* The bell list. */
.ann-bell-h{margin:var(--s5) 0 var(--s2);font-size:var(--t-sm);text-transform:uppercase;letter-spacing:.08em;color:var(--ink-3)}
.ann-bell-past{margin-top:var(--s3)}
.ann-bell-past > summary{cursor:pointer;color:var(--ink-2);font-size:var(--t-sm)}
/* The office page. */
.ann-choices{display:flex;flex-wrap:wrap;gap:0 var(--s5)}
.ann-off{color:var(--ink-3)}
.ann-some{margin-top:var(--s2)}
.ann-some > summary{cursor:pointer;color:var(--ink-2);font-size:var(--t-sm)}
.ann-group{margin:var(--s3) 0 0}
.ann-sets{margin-left:var(--s5);border-left:2px solid var(--line);padding-left:var(--s3)}
.ann-own{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--s2);margin:var(--s1) 0 var(--s2) var(--s5)}
.ann-go{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;margin-top:var(--s4)}
.ann-row{margin-top:var(--s3)}
.ann-head{margin:0;display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:baseline}
.ann-names{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s4);font-size:var(--t-sm);margin:var(--s2) 0}
.ann-acts{display:flex;flex-wrap:wrap;gap:var(--s2);margin-top:var(--s2);align-items:center}
.ann-acts form{margin:0}
.ann-acts .btn{margin:0}
.ann-past{margin-top:var(--s5)}
.ann-past > summary{cursor:pointer;font-weight:600;color:var(--ink-2)}

/* The feedback pill: "? Feedback", bottom right; open, the same summary is Cancel beside Send. */
.fb > summary{position:relative}
details.fb > summary::before, details.fb[open] > summary::before{content:none !important;display:none !important}
.fb[open] .panel{border-top:0}
.fb .panel > form > label:first-of-type{margin-top:0}
.fb-q{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:var(--r-full);
  border:2px solid currentColor;font-size:var(--t-xs);line-height:1}
.fb[open] .panel{padding-bottom:var(--s4)}
.fb[open] > summary{position:absolute;right:var(--s4);bottom:var(--s4);width:auto;min-height:40px;
  padding:9px 18px;border-radius:var(--r-sm);background:var(--surface);color:var(--ink);
  border:1px solid var(--line-2);box-shadow:none;justify-content:center;font-weight:600;z-index:1}
.fb[open] > summary:hover{background:var(--surface-2)}
.fb .fb-where{font-size:var(--t-xs);color:var(--ink-3);margin:var(--s2) 0 0;overflow-wrap:anywhere}
.fb label.fb-urgent{display:flex;text-transform:none;letter-spacing:0;font-size:var(--t-sm);color:var(--ink);margin:var(--s2) 0 0}
.fb .fb-go{display:flex;gap:var(--s3);margin-top:var(--s3);min-height:40px}
/* Thanks — sent: shown by :target after the page comes back, then it fades and the pill is back. */
.fb-thanks{display:none}
.fb-thanks:target{display:flex;align-items:center;position:absolute;top:0;bottom:0;right:0;padding:0 18px;white-space:nowrap;
  border-radius:var(--r-full);background:var(--good);color:var(--surface);font-weight:700;
  animation:fb-thanks 4s ease-in forwards;pointer-events:none}
@keyframes fb-thanks{0%,70%{opacity:1;visibility:visible}100%{opacity:0;visibility:hidden}}
/* Office list: the columns named, and room for "From which page". */
.fb-head{display:grid;grid-template-columns:14px minmax(150px,1.3fr) minmax(0,1fr) 108px 104px minmax(0,0.9fr);
  gap:var(--s3);padding:0 calc(var(--s4) + 1px) var(--s1);font-size:var(--t-xs);color:var(--ink-3);text-transform:uppercase;letter-spacing:.06em}
.fb-page{overflow:hidden;text-overflow:ellipsis}
@media (max-width:720px){
  .fb-head{display:none}
  .fb-page{white-space:normal}
}
/* Phone: smaller, above the thumb area. On the class page, smaller still and lower-left, clear of Save. */
@media (max-width:640px){
  .fb{bottom:72px}
  .fb > summary{padding:6px 12px;font-size:var(--t-xs)}
  .fb.fb-class{right:auto;left:var(--s2);bottom:var(--s2)}
  .fb.fb-class > summary{padding:4px 10px}
  .fb.fb-class > summary .fb-q{width:16px;height:16px}
  .fb[open]{bottom:var(--s3)}
  .fb.fb-class[open]{left:var(--s3);right:var(--s3)}
  .fb[open] > summary{padding:9px 18px;font-size:var(--t-sm)}
}
/* 3.11.0 — tools: the metronome and the tuner (Mockup 34). Drawn by
   assets/tools.js on the tool page (#toolmount) and in place on the class
   page (.toolinline, under the INFO buttons). The needle's place is a
   custom property (--c, cents) set by the script, not an inline style. */
.occpanel > .grouph .toolbtns{display:inline-flex;gap:var(--s2);flex-wrap:wrap}
.occpanel > .grouph > span + .toolbtns{margin-left:auto}
.toolbtns .btn{margin-top:0}
.toolinline{margin:0;border-radius:0;border-left:0;border-right:0;box-shadow:none;padding:var(--s3) var(--s5);background:var(--surface-2)}
.toolinline .btn,.toolcard .btn,.toolpick .btn{margin-top:0}
.toolinline .tk-line{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2) var(--s3)}
.toolinline .tk-row{margin:0}
.toolinline .tk-end{margin-left:auto;display:inline-flex;gap:var(--s2)}
.toolinline .tk-line{gap:var(--s2)}
.toolinline .btn{min-height:36px;padding:var(--s1) var(--s3)}
.toolinline.metro .m-step{min-width:40px}
.toolinline .t-status:not(.flash){display:none}
.toolinline .t-status.flash{margin:0}
.toolinline.toolflash,body.toolflash{background:var(--accent-wash)}
.toolhead .seg .btn{margin:0}
.toolpick{display:flex;flex-wrap:wrap;gap:var(--s3)}
.toolpick .btn{font-size:var(--t-md);padding:var(--s3) var(--s5)}
.toolcard{max-width:560px;padding-bottom:0}
.toolcard .tk-body{padding-bottom:var(--s4)}
.tk-row{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2);margin:var(--s3) 0}
.tk-lbl{font-size:var(--t-sm);color:var(--ink-2);min-width:7.5rem}
.toolinline .tk-lbl{min-width:0}
.tk-check{display:flex;align-items:center;gap:var(--s1);font-size:var(--t-sm);margin:var(--s2) 0}
.tool-go{position:sticky;bottom:0;display:flex;flex-wrap:wrap;align-items:center;gap:var(--s3);
  margin:0 calc(-1 * var(--s5));padding:var(--s3) var(--s5);background:var(--surface);border-top:1px solid var(--line)}
/* metronome */
.metro .m-head{display:flex;align-items:baseline;gap:var(--s3)}
.metro .m-bpm{font-family:Georgia,serif;font-size:var(--clock);line-height:1;font-variant-numeric:tabular-nums;color:var(--ink)}
.metro .m-word{font-size:var(--t-lg);color:var(--ink-2);font-style:italic}
.toolinline.metro .m-bpm{font-size:var(--t-2xl)}
.toolinline.metro .m-word{font-size:var(--t-base)}
.metro .m-steps,.metro .m-presets{display:flex;flex-wrap:wrap;gap:var(--s2);margin:var(--s3) 0}
.toolinline.metro .m-steps{margin:0}
.metro .m-step{min-width:48px;font-size:var(--t-md);font-weight:600}
.metro .m-presets .btn{min-width:44px;font-variant-numeric:tabular-nums}
.metro .m-vol{width:min(240px,100%)}
.metro .m-dots{display:flex;gap:var(--s2);align-items:center}
.metro .m-dots i{width:14px;height:14px;border-radius:var(--r-full);border:2px solid var(--line-2);display:inline-block}
.metro .m-dots i.first{border-color:var(--accent)}
.metro .m-dots i.on{background:var(--accent);border-color:var(--accent)}
.metro .m-where{margin:0;min-width:6rem}
.metro .m-go{min-width:120px;font-size:var(--t-md);padding:var(--s3) var(--s6)}
.metro .tool-go .m-go{margin-left:auto}
.toolinline.metro .m-go{min-width:88px;padding:var(--s2) var(--s4)}
.metro .m-more > summary{cursor:pointer;font-size:var(--t-sm);color:var(--accent)}
.metro .m-more[open]{flex:1 1 100%}
/* tuner */
.tuner .t-status{margin:0 0 var(--s2);color:var(--ink-2)}
.tuner .t-note{font-family:Georgia,serif;font-size:var(--clock);line-height:1.1;text-align:center;color:var(--ink)}
.tuner .t-oct{font-size:var(--t-lg);color:var(--ink-3);margin-left:2px}
.toolinline.tuner .t-note{font-size:var(--t-2xl);text-align:left;min-width:3ch}
.tuner .t-meter{position:relative;height:56px;margin:var(--s3) 0 var(--s1);border-radius:var(--r-sm);background:var(--surface-2);border:1px solid var(--line)}
.tuner .t-band{position:absolute;top:0;bottom:18px;left:45%;width:10%;background:var(--good-wash);border-left:1px solid var(--good);border-right:1px solid var(--good)}
.tuner .t-needle{position:absolute;top:4px;bottom:20px;width:4px;margin-left:-2px;border-radius:2px;background:var(--ink-3);
  left:calc(50% + var(--c, 0) * 1%);transition:left .12s ease-out}
.tuner .t-meter.good .t-needle{background:var(--good)}
.tuner .t-meter.off .t-needle{background:var(--attn)}
.tuner .t-mark{position:absolute;bottom:2px;transform:translateX(-50%);font-size:var(--t-xs);color:var(--ink-3)}
.tuner .t-mark.m50{left:6%}.tuner .t-mark.m25{left:25%}.tuner .t-mark.z{left:50%}.tuner .t-mark.p25{left:75%}.tuner .t-mark.p50{left:94%}
.tuner .t-cents{text-align:center;font-weight:600;margin:var(--s1) 0 var(--s3);color:var(--ink-2)}
.tuner .t-meter.good + .t-cents{color:var(--good)}
.tuner .t-meter.off + .t-cents{color:var(--attn)}
.toolinline.tuner .t-cents{margin:0;text-align:left}
.tuner .t-ref{min-width:5rem;text-align:center;font-weight:600;font-variant-numeric:tabular-nums}
.tuner .t-strings{display:flex;flex-wrap:wrap;gap:var(--s2)}
.tuner .tool-go .t-strings{flex:1 1 100%}
.tuner .tool-go .t-str{flex:1 1 0;min-height:52px}
.tuner .t-str b{font-size:var(--t-md)}
.tuner .t-str span{color:var(--ink-3);font-size:var(--t-xs)}
.tuner .t-str.hear{border-color:var(--good);box-shadow:0 0 0 2px var(--good-wash)}
.tuner .t-str.on{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.tuner .t-str.on span{color:var(--accent-ink)}
@media (max-width:600px){
  .toolcard{max-width:none;margin:0 calc(-1 * var(--s3));border-radius:0;border-left:0;border-right:0}
  .toolinline{padding:var(--s3)}
  .toolinline .tk-end{margin-left:0}
  .tk-lbl{min-width:0;flex:1 1 100%}
  .metro .tool-go .m-go{flex:1 1 auto}
  /* the feedback pill sits above the Start bar / strings, not on them */
  body:has(#toolmount) .fb:not([open]){bottom:calc(var(--s4) + 84px)}
}
/* 3.11.0 — daypack: follow-up pack per first-timer (Mockup 35); Submit the day and Keep this in the library (Mockup 36). */
.dp-new{margin:var(--s3) 0 0;padding-top:var(--s3);border-top:1px solid var(--line)}
.dp-new .btn{margin:var(--s2) 0 0 var(--s2);vertical-align:middle}
.dp-new-none{margin:var(--s3) 0 0}
.dp-fp{margin-top:var(--s3)}
.dp-fp fieldset{margin:0}
.dp-fp-head .btn{margin:0 0 0 var(--s2)}
.dp-fprow{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2) var(--s3);padding:var(--s2) 0;border-top:1px solid var(--line)}
.dp-fpname{flex:1 1 12rem;font-weight:600}
.dp-fprow .seg button{min-height:40px;min-width:4.5rem}
.dp-fpline{margin:0 0 var(--s3)}
.dp-fpline summary{cursor:pointer}
.dp-trail{margin:var(--s2) 0 0;color:var(--ink-2)}
.dp-trail li{padding:2px 0}
table.dp-done tr.dp-other td{color:var(--ink-3)}
.dp-ready{white-space:normal}
.dp-submit{margin:var(--s4) 0 0;padding:var(--s3);border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface-2)}
.dp-submit p{margin:0 0 var(--s2)}
.dp-submit .dp-go{width:100%;max-width:28rem;margin:var(--s2) 0}
.dp-fixes{margin:0 0 var(--s2)}
.dp-fixes li{padding:2px 0}
.dp-subdone{margin:var(--s4) 0 0;padding:var(--s3);border-radius:var(--r-md);background:var(--good-wash);color:var(--good)}
.dp-keep{margin-top:var(--s1)}
.dp-keepst{margin:var(--s1) 0 0}
.dp-keepbox form{margin-top:var(--s2);padding:var(--s3);border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface)}
.dp-keepopt{display:flex;gap:var(--s2);align-items:flex-start;margin:0 0 var(--s2)}
.dp-keepopt span{display:block}
.dp-keepdup .btn{margin:var(--s1) var(--s2) 0 0}
.dp-todo .actions .btn{margin-right:var(--s1)}
/* 3.11.0 — learner: the Learner Record, rebuilt (Mockup 37). One header
   strip, Recent classes, Coming up, then everything else in closed folds. */
.lr-head .lr-line{margin:var(--s1) 0 0;color:var(--ink-2)}
.lr-head .lr-facts{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s3);align-items:center;margin-top:var(--s2)}
.lr-head .lr-active{font-weight:600}
.lr-head .lr-contact{margin:var(--s2) 0 0;font-size:var(--t-sm);color:var(--ink-2);overflow-wrap:anywhere}
.lr-head .lr-btns{display:flex;flex-wrap:wrap;gap:var(--s2);margin:var(--s3) 0 0}
.lr-head .lr-btns .btn{margin-top:0}
.lr-recent,.lr-coming{padding:var(--s4) var(--s5)}
.lr-rows{list-style:none;margin:0;padding:0}
.lr-row{display:grid;grid-template-columns:7.5em 10em 6em 1fr auto;gap:var(--s1) var(--s3);align-items:start;
  padding:var(--s2) 0;border-top:1px solid var(--line)}
.lr-row:first-child{border-top:0}
.lr-when{font-weight:600;white-space:nowrap}
.lr-note{color:var(--ink-2);font-size:var(--t-sm);min-width:0;overflow-wrap:anywhere}
.lr-coming .lr-row{grid-template-columns:7.5em 12em 1fr auto}
.lr-acts{display:flex;flex-wrap:wrap;gap:var(--s2);justify-content:flex-end;align-items:flex-start}
.lr-acts form.inline{display:inline}
.lr-missed{color:var(--attn);font-size:var(--t-sm)}
.lr-act{position:relative}
.lr-act > summary{list-style:none;cursor:pointer}
.lr-act > summary::-webkit-details-marker{display:none}
.lr-act[open] > summary{background:var(--accent-wash);color:var(--accent)}
.lr-form{margin-top:var(--s2);padding:var(--s3);background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-sm);min-width:16rem;max-width:26rem}
.lr-form p{margin:0 0 var(--s2)}
.lr-why{display:flex;flex-wrap:wrap;gap:var(--s3)}
.lr-why label.check{margin:0}
.lr-targets > li{padding:var(--s1) 0}
.lr-targets label.check{margin:0}
.btn.lr-grey{cursor:not-allowed}
.lr-epoch{margin-top:var(--s2)}
.lr-hist .lr-row{grid-template-columns:9em 1fr auto}
/* the folds: a card each, closed by default, one summary line when closed */
details.lfold{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);margin:var(--s3) 0;box-shadow:var(--lift)}
details.lfold > summary{cursor:pointer;padding:var(--s3) var(--s5);display:flex;flex-wrap:wrap;gap:var(--s1) var(--s3);align-items:baseline;list-style:none}
details.lfold > summary::-webkit-details-marker{display:none}
details.lfold > summary:hover{background:var(--accent-wash)}
.lf-h{font-weight:700;font-size:var(--t-md)}
.lf-sum{color:var(--ink-2);font-size:var(--t-sm);min-width:0;overflow-wrap:anywhere}
.lf-body{padding:0 var(--s5) var(--s4)}
.lf-body > .card{box-shadow:none;margin:var(--s3) 0}
@media (max-width:720px){
  .lr-row,.lr-coming .lr-row,.lr-hist .lr-row{grid-template-columns:1fr;gap:2px}
  .lr-acts{justify-content:flex-start;flex-direction:column;align-items:stretch}
  .lr-acts .btn,.lr-act > summary.btn,.lr-head .lr-btns .btn{width:100%;text-align:center}
  .lr-head .lr-btns{flex-direction:column}
  .lr-form{min-width:0;max-width:none}
  .lr-recent,.lr-coming{padding:var(--s3) var(--s4)}
  details.lfold > summary{padding:var(--s3) var(--s4)}
  .lf-body{padding:0 var(--s3) var(--s3)}
}
.lr-act > summary::before,.lr-act[open] > summary::before{content:none !important;display:none !important}
@media (max-width:720px){
  .lr-recent .lr-row,.lr-coming .lr-row{display:flex;flex-wrap:wrap;gap:2px var(--s2);align-items:baseline}
  .lr-recent .lr-note,.lr-coming .lr-acts{flex:1 1 100%}
}
/* 3.11.0 — message: "Read this message for me" (Mockup 38). Green when sure, amber when not. */
.mai-privacy{margin-top:var(--s2)}
.mai-whynot{margin-left:var(--s2)}
.card.mai h3{margin:var(--s4) 0 var(--s2);font-size:var(--t-base)}
.mai-who{border-radius:8px;padding:var(--s2) var(--s3);margin:0 0 var(--s2)}
.mai-who.ok{background:var(--good-wash)}
.mai-who.warn{background:var(--attn-wash);border-left:3px solid var(--attn)}
.mai-who p{margin:var(--s1) 0}
.mai-picks{display:flex;flex-wrap:wrap;gap:var(--s2)}
.mai-picks .btn{margin-top:0}
.mai-row{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s3);align-items:flex-start;justify-content:space-between;
  border:1px solid var(--line);border-left:3px solid var(--good);border-radius:8px;padding:var(--s2) var(--s3);margin:var(--s2) 0}
.mai-row.warn{border-left-color:var(--attn);background:var(--attn-wash)}
.mai-row.done{border-left-color:var(--line-2);opacity:.8}
.mai-what{flex:1 1 260px;min-width:0;overflow-wrap:anywhere}
.mai-why{color:var(--attn)}
.mai-do{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center}
.mai-pill{display:inline-flex;align-items:center;gap:var(--s1);border:1px solid var(--line-2);border-radius:var(--r-full);
  padding:2px var(--s3);font-size:var(--t-sm);cursor:pointer;background:var(--surface)}
.mai-pill:has(input:checked){border-color:var(--accent);background:var(--accent-wash)}
.mai-change > summary{cursor:pointer;font-size:var(--t-sm);color:var(--accent)}
.mai-change select{max-width:100%;margin-top:var(--s1)}
.mai-other,.mai-skipped{margin:var(--s1) 0 var(--s2)}
.mai-reply{margin-top:var(--s4)}
.mai-reply > summary{cursor:pointer;font-weight:600}
.mai-replytext{width:100%;max-width:100%;box-sizing:border-box;margin-top:var(--s2);font:inherit}
.mai-teacher textarea{width:100%;box-sizing:border-box}
.mai-passed{padding:var(--s2) 0;border-top:1px solid var(--line)}
.mai-passed:first-child{border-top:0}
.mai-passed form{margin-top:var(--s1)}
/* 3.11.0 — roles: several roles on one account (Mockup 41). "Working as" in
   the header, the "Who are you today?" page, and the Roles ticks on Accounts. */
details.rs-switch{position:relative}
details.rs-switch > summary{
  list-style:none;cursor:pointer;white-space:nowrap;color:var(--ink-2);
  padding:var(--s1) var(--s2);border-radius:var(--r-sm);
}
details.rs-switch > summary::-webkit-details-marker{display:none}
details.rs-switch > summary:hover{background:var(--accent-wash)}
details.rs-switch > summary strong{color:var(--ink)}
details.rs-switch .car{font-size:var(--t-xs);color:var(--ink-3)}
.rs-pop{
  position:absolute;z-index:31;top:calc(100% + var(--s1));right:0;min-width:200px;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  padding:var(--s2);box-shadow:var(--lift-2);
  display:flex;flex-direction:column;gap:1px;white-space:nowrap;
}
.rs-pop form{margin:0}
.rs-pop .linkish,.rs-pop a,.rs-pop .rs-on{display:block;width:100%;text-align:left;padding:var(--s2) var(--s3);border-radius:var(--r-sm)}
.rs-pop .linkish:hover,.rs-pop a:hover{background:var(--accent-wash)}
.rs-pop .rs-on{font-weight:600;color:var(--ink)}
@media (max-width:999px){
  .rs-pop{position:static;box-shadow:none;border:0;padding:0 0 var(--s1) var(--s3);min-width:0}
}
.rs-pick{max-width:520px;margin:var(--s6) auto}
.rs-choices{display:flex;flex-direction:column;gap:var(--s3);margin:var(--s4) 0}
.rs-choices .rs-big{font-size:var(--t-md);padding:var(--s4);width:100%}
details.rs-switch > summary::before, details.rs-switch[open] > summary::before{content:none !important;display:none !important}
/* 3.11.1 — att: Mockup 47, attendance at a glance on Enrolments. One dot per
   session (✓ present, – told us before, ✕ no word, ? no mark yet, hollow =
   still to come, grey dash = not on the course yet or taken off). Each dot
   and its session number are one column, so they wrap together on a phone. */
.att-legend{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s4);font-size:var(--t-sm);background:var(--surface-2,var(--accent-wash));border-radius:var(--r-md);padding:var(--s2) var(--s3);margin:0 0 var(--s3)}
.att-legend > span{display:inline-flex;align-items:center;gap:6px}
.att-h .att-sub{display:block;font-weight:400;text-transform:none;letter-spacing:0;font-size:var(--t-xs);cursor:help}
td.att{line-height:1.2;min-width:0}
.att-dots{display:inline-flex;flex-wrap:wrap;gap:3px;vertical-align:top;max-width:100%}
.att-c{display:inline-flex;flex-direction:column;align-items:center;width:18px}
.att-n{font-style:normal;font-size:10px;color:var(--ink-3);line-height:1.3}
.att-d{width:18px;height:18px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-size:11px;font-weight:800;line-height:1;color:var(--surface);text-decoration:none;flex:none;box-sizing:border-box}
a.att-d:hover,a.att-d:focus-visible{box-shadow:var(--focus);text-decoration:none}
.att-d.p{background:var(--good)}
.att-d.e{background:var(--attn)}
.att-d.u{background:var(--prob)}
.att-d.q{border:1.5px dashed var(--ink-3);background:var(--surface);color:var(--ink-2)}
.att-d.f{border:1.5px solid var(--line-2,var(--line));background:var(--surface)}
.att-d.x{background:transparent;border-radius:0}
.att-d.x::after{content:"";width:12px;height:4px;border-radius:2px;background:var(--line-2,var(--line))}
.att-ct{white-space:nowrap;font-size:var(--t-sm);color:var(--ink-2);margin-left:6px;vertical-align:top;line-height:18px}
.att-ct strong{color:var(--ink)}
.att-tag{vertical-align:top;margin-left:4px}
.att-sort{margin:0 0 var(--s1)}
.att-total{color:var(--ink-2);margin:var(--s2) 0 var(--s1)}
.att-total strong{color:var(--ink)}
.att-dash p{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2);margin:0}
.att-dash .btn{margin-left:auto}
ul.att-call li{padding:2px 0}
@media (max-width:640px){
  table.cards td.att{align-items:flex-start}
  .att-ct{margin-left:0}
}
/* 3.11.1 — starter: Mockup 48, when the Starter classes run out. The Next step
   column and settings lines on Starter Programme, the "Starter classes used up"
   group on To do (panels open in place, no script), and the learner page card. */
.st-summary{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;margin:var(--s2) 0;padding:var(--s2) var(--s3);border-radius:8px;background:var(--surface-2)}
.st-settings{margin:0 0 var(--s3)}
.st-setl{display:flex;flex-wrap:wrap;justify-content:space-between;gap:var(--s2);align-items:center;padding:var(--s2) 0;border-bottom:1px solid var(--line);margin:0}
.st-setl form.inline{display:inline-flex;flex-direction:row;flex-wrap:wrap;gap:var(--s1);align-items:center;margin:0}
.st-setl form.inline input[type=date]{width:auto;min-height:0}
.st-next .st-ok,.st-ok{color:var(--good);font-weight:600}
.st-row .st-head{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:center}
.st-facts{color:var(--ink-2);margin:var(--s1) 0}
.st-miss{color:var(--attn);font-weight:600;margin:var(--s1) 0}
.st-passed{border-left:4px solid var(--good);background:var(--good-wash);padding:var(--s2) var(--s3);border-radius:0 8px 8px 0;margin:var(--s1) 0}
.st-over{border-left:4px solid var(--prob);background:var(--prob-wash);padding:var(--s2) var(--s3);border-radius:0 8px 8px 0;margin:var(--s2) 0}
.st-over p{margin:0 0 var(--s1)}
.st-acts{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:flex-start;margin-top:var(--s2)}
.st-acts form.inline{display:inline-flex;gap:var(--s1);margin:0}
details.st-panel > summary{list-style:none;cursor:pointer;display:inline-block}
details.st-panel.st-panel > summary.btn.btn{display:inline-flex;width:auto}
details.st-panel > summary::-webkit-details-marker{display:none}
details.st-panel[open]{flex-basis:100%}
details.st-panel[open] > summary.btn{background:var(--ask-wash);color:var(--ink);border-color:var(--attn)}
.st-form{margin-top:var(--s2);padding:var(--s3);border-radius:8px;background:var(--ask-wash);max-width:40rem}
.st-over .st-form,.st-over form{background:transparent;padding:var(--s1) 0 0;margin:0}
.st-title{margin:0 0 var(--s2)}
.st-pick{border:0;margin:0 0 var(--s2);padding:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(12rem,1fr));gap:var(--s2)}
.st-pick .st-opt{border:1px solid var(--line);border-radius:8px;padding:var(--s2);background:var(--surface)}
.st-opt{display:block;padding:2px 0}
.st-opt .small{display:block}
.st-fld{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:center;margin:var(--s2) 0}
.st-fld > label{flex:0 0 auto;margin:0;width:auto}
.st-fld > input[type=number]{flex:0 0 6rem;width:6rem}
.st-fld input[type=text]{flex:1 1 12rem;width:auto;max-width:100%}
textarea.st-draft{display:block;width:100%;max-width:100%;box-sizing:border-box;font:inherit;font-size:var(--t-sm,14px);margin:var(--s1) 0}
.st-btns{display:flex;flex-wrap:wrap;gap:var(--s2);margin:var(--s2) 0 0}
@media (max-width:640px){.st-pick{grid-template-columns:1fr}.st-form{padding:var(--s2)}}

/* 3.12.0 — bk: Mockup 54, Upload several. The tray is one form; each file is
   a row of four controls that wraps to two lines on a phone. Amber where
   Arcanté is not sure — and the words "not sure" beside it, never colour alone. */
.bk-link{margin:var(--s2) 0 var(--s3)}
.bk-add form{margin:0}
.bk-add input[type=file]{max-width:100%}
.bk-default{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.bk-trayline{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s3);justify-content:space-between;align-items:baseline;background:var(--attn-wash);border-radius:8px;padding:var(--s2) var(--s3);margin:0 0 var(--s3)}
.bk-trayline p{margin:0}
.bk-form{position:relative}
.bk-head,.bk-main{display:grid;grid-template-columns:28px minmax(0,2.2fr) minmax(0,1fr) minmax(0,2.2fr) minmax(0,1.6fr);gap:var(--s2);align-items:center}
.bk-head{font-size:var(--t-xs);letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3);font-weight:700;padding:0 0 var(--s1)}
.bk-row{border-top:1px solid var(--line);padding:var(--s2) 0}
.bk-main select,.bk-main input[type=text]{width:100%;max-width:100%;min-width:0;margin:0}
.bk-name{font-weight:600;word-break:break-word;min-width:0}
.bk-name small{display:block;font-weight:400;color:var(--ink-3);font-size:var(--t-xs)}
.bk-where{display:flex;flex-direction:column;gap:2px;min-width:0}
.bk-where .tag{align-self:flex-start}
.bk-tick{display:flex;align-items:center;justify-content:center;margin:0}
.bk-tick input{width:18px;height:18px;margin:0}
select.bk-unsure{background:var(--attn-wash);border-color:var(--attn);color:var(--attn)}
.bk-more{margin:var(--s1) 0 0 36px}
.bk-more > summary{cursor:pointer}
.bk-panel{background:var(--surface-2);border-radius:8px;padding:var(--s2) var(--s3);margin:var(--s1) 0;max-width:40rem}
.bk-panel label{margin-top:var(--s2)}
.bk-panel p{margin:var(--s2) 0 0}
.bk-group{border:2px solid var(--accent);border-radius:10px;padding:var(--s2) var(--s3);margin:var(--s2) 0;background:var(--surface)}
.bk-ghead{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:center}
.bk-ghead .bk-tick{justify-content:flex-start}
.bk-members{list-style:none;margin:var(--s2) 0 0;padding:0}
.bk-members > li{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr);gap:var(--s1) var(--s2);align-items:center;border-top:1px solid var(--line);padding:var(--s1) 0}
.bk-members > li > input[type=hidden]{display:none}
.bk-members > li > .bk-more{grid-column:1 / -1;margin-left:0}
.bk-members .bk-title input{width:100%;margin:0}
.bk-inline{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center}
.bk-inline label{margin:0}
.bk-inline input{flex:1 1 12rem;width:auto;margin:0}
.bk-bulk{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:flex-start;border-radius:8px;padding:var(--s2) var(--s3);margin:var(--s3) 0 0;background:var(--surface-2);border:1px solid var(--line)}
.bk-form:has(input[name="tick[]"]:checked) .bk-bulk{background:var(--ink);color:var(--bg);border-color:var(--ink)}
.bk-form:has(input[name="tick[]"]:checked) .bk-bulk .bk-panel{color:var(--ink)}
.bk-bulk-say{font-weight:700;padding-top:4px}
.bk-tool > summary{list-style:none;cursor:pointer}
.bk-tool > summary::-webkit-details-marker{display:none}
.bk-tool[open]{flex-basis:100%}
.bk-merge fieldset{border:0;margin:0;padding:0}
.bk-choice{display:block;font-weight:600;margin-top:var(--s2)}
.bk-sub{margin:0 0 var(--s2) var(--s5);padding-left:var(--s2);border-left:2px solid var(--line-2)}
.bk-off{color:var(--ink-3)}
.bk-go{margin-top:var(--s3)}
.bk-sum{list-style:none;margin:var(--s2) 0;padding:0}
.bk-sum li{padding:var(--s1) 0;border-top:1px solid var(--line)}
.bk-k-repertoire{background:var(--accent-wash);color:var(--accent)}
.bk-k-curriculum{background:var(--good-wash);color:var(--good)}
.bk-k-documents{background:var(--surface-2);color:var(--ink-2)}
.bk-notready{border-left:4px solid var(--line-2);background:var(--surface-2);padding:var(--s2) var(--s3);border-radius:0 8px 8px 0;margin:var(--s2) 0}
.bk-notready ul{margin:var(--s1) 0 0;padding-left:1.2em}
.bk-dup{border-left:4px solid var(--attn);background:var(--attn-wash);padding:var(--s2) var(--s3);border-radius:0 8px 8px 0;margin:var(--s2) 0}
.bk-dupone{border:0;margin:var(--s2) 0 0;padding:0}
.bk-dupone legend{padding:0}
.bk-dupone .bk-choice{display:inline-flex;gap:4px;align-items:center;margin:var(--s1) var(--s3) 0 0;font-weight:600}
.bk-filedlist{list-style:none;margin:0;padding:0}
.bk-filedlist li{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;border-top:1px solid var(--line);padding:var(--s1) 0}
.printlist li.bk-part{margin-left:var(--s5);border-left:2px solid var(--line-2);padding-left:var(--s2)}
@media (max-width:760px){
  .bk-head{display:none}
  .bk-main{grid-template-columns:28px minmax(0,1fr) minmax(0,1fr)}
  .bk-main .bk-name{grid-column:2 / 4}
  .bk-main .bk-kind{grid-column:2 / 3}
  .bk-main .bk-where{grid-column:3 / 4}
  .bk-main .bk-title{grid-column:2 / 4}
  .bk-more{margin-left:0}
  .bk-members > li{grid-template-columns:minmax(0,1fr)}
  .bk-sub{margin-left:var(--s2)}
  .printlist li.bk-part{margin-left:var(--s2)}
}
.bk-np{margin-top:var(--s2)}

/* =====================================================================
   3.12.0 — Mockup 53: To do in three bands, and the Monday review card.
   No script: every "press to open" is a <details>.
   ===================================================================== */
.td-bands{margin:var(--s3) 0 var(--s4)}
.td-band{border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface);margin:0 0 var(--s2)}
.td-band > summary,.td-empty{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;padding:var(--s2) var(--s3);font-size:var(--t-md);list-style:none;cursor:pointer}
.td-empty{margin:0 0 var(--s2);cursor:default;color:var(--ink-3)}
.td-band > summary::-webkit-details-marker,.td-grp > summary::-webkit-details-marker,.td-mr > summary::-webkit-details-marker,.td-step > summary::-webkit-details-marker{display:none}
.td-notneeded > summary::before,.td-notneeded[open] > summary::before{content:none !important;display:none !important}
.td-c{margin-left:auto;font-size:var(--t-sm);font-weight:600;color:var(--ink-3)}
.td-dot{display:inline-block;width:10px;height:10px;border-radius:50%;background:var(--line-2)}
.td-band-a{border-color:var(--prob)}
.td-band-a > summary{background:var(--prob-wash);border-radius:var(--r-md) var(--r-md) 0 0}
.td-band-a .td-dot{background:var(--prob)}
.td-band-b .td-dot{background:var(--attn)}
.td-grp{border-top:1px solid var(--line)}
.td-grp > summary{display:flex;align-items:flex-start;gap:var(--s1) var(--s2);flex-wrap:wrap;padding:var(--s2) var(--s3);list-style:none;cursor:pointer}
.td-grp[open] > summary{background:var(--surface-2)}
.td-label{font-weight:600;flex:1 1 14rem;min-width:0}
.td-hint{font-size:var(--t-sm);color:var(--ink-3)}
.td-items{flex:1 1 100%;display:flex;flex-direction:column;gap:2px;margin:2px 0 0 0}
.td-item{display:flex;gap:var(--s2);flex-wrap:wrap;font-size:var(--t-sm);padding:2px 0;border-top:1px dashed var(--line)}
.td-what{flex:1 1 14rem;min-width:0}
.td-age{color:var(--ink-3);white-space:nowrap}
.td-more{color:var(--ink-3)}
.td-body{padding:0 var(--s3) var(--s3)}
.td-body > .band{border-top:0;padding-top:var(--s2)}
.td-why{margin:var(--s2) 0 0}
.td-follow{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:center;margin:var(--s1) 0 var(--s2)}
.td-follow .btn,.td-follow form{margin:0}
.td-notneeded > summary{list-style:none;cursor:pointer;display:inline-block}
.td-notneeded > summary::-webkit-details-marker{display:none}
.td-notneeded[open]{flex-basis:100%}
.td-notneeded form.td-why{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;margin-top:var(--s2)}
.td-notneeded form.td-why input[type=text]{flex:1 1 14rem;width:auto;margin:0}
.att-call > li{padding:var(--s2) 0;border-top:1px solid var(--line)}
.td-recent{margin-top:var(--s2)}
.td-recent li{padding:var(--s1) 0}
.td-np > li{padding:var(--s2) 0;border-top:1px solid var(--line)}
.td-all{margin:var(--s4) 0}
.td-all > summary{cursor:pointer;color:var(--ink-2)}
/* the Monday review */
.td-mr{border:2px solid var(--accent);border-radius:var(--r-md);background:var(--surface);margin:var(--s3) 0}
.td-mr > summary{display:flex;align-items:center;gap:var(--s2) var(--s3);flex-wrap:wrap;padding:var(--s2) var(--s3);list-style:none;cursor:pointer}
.td-mr-line,.td-mr-closed{padding:var(--s2) var(--s3)}
.td-mr-line p,.td-mr-closed p{margin:0;display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:center}
.td-mr-line form{margin:0}
.td-mr-closed{border-color:var(--good);background:var(--good-wash)}
.td-mr-prev{margin:var(--s3) 0 0;color:var(--attn)}
.td-mr-body{padding:0 var(--s3) var(--s3)}
.td-pips{display:inline-flex;gap:3px}
.td-pips i{display:inline-block;width:18px;height:6px;border-radius:3px;background:var(--line)}
.td-pips i.on{background:var(--good)}
.td-step{border-top:1px solid var(--line);padding:var(--s2) 0}
.td-step > summary{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;list-style:none;cursor:pointer}
.td-sw{flex:1 1 14rem;min-width:0}
.td-ct{font-size:var(--t-sm);font-weight:700;white-space:nowrap}
.td-box{display:inline-flex;width:20px;height:20px;flex:0 0 20px;border:2px solid var(--line-2);border-radius:4px;align-items:center;justify-content:center;font-size:13px;font-weight:800;color:#fff}
.td-box.on{background:var(--good);border-color:var(--good)}
.td-step-in{padding:var(--s2) 0 0 28px}
.td-mini > li{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:center;padding:var(--s1) 0;border-top:1px dashed var(--line)}
.td-mini > li > span:first-child{flex:1 1 14rem;min-width:0}
.td-mini form{margin:0}
.td-tick,.td-cover{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;margin:var(--s2) 0 0}
.td-tick label,.td-cover label{flex:1 1 100%;font-size:var(--t-sm);font-weight:600}
.td-tick input[type=text]{flex:1 1 14rem;width:auto;margin:0}
.td-cover select{width:auto;max-width:100%;margin:0}
.td-glance{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--s2);margin:var(--s1) 0 var(--s2)}
.td-glance div{background:var(--surface-2);border-radius:8px;padding:var(--s2);font-size:var(--t-sm);color:var(--ink-2)}
.td-glance b{display:block;font-size:var(--t-lg);color:var(--ink)}
.td-mr-foot{margin:var(--s3) 0 0}
@media (max-width:760px){
  .td-glance{grid-template-columns:repeat(2,minmax(0,1fr))}
  .td-step-in{padding-left:0}
}

/* ---------------------------------------------------------------------
   3.13.0 — Mockup 61: files on each scale. ▶ Play · 🖨 Print beside a
   scale (class page, learner's page), a scale's Files on Class plans,
   Print today's scales, and the Scale kind in Upload several.
   --------------------------------------------------------------------- */
/* Beside the tick, never inside it: the line wraps, an opened list goes under it. */
ul.skrows li.skr.hasf{display:flex;flex-wrap:wrap;align-items:center;gap:0 var(--s2)}
ul.skrows li.skr.hasf > form{flex:1 1 14rem;min-width:0}
ul.skrows li.skr.hasf > span.tick + .skt{flex:1 1 10rem}
.sf-chips,ul.skrows li.skr > span.sf-chips{display:contents}
.sf-chips > details.play,.sf-chips > a.ico{flex:0 0 auto;margin:var(--s1) 0}
.sf-chips > details[open]{flex:1 1 100%;order:5;margin:0 0 var(--s2)}
.sf-chips > details[open] > summary{width:max-content;max-width:100%;margin-bottom:var(--s1)}
ul.sf-pls{list-style:none;margin:var(--s1) 0 0;padding:0}
.sf-pl,.sf-pr{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:center;margin:var(--s1) 0}
.sf-pl > span{flex:0 0 9rem;font-size:var(--t-sm);font-weight:600;min-width:0}
.sf-pl audio,details.play .sf-pl audio{flex:1 1 14rem;min-width:0;width:auto;max-width:100%;margin:0}
.sf-pr > span{flex:1 1 12rem;font-size:var(--t-sm);min-width:0}
ul.skgrid > li .sf-chips > details[open]{flex-basis:100%}
.sf-printday{margin:var(--s2) 0 0}
/* Class plans: the Files fold at the end of each checklist line. */
.skline{display:flex;flex-wrap:wrap;align-items:center;gap:0 var(--s2);border-bottom:1px solid var(--line)}
.skline > form.skrow{flex:1 1 30rem;min-width:0;border-bottom:0}
.skline > details.sf-files{flex:0 0 auto}
.skline > details.sf-files[open]{flex:1 1 100%}
details.sf-files > summary{cursor:pointer;white-space:nowrap;padding:var(--s1) 0}
.sf-panel{background:var(--surface-2);border-radius:8px;padding:var(--s2) var(--s3);margin:0 0 var(--s2)}
ul.sf-list{list-style:none;margin:0;padding:0}
ul.sf-list > li{display:grid;grid-template-columns:minmax(0,9rem) minmax(0,1fr) auto;gap:var(--s1) var(--s3);align-items:center;padding:var(--s2) 0;border-bottom:1px solid var(--line)}
.sf-k{font-weight:700;font-size:var(--t-sm)}
.sf-n{min-width:0;word-break:break-word;font-size:var(--t-sm)}
.sf-n small{display:block;color:var(--ink-3);font-size:var(--t-xs)}
.sf-act{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:center;justify-content:flex-end}
.sf-act > details.sf-change[open]{flex:1 1 100%}
ul.sf-list > li:has(details.sf-change[open]) .sf-act{grid-column:1 / -1;justify-content:flex-start}
.sf-form{background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:var(--s2) var(--s3);margin-top:var(--s1)}
.sf-form form{margin:0 0 var(--s2)}
.sf-repl{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:center;border-top:1px solid var(--line);padding-top:var(--s2)}
.sf-repl label{flex:1 1 100%;margin:0}
.sf-repl input[type=file]{flex:1 1 14rem;min-width:0;width:auto;margin:0}
.sf-shared{margin:var(--s2) 0;color:var(--ink-2)}
.sf-add{border-top:1px solid var(--line);margin-top:var(--s2);padding-top:var(--s2)}
.sf-add h4{margin:0 0 var(--s1)}
.sf-what,.sf-where{border:0;margin:var(--s2) 0 0;padding:0;min-width:0}
.sf-what legend,.sf-where legend{padding:0;font-weight:600;font-size:var(--t-sm)}
.sf-choice{display:inline-flex;align-items:center;gap:4px;margin:var(--s1) var(--s3) 0 0;font-weight:500}
.sf-where .sf-choice{display:flex}
.sf-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0 var(--s3);align-items:end}
.sf-grid label{grid-row:1;margin-top:var(--s2);font-size:var(--t-sm)}
.sf-grid input{grid-row:2;width:100%;min-width:0;margin:0}
.sf-more{margin:var(--s2) 0}
.sf-more > summary{cursor:pointer}
/* Print today's scales */
ul.sf-plist{list-style:none;margin:var(--s2) 0;padding:0}
.sf-pline{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s3);align-items:center;border-top:1px solid var(--line);padding:var(--s2) 0}
.sf-ptick{flex:1 1 16rem;display:flex;gap:var(--s2);align-items:center;margin:0;font-weight:600;min-width:0}
.sf-ptick input{width:20px;height:20px;margin:0;flex:0 0 20px}
.sf-pother > span:first-child{flex:1 1 16rem;min-width:0}
.sf-copies{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:center;margin:var(--s3) 0 var(--s1)}
.sf-copies label{margin:0}
.sf-copies input{width:5.5rem;margin:0}
.sf-nojoin{border-left:4px solid var(--attn);background:var(--attn-wash);padding:var(--s2) var(--s3);border-radius:0 8px 8px 0}
.sf-prest{margin:var(--s2) 0}
.sf-prest > summary{cursor:pointer}
/* Upload several: the Scale kind */
.bk-k-scale{background:var(--attn-wash);color:var(--ink-2)}
.bk-swhat{display:flex;gap:var(--s1);min-width:0}
.bk-swhat select{flex:1 1 auto;min-width:0}
.bk-main .bk-swhat input[type=number]{flex:0 0 4.5rem;width:4.5rem;margin:0}
@media (max-width:760px){
  ul.sf-list > li{grid-template-columns:minmax(0,1fr)}
  .sf-act{justify-content:flex-start}
  .sf-grid{grid-template-columns:minmax(0,1fr)}
  .sf-grid label,.sf-grid input{grid-row:auto}
  .sf-pl > span{flex-basis:100%}
}

/* =====================================================================
   3.13.0 — Mockup 59: summaries that say what they were made from.
   ===================================================================== */
.cs-notr,.cs-norep{white-space:nowrap}
.cs-mf{color:var(--ink-2);margin:var(--s2) 0 var(--s1)}
.cs-mfv.ok{color:var(--good)}
.cs-mfv.gap{color:var(--attn);font-weight:600}
.cs-given{margin:0 0 var(--s3)}
.cs-dl{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:var(--s1) var(--s3);margin:var(--s2) 0;font-size:var(--t-sm)}
.cs-dl dt{font-weight:600;color:var(--ink-2)}
.cs-dl dd{margin:0;min-width:0}
.cs-notr-line{margin:var(--s2) 0;font-size:var(--t-sm);color:var(--attn)}
.cs-wait,.cs-since-box{border-left:4px solid var(--attn);background:var(--attn-wash);padding:var(--s2) var(--s3);border-radius:0 8px 8px 0;margin:var(--s2) 0}
.cs-wait p{margin:var(--s1) 0}
.cs-anyway{margin-top:var(--s2)}
.cs-anyway > summary{cursor:pointer;color:var(--ink-2);font-size:var(--t-sm)}
.cs-since-box p{margin:0 0 var(--s1)}
.cs-checkform{display:inline-flex;flex-wrap:wrap;gap:var(--s2);align-items:center}
.cs-against{margin:0;font-size:var(--t-sm);max-width:36rem}
.wr-mfline{border-left:4px solid var(--attn);background:var(--attn-wash);padding:var(--s2) var(--s3);border-radius:0 8px 8px 0;margin:0 0 var(--s3)}
.wr-mfline p{margin:0 0 var(--s1)}
.wr-ask{border:1px solid var(--line-2);border-radius:var(--r-md);background:var(--surface);padding:var(--s3) var(--s4);margin:var(--s3) 0}
.wr-ask h3{margin:0 0 var(--s1)}
.wr-askrow{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;margin:var(--s2) 0}
.wr-askrow .btn{margin:0}
.wr-waiting{margin:var(--s2) 0}

/* 3.13.0 — Mockup 68: what teachers see once a summary is checked. */
.cs-ask{border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface-2);padding:var(--s2) var(--s3);margin:var(--s2) 0 var(--s3)}
.cs-ask.open{border-color:var(--accent);background:var(--accent-wash)}
.cs-ask p{margin:var(--s1) 0}
.cs-ask .cs-fair h3{margin:var(--s2) 0 var(--s1)}
.cs-chg.add{color:var(--good)}
.cs-chg.del{color:var(--prob)}
.cs-waitcard h2{margin-bottom:var(--s1)}
ul.cs-waitlist{margin:var(--s2) 0;padding:0}
.cw-row{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s3);align-items:center;border-top:1px solid var(--line);padding:var(--s2) 0}
.cw-what{flex:1 1 18rem;min-width:0}
.cw-what .small{display:block}
.cw-act{display:flex;gap:var(--s2);align-items:center}
.cw-act .btn,.cw-act form{margin:0}
ul.ms-list{margin:0;padding:0}
.ms-row{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s3);align-items:center;border-top:1px solid var(--line);padding:var(--s2) 0}
.ms-what{flex:0 1 14rem;min-width:0}
.ms-state{flex:1 1 16rem;min-width:0}
.ms-go .btn{margin:0}

/* =====================================================================
   3.13.0 — Mockup 62: the day page's one line, packs for new learners,
   and the register footer on one line.
   ===================================================================== */
.rail.jumpline{flex-wrap:wrap;align-items:center;gap:var(--s1)}
.rail.jumpline a{min-height:30px;padding:2px var(--s2);font-size:var(--t-xs)}
.rail.jumpline a.done{color:var(--good);border-color:var(--good)}
.jl-class{display:inline-flex;flex-wrap:wrap;align-items:center;gap:0;padding:0 4px;border-radius:var(--r-full);border:1px solid var(--line-2);background:var(--surface)}
.jl-class.here{background:var(--accent-wash);border-color:var(--accent)}
.rail.jumpline .jl-class a{border:0;background:transparent;padding:2px 6px;min-height:30px}
.rail.jumpline .jl-class a:hover{color:var(--accent);text-decoration:underline}
.rail.jumpline .jl-name{font-weight:700;color:var(--ink)}
.jumpfold{display:none;margin:var(--s3) 0 var(--s2);border:1px solid var(--line-2);border-radius:var(--r-md);background:var(--surface)}
.jumpfold > summary{display:flex;justify-content:space-between;gap:var(--s2);align-items:center;padding:var(--s2) var(--s3);cursor:pointer;list-style:none;font-weight:600}
.jumpfold > summary::-webkit-details-marker{display:none}
details.jumpfold > summary::before,details.jumpfold[open] > summary::before{content:none !important;display:none !important}
.jumpfold .jf-all{color:var(--accent);font-weight:400;white-space:nowrap}
.jumpfold .jf-all::after{content:" ▾"}
.jumpfold[open] .jf-all{font-size:0}
.jumpfold[open] .jf-all::after{content:"Close ▴";font-size:var(--t-sm)}
.jumpfold ul{margin:0;padding:0 var(--s3) var(--s2)}
.jumpfold li{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s3);align-items:center;border-top:1px solid var(--line);padding:var(--s2) 0}
.jumpfold li.here{background:var(--accent-wash)}
.jumpfold li > span:first-child{flex:1 1 9rem;font-weight:600;min-width:0}
.jumpfold a.done{color:var(--good)}
@media (max-width:760px){
  .rail.jumpline{display:none}
  .jumpfold{display:block}
}
.dp-why{margin:var(--s1) 0 var(--s2)}
.dp-why > summary{cursor:pointer;color:var(--ink-2)}
.dp-why p{margin:var(--s1) 0}
.dp-treat{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s3);align-items:center;margin:0 0 var(--s2)}
.dp-treat .seg button{min-height:32px}
.dp-newl,.dp-firstf{font-size:var(--t-xs)}
.row.saverow.regfoot{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:var(--s2);margin:var(--s3) 0 var(--s2)}
.regfoot .regactions{margin:0}
.regsave{display:inline-flex;align-items:center;gap:var(--s2);margin-left:auto}
.regsave .btn{margin:0}
.regcount{color:var(--ink-2)}
.regcount.ok{color:var(--good)}
.sb-unmarked{margin:var(--s2) 0;padding:var(--s2) var(--s3);border-left:4px solid var(--attn);background:var(--attn-wash);border-radius:0 8px 8px 0;font-size:var(--t-sm)}
@media (max-width:760px){
  .row.saverow.regfoot{flex-direction:column-reverse;align-items:stretch}
  .regsave{margin-left:0;justify-content:space-between}
}

/* ==================================================================
   3.13.0 — Mockup 69: playback speed without changing the pitch.
   The chip and panel are added by assets/player.js under every player;
   without the script none of this is drawn. Violet = interactive, so the
   chip is ink when at real speed and violet when it is not (so nobody
   forgets the track is slowed down).
   ================================================================== */
.pl-bpm{font-size:var(--t-sm);color:var(--ink-2);font-variant-numeric:tabular-nums;white-space:nowrap;margin-right:var(--s2)}
details.play > summary .pl-bpm{font-weight:400;margin:0 0 0 var(--s1)}
.spd{margin:var(--s1) 0 var(--s2);max-width:100%}
.spd-chip{font:inherit;font-size:var(--t-sm);border:1px solid var(--line-2);background:var(--surface);color:var(--ink-2);
  border-radius:var(--r-full);padding:2px var(--s3);min-height:28px;cursor:pointer;font-variant-numeric:tabular-nums}
.spd-chip:hover{border-color:var(--accent);color:var(--accent)}
.spd-chip.spd-off{background:var(--accent-wash);border-color:var(--accent);color:var(--accent);font-weight:600}
.spd-sum{font-weight:400;color:var(--accent)}
.spd-panel{margin-top:var(--s2);padding:var(--s3);border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface-2);
  display:flex;flex-direction:column;gap:var(--s2);max-width:34rem}
.spd-panel[hidden]{display:none}
.spd-row,.spd-quick,.spd-tempo,.spd-ask{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2)}
.spd-tempo[hidden],.spd-ask[hidden]{display:none}
.spd-b,.spd-q,.spd-reset{font:inherit;font-size:var(--t-sm);border:1px solid var(--line-2);background:var(--surface);color:var(--ink);
  border-radius:var(--r-sm);padding:var(--s1) var(--s3);min-height:32px;cursor:pointer;font-variant-numeric:tabular-nums}
.spd-b:hover,.spd-q:hover,.spd-reset:hover{border-color:var(--accent);color:var(--accent)}
.spd-b:disabled{opacity:.45;cursor:default}
.spd-q.on{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.spd-now{min-width:5.5em;text-align:center;font-weight:600;font-variant-numeric:tabular-nums}
.spd-lbl{font-size:var(--t-sm);color:var(--ink-2)}
.spd input.spd-bpm{width:6em;flex:0 0 auto;min-height:32px;margin:0}
.spd label.spd-lbl{display:inline;width:auto;margin:0;font-weight:400}
.spd-tempo .spd-lbl,.spd-ask .spd-lbl{flex-basis:100%}
.spd-unit{font-size:var(--t-sm);color:var(--ink-2)}
.spd-reset{align-self:flex-start}
.spd-say{flex-basis:100%;margin:0;font-size:var(--t-sm);color:var(--ink-2)}
.spd-fine{margin:0;font-size:var(--t-xs);color:var(--ink-3)}
.spd-ask .spd-fine{flex-basis:100%}
details.pl-tempo{display:inline-block}
details.pl-tempo[open]{display:block;margin:var(--s1) 0}
details.pl-tempo form{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2)}
details.pl-tempo input{width:6em}
/* On a phone at the class (often playing to a speaker): big buttons. */
@media (max-width:640px){
  .spd-panel{max-width:none;padding:var(--s3) var(--s2)}
  .spd-b,.spd-q,.spd-reset,.spd-bpm{min-height:44px;font-size:var(--t-base)}
  .spd-row{display:grid;grid-template-columns:1fr 1fr}
  .spd-row .spd-now{grid-column:1 / -1;order:-1}
  .spd-row .spd-b{white-space:nowrap}
  .spd-quick .spd-lbl{flex-basis:100%}
  .spd-quick .spd-q{flex:1 1 0;min-width:0;white-space:nowrap;padding:var(--s1) var(--s2)}
  .spd input.spd-bpm{flex:1 1 4em}
  .spd-reset{align-self:stretch}
}

/* ==================================================================
   3.13.0 — Mockup 66: Transcribe inside Arcanté (the day's recordings,
   Settings → Transcription). No script.
   ================================================================== */
.tr-all,.tr-check{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2);margin:var(--s2) 0}
.tr-go{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s1) var(--s2);margin:0 0 var(--s1)}
.tr-sent{margin:0 0 var(--s1);font-size:var(--t-sm)}
.tr-bad{margin:0 0 var(--s1);padding:var(--s1) var(--s2);border-left:3px solid var(--prob);background:var(--prob-wash);border-radius:0 6px 6px 0}
.tr-blocked,.tr-notset{margin:var(--s1) 0}
.tag.tr-auto{background:var(--surface-2);color:var(--ink-2)}
.tr-len{display:block}
.tr-read{margin-top:var(--s1)}
.tr-lines{margin:var(--s1) 0;padding:var(--s2) var(--s3);background:var(--surface-2);border-radius:var(--r-sm);font-size:var(--t-sm);max-width:40rem}
.tr-lines p{margin:0 0 var(--s1);overflow-wrap:anywhere}
.tr-trail ul{margin:var(--s2) 0;padding-left:var(--s4)}
.tr-block{margin:var(--s2) 0 0}
.tr-settings h2{font-size:var(--t-md);margin:var(--s5) 0 var(--s2)}
.tr-sumline{margin:0 0 var(--s3)}
.tr-privacy{padding:var(--s3) var(--s4);border-left:4px solid var(--attn);background:var(--attn-wash);border-radius:0 8px 8px 0}
.tr-privacy h2{margin-top:0}
.tr-quote{margin:var(--s2) 0;padding:var(--s2) var(--s3);background:var(--surface);border-radius:var(--r-sm);font-size:var(--t-sm)}
.tr-prov{list-style:none;padding:0;margin:0}
.tr-prov li{padding:var(--s2) 0;border-bottom:1px solid var(--line)}
.tr-prov li .small{display:block}
.tr-cfg{white-space:pre-wrap;overflow-wrap:anywhere;font-size:var(--t-sm);background:var(--surface-2);padding:var(--s2) var(--s3);border-radius:var(--r-sm)}
.tr-form .check{display:block;margin:var(--s1) 0}
.tr-form input[name=limit]{max-width:8em}
.settings-link{margin:0 0 var(--s3)}

/* ==================================================================
   3.13.0 — Mockup 56: Defer a learner to a later term. No script.
   ================================================================== */
.df-card h2{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s2)}
.df-facts{display:grid;grid-template-columns:max-content 1fr;gap:var(--s1) var(--s3);margin:var(--s2) 0;font-size:var(--t-sm)}
.df-facts dt{color:var(--ink-2)}
.df-facts dd{margin:0}
.df-step,.df-open{margin:var(--s2) 0}
.df-step > summary,.df-open > summary{list-style:none;display:inline-block}
.df-step > summary::-webkit-details-marker,.df-open > summary::-webkit-details-marker{display:none}
.df-step[open],.df-open[open]{padding:var(--s3);border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface-2)}
.df-draft{width:100%;font-size:var(--t-sm);font-family:inherit}
.df-offer{margin:var(--s2) 0}
.df-offer > summary{cursor:pointer;font-size:var(--t-sm)}
.df-inline{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2);margin-top:var(--s3)}
.df-inline input{max-width:12em}
.df-choice{display:block;margin:var(--s1) 0;font-weight:400}
.df-to,.df-why{border:0;padding:0;margin:var(--s2) 0}
.df-to legend,.df-why legend{font-weight:600;padding:0}
.df-to select{max-width:16em;margin-left:var(--s4)}
.df-change{margin:var(--s1) 0 var(--s2)}
.df-does{padding-left:var(--s4)}
.df-offered{font-size:var(--t-sm)}
.df-past{padding-left:var(--s4)}
.df-todo{list-style:none;padding:0;margin:var(--s2) 0}
.df-row{padding:var(--s2) 0;border-bottom:1px solid var(--line)}
.df-row p{margin:0 0 var(--s1)}
.df-row.urgent strong{color:var(--prob)}
.df-acts{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center}
.df-acts form{margin:0}
tr.df-deferred td{color:var(--ink-3)}
tr.df-deferred td a{color:var(--ink-2)}
.df-off{margin:var(--s2) 0 0;font-size:var(--t-sm);color:var(--ink-3)}
.lr-deferred{color:var(--ink-2)}

/* =====================================================================
   3.13.0 — Mockup 67 (+ v2): the week ladder at the top of the Week review
   ===================================================================== */
.wl-head h2{margin:0}
.wl-head p{margin:var(--s1) 0 var(--s2);display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center}
.wl-sq{display:inline-flex;gap:3px;flex-wrap:wrap}
.wl-sq i{display:inline-block;width:10px;height:10px;border-radius:2px;border:1px solid var(--line-2);background:var(--surface)}
.wl-sq i.d{background:var(--good);border-color:var(--good)}
.wl-sq i.g{background:var(--attn);border-color:var(--attn)}
.wl-sq i.c{background:var(--accent);border-color:var(--accent)}
.wl-sq i.a{border-style:dashed;border-color:var(--accent)}
.wl-stages{list-style:none;margin:0;padding:0;display:grid;gap:var(--s1)}
.wl-st{border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface)}
.wl-st > summary{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s1) var(--s2);padding:var(--s2) var(--s3);cursor:pointer;list-style:none}
.wl-st > summary::-webkit-details-marker{display:none}
.wl-num{display:inline-flex;align-items:center;justify-content:center;min-width:1.7em;height:1.7em;border-radius:var(--r-full);background:var(--surface-2);color:var(--ink-2);font-weight:700;font-size:var(--t-sm)}
.wl-name{font-weight:600}
.wl-ct{color:var(--ink-2);flex:1 1 16em;min-width:0;overflow-wrap:anywhere}
.wl-tag{display:inline-block;font-size:var(--t-xs);letter-spacing:.06em;padding:1px 6px;border-radius:var(--r-sm);background:var(--accent);color:var(--accent-ink);vertical-align:middle}
.wl-body{padding:0 var(--s3) var(--s3);overflow-wrap:anywhere}
.wl-done .wl-num{background:var(--good-wash);color:var(--good)}
.wl-gaps .wl-num{background:var(--attn-wash);color:var(--attn)}
.wl-now{border-color:var(--accent);box-shadow:var(--lift)}
.wl-now .wl-num{background:var(--accent);color:var(--accent-ink)}
.wl-along{border-style:dashed;border-color:var(--accent)}
.wl-later{opacity:.72}
.wl-later .wl-name{color:var(--ink-2)}
.wl-why{background:var(--attn-wash);color:var(--attn);padding:var(--s1) var(--s2);border-radius:var(--r-sm)}
.wl-mini li{display:flex;flex-wrap:wrap;gap:var(--s1);align-items:baseline;padding:2px 0}
.wl-acts{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center}
.wl-form{display:grid;gap:var(--s1);max-width:40em;margin-top:var(--s2)}
.wl-form input[type=text],.wl-form textarea{width:100%}
.wl-gapsform{margin-top:var(--s2)}
.wl-archived{background:var(--surface-2);border-radius:var(--r-md);padding:var(--s2) var(--s3);margin:0 0 var(--s2)}
.wl-reopened{background:var(--attn-wash);color:var(--attn);border-radius:var(--r-sm);padding:var(--s1) var(--s2);margin:0 0 var(--s1)}
.wl-confirm{border:1px solid var(--accent);border-radius:var(--r-md);padding:var(--s2) var(--s3);background:var(--accent-wash)}
.wl-buckets{display:flex;flex-wrap:wrap;gap:var(--s2);margin:0 0 var(--s2)}
.wl-buckets div{flex:1 1 7em;border-radius:var(--r-md);padding:var(--s2) var(--s3);font-size:var(--t-sm);background:var(--surface-2);color:var(--ink-2)}
.wl-buckets b{display:block;font-size:var(--t-xl);color:var(--ink)}
.wl-buckets .b-now b{color:var(--prob)}.wl-buckets .b-look b{color:var(--attn)}.wl-buckets .b-fine b{color:var(--good)}
.wl-tick{margin-top:var(--s2)}
.wl-lc{border-top:1px solid var(--line);margin-top:var(--s3);padding-top:var(--s2)}
.wl-lc h3{font-size:var(--t-md);margin:var(--s2) 0}
.wl-lc h4{font-size:var(--t-base);margin:var(--s2) 0 var(--s1)}
.lc-list li{display:flex;flex-wrap:wrap;gap:var(--s1);align-items:baseline;padding:var(--s1) 0;border-bottom:1px solid var(--line)}
.lc-seen li{padding:2px 0}
.lc-form{display:grid;gap:var(--s2);max-width:44em}
.lc-form fieldset{border:0;padding:0;margin:0;display:flex;flex-wrap:wrap;gap:var(--s1) var(--s3)}
.lc-form textarea,.lc-form input[type=text]{width:100%}
.wl-happy{margin-top:var(--s2)}
.wl-chips{display:flex;flex-wrap:wrap;gap:var(--s1)}
.wl-chip{display:inline-block;padding:2px 8px;border-radius:var(--r-full);border:1px solid var(--line-2);font-size:var(--t-sm);text-decoration:none;color:var(--ink-2)}
.wl-chip.ok{background:var(--good-wash);color:var(--good);border-color:transparent}
.wl-chip.on{border-color:var(--accent);color:var(--accent);font-weight:600}
.wl-nx-cols{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--s3)}
@media (max-width:760px){.wl-nx-cols{grid-template-columns:minmax(0,1fr)}}
.wl-nx-props ul li{padding:var(--s1) 0}
.wl-nx-list{background:var(--surface-2);border-radius:var(--r-md);padding:var(--s2) var(--s3)}
.wl-moved{background:var(--attn-wash);color:var(--attn);padding:var(--s1) var(--s2);border-radius:var(--r-sm)}
.wl-ideas li{padding:var(--s1) 0;border-bottom:1px solid var(--line)}
.wk-cards > summary{cursor:pointer;margin:var(--s3) 0 var(--s2)}
.wk-week-tag{white-space:nowrap}
.pw-stage{display:inline-flex;align-items:center;gap:var(--s1);flex-wrap:wrap}
.pw-arch{margin-top:var(--s2)}
.wl-archbefore{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:end;margin-top:var(--s2)}
.ro-archived{background:var(--surface-2)}

/* =====================================================================
   3.13.0 — Mockup 58: Office → Teacher pay (hours only)
   ===================================================================== */
.tp-weeks{display:grid;gap:var(--s2)}
.tp-week{border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface)}
.tp-week > summary{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:baseline;padding:var(--s2) var(--s3);cursor:pointer}
.tp-hint{flex:1 1 100%;min-width:0;overflow-wrap:anywhere}
.tp-body{padding:0 var(--s3) var(--s3);overflow-wrap:anywhere}
.tp-problems{background:var(--prob-wash);border-radius:var(--r-md);padding:var(--s2) var(--s3);margin:0 0 var(--s2)}
.tp-prob{padding:var(--s1) 0;border-bottom:1px solid var(--line)}
.tp-prob p{margin:0 0 var(--s1)}
.tp-acts{display:flex;flex-wrap:wrap;gap:var(--s1);align-items:center}
.tp-form{display:grid;gap:var(--s1);margin-top:var(--s1);max-width:36em}
.tp-form input[type=text]{width:100%}
.tp-teacher{border-top:1px solid var(--line);padding:var(--s1) 0}
.tp-teacher > summary{cursor:pointer;display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:baseline}
.tp-sum td{font-weight:700}
.tp-sign,.tp-signed,.tp-adj{margin-top:var(--s3)}
.tp-confirm > summary,.tp-send > summary{display:inline-block;cursor:pointer;margin-bottom:var(--s2)}
.tp-copy{width:100%;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:var(--t-sm);white-space:pre;overflow:auto;tab-size:16}
.tp-decided li{padding:2px 0}
.tp-note{background:var(--surface-2);padding:var(--s1) var(--s2);border-radius:var(--r-sm)}
.tp-earlier > summary{cursor:pointer;margin:var(--s1) 0}
.xs-paid{display:inline-flex;gap:var(--s1);align-items:center}

/* =====================================================================
   3.13.0 — Mockup 63: the key-facts strip on the Learner Record
   ===================================================================== */
.ls-tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(9.5rem,1fr));gap:var(--s2);margin:var(--s3) 0 0}
.ls-t{background:var(--surface-2);border-radius:var(--r-md);padding:var(--s2);min-width:0;overflow-wrap:anywhere}
.ls-t .k{display:block;font-size:var(--t-xs);text-transform:uppercase;letter-spacing:.05em;color:var(--ink-3)}
.ls-t b{display:block;font-size:var(--t-base);color:var(--ink)}
.ls-t .s{display:block;font-size:var(--t-sm);color:var(--ink-2)}
.ls-violin{background:var(--accent-wash)}
.ls-vb{display:flex;flex-wrap:wrap;gap:var(--s1);margin-top:var(--s1);align-items:center}
.ls-change > summary{cursor:pointer}
.ls-dots{letter-spacing:.12em}
.ls-d.present{color:var(--good)}.ls-d.absent{color:var(--prob)}.ls-d.ill{color:var(--attn)}.ls-d.away{color:var(--ink-3)}
.ls-changed{background:var(--good-wash);color:var(--good);padding:var(--s1) var(--s2);border-radius:var(--r-sm);margin:var(--s2) 0 0;display:flex;flex-wrap:wrap;gap:var(--s1);align-items:center}
.ls-flags{margin:var(--s2) 0 0}
.ls-more{margin-top:var(--s2)}
.ls-more > summary{cursor:pointer}
.ti-from{font-size:var(--t-xs);padding:1px 6px;border-radius:var(--r-sm);background:var(--accent-wash);color:var(--accent);margin-left:var(--s1)}
@media (max-width:600px){.rweek-line .wl-sq{display:none}}

/* =====================================================================
   3.13.1 — StringSchool Manchester: the branch switch and the branch pill
   ===================================================================== */
.brsw{display:flex;flex-wrap:wrap;align-items:center;gap:2px var(--s1);justify-content:flex-end;
  margin:0 0 var(--s2);font-size:var(--t-sm);color:var(--ink-3)}
.brsw-k{font-size:var(--t-xs);font-weight:600;letter-spacing:.06em;text-transform:uppercase;margin-right:var(--s1)}
.brsw a{color:var(--ink-2);text-decoration:none;padding:2px var(--s2);border-radius:var(--r-full)}
.brsw a:hover,.brsw a:focus-visible{background:var(--surface-2);color:var(--ink)}
.brsw-on{font-weight:700;color:var(--accent);background:var(--accent-wash);padding:2px var(--s2);border-radius:var(--r-full)}
.brsw-sep{color:var(--line-2)}
.tag.brtag{background:transparent;color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent);margin-left:var(--s1)}
.tag.brtag.both{color:var(--ink-2);box-shadow:inset 0 0 0 1px var(--line-2)}
.tag.brvisit{background:var(--accent-wash);color:var(--accent);border:1px dashed var(--accent)}
.brnote{margin:var(--s2) 0}
.lp-branch{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;margin:var(--s2) 0 var(--s3)}
.lp-branch label{margin:0}
.lp-branch select{width:auto;min-width:9rem}
.sd-kind{border:0;padding:0;margin:0}
.sd-kind legend{padding:0;margin-bottom:var(--s1)}

/* =====================================================================
   3.13.2 — Mockup 71: finding where each class starts. The strip by the
   clock, one line per class, jump by minutes, every line pressable,
   Ends here, ▶ Listen from. No script: every button is a form.
   ===================================================================== */
.drstrip{width:100%;table-layout:fixed;border-collapse:separate;border-spacing:2px 3px;font-size:var(--t-xs);margin:var(--s2) 0 var(--s1)}
.drstrip th{width:7.5em;text-align:left;font-weight:600;color:var(--ink-3);white-space:nowrap;text-transform:none;letter-spacing:0;font-size:var(--t-xs);padding:0 var(--s1) 0 0;vertical-align:middle}
.drstrip td{height:1.6em;padding:0;border-radius:3px;overflow:hidden;vertical-align:middle}
.drstrip td span{display:block;padding:1px 4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#fff}
.drstrip td b{font-weight:700}
.drstrip .c0{background:var(--accent)} .drstrip .c1{background:var(--good)} .drstrip .c2{background:var(--attn)}
.drstrip .x{background:var(--line-2)} .drstrip .x span{color:var(--ink-2)}
.drstrip .tick{background:none;border-left:1px solid var(--line-2);border-radius:0}
.drstrip .tick span{color:var(--ink-3);padding-left:3px}
.drstrip-t td{height:1.2em}
.drq{display:inline-block;background:#fff;color:var(--attn);border-radius:50%;width:1.2em;text-align:center;font-weight:800;line-height:1.2em;margin-left:2px}
.drsl{margin:var(--s1) 0;display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:baseline}
.drsl .drok{color:var(--good);font-weight:800}
.drsl.unsure{color:var(--ink)}
.drlisten{white-space:nowrap}
.drfind{font-weight:600}
.drcut .drsetup{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:center;margin:0 0 var(--s2)}
.drnudge{display:flex;flex-wrap:wrap;gap:var(--s1);align-items:center;margin:var(--s2) 0}
.drnudge .btn{text-decoration:none}
.drnow{display:inline-block;min-width:4.5em;text-align:center;font-weight:800;font-variant-numeric:tabular-nums;padding:2px var(--s2);border:1px solid var(--line-2);border-radius:var(--r-sm);background:var(--surface)}
.drgoto{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4);align-items:center;margin:0 0 var(--s2)}
.drgoto form{display:inline-flex;flex-wrap:wrap;gap:var(--s1);align-items:center;margin:0}
.drgoto label{margin:0;font-size:var(--t-sm)}
.drgoto input{width:auto;min-width:5em}
.drgoto input[type=search]{min-width:10em}
.drview{margin:0}
.drwin,.drhits{font-size:var(--t-sm);background:var(--surface-2);border-radius:var(--r-sm);padding:var(--s2) var(--s3);line-height:1.5;margin:0 0 var(--s2)}
.drhits{background:var(--accent-wash)}
.drhits mark,.drwin mark{background:var(--attn-wash);color:inherit;padding:0 1px;border-radius:2px}
.drline{display:grid;grid-template-columns:5.6em 5.2em 1fr;gap:0 var(--s2);align-items:start;padding:2px 0;border-top:1px solid transparent}
.drline.now{background:var(--surface);border-radius:3px}
.drline.off .drtx{color:var(--ink-3)}
.drsh{font:inherit;font-size:var(--t-xs);font-weight:700;line-height:1.5;padding:0 var(--s1);border:1px solid var(--accent);border-radius:var(--r-sm);background:var(--surface);color:var(--accent);cursor:pointer;white-space:nowrap}
.drsh:hover,.drsh:focus-visible{background:var(--accent);color:#fff;outline:none}
.drsh.off{display:inline-block;border:0;background:none}
.drst{font-variant-numeric:tabular-nums;color:var(--ink-3);font-size:var(--t-xs);line-height:1.9;white-space:nowrap}
.drtx{overflow-wrap:anywhere}
.drmin{margin:var(--s2) 0 2px;font-size:var(--t-xs);font-weight:800;color:var(--ink-2);letter-spacing:.04em;border-bottom:1px solid var(--line);padding-bottom:1px}
.drmin:first-child{margin-top:0}
.drgap{margin:var(--s1) 0;font-size:var(--t-xs);color:var(--ink-3);font-style:italic;text-align:center}
.drwin .mark,.drhits .mark{display:block;border-top:2px dashed var(--accent);margin:var(--s1) 0 2px;padding-top:2px;font-size:var(--t-xs);font-weight:800;color:var(--accent);letter-spacing:.06em;text-transform:uppercase}
.drwin .mark.other,.drhits .mark.other{border-top-style:dotted;color:var(--ink-3)}
.drall{margin:var(--s2) 0}
.drall > summary,.drends > summary,.drnudge-s > summary{cursor:pointer}
.drpiece{margin:var(--s1) 0 var(--s1) var(--s2);border-left:2px solid var(--line);padding-left:var(--s2)}
.drpiece > summary{cursor:pointer;font-size:var(--t-sm)}
.drpiece[open] > summary{font-weight:700}
.drnudge-s{margin:var(--s1) 0}
.drnudge-s form.inline{display:inline-block;margin:var(--s1) var(--s1) 0 0}
.drends{margin:var(--s2) 0 0;border-top:1px solid var(--line);padding-top:var(--s1)}
.drends > summary{font-size:var(--t-sm)}
.drask{display:block;font-size:var(--t-xs);font-weight:700;color:var(--attn);margin:0 0 2px}
.drask-why{display:block;margin-top:2px}
.drask-line{margin:0 0 var(--s2)}
@media (max-width:600px){
  .drline{grid-template-columns:5.2em 1fr}
  .drline .drtx{grid-column:1 / -1}
  .drstrip th{width:4.5em;font-size:.7rem;white-space:normal;line-height:1.1}
  .drstrip td span{padding:1px 2px}
}

/* 3.13.3 — Spare material: from earlier weeks of this course */
.tl-earlier{margin-top:12px;border-top:1px solid var(--line,#e6e0dc);padding-top:8px}
.tl-earlier h3{margin:0 0 2px}
.tl-earl li{display:flex;flex-wrap:wrap;gap:4px 10px;align-items:baseline;justify-content:space-between;padding:5px 0;border-top:1px solid var(--line,#e6e0dc)}
.tl-earl li:first-child{border-top:0}
.tl-earl .te-t{display:flex;flex-direction:column}
.tl-earl .te-do{margin-left:auto}

/* 3.13.3 — Mockup 72: the Scales page, files and pictures.
   E. A small picture on the left of a file in a class's content and Spare
   material (.thumb-s), a larger one on the Scales page's cards (.thumb-l):
   the page's picture, or a coloured tile — ♪ audio, ▶ video, the kind in a
   word for anything else. Never a blank. */
.thumb-s,.thumb-l{display:inline-flex;align-items:center;justify-content:center;flex:none;overflow:hidden;
  border:1px solid var(--line-2);border-radius:var(--r-sm);background:var(--surface-2,var(--surface));vertical-align:top}
.thumb-s{width:38px;height:48px}
.thumb-l{width:84px;height:108px}
.thumb-s img,.thumb-l img{max-width:100%;max-height:100%;width:auto;height:auto;display:block}
.thumb-s .tp{font-size:20px;line-height:1}
.thumb-l .tp{font-size:36px;line-height:1}
.thumb-s .tw{font-size:10px;font-weight:700;letter-spacing:.02em;color:var(--ink-2)}
.thumb-l .tw{font-size:var(--t-sm);font-weight:700;color:var(--ink-2)}
.tile-au{background:var(--good-wash);border-color:var(--good);color:var(--good)}
.tile-vi{background:var(--accent-wash);border-color:var(--accent);color:var(--accent)}
.tile-doc{background:var(--attn-wash);border-color:var(--line-2)}
.ti-body.has-pic{display:flow-root}
.ti-body.has-pic > .thumb-s{float:left;margin:0 var(--s2) var(--s1) 0}
.tl-earl li > .thumb-s{order:-1;margin-right:2px}
.tl-earl li > .thumb-s + .te-t{flex:1 1 12em}

/* A. The list: one row per scale, quiet first. */
.sc-find{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;margin:var(--s3) 0}
.sc-find input[type=search]{flex:1 1 14em;max-width:22em;width:auto}
.sc-find select{width:auto;flex:0 1 auto}
.sc-find .chip{text-decoration:none}
.sc-find .chip.on{border-color:var(--accent);background:var(--accent-wash)}
.sc-table{width:100%;border-collapse:collapse}
.sc-table th{text-align:left;font-size:var(--t-sm);color:var(--ink-2);padding:var(--s1) var(--s2);border-bottom:1px solid var(--line)}
.sc-table td{padding:var(--s2);border-bottom:1px solid var(--line);vertical-align:middle}
.sc-table tr.sc-arp td:first-child{padding-left:calc(var(--s2) + 1.2em)}
.sc-table .sc-name{text-decoration:none}
.sc-table .lvchip{margin:1px 2px 1px 0}
.sc-table .sc-open{text-align:right}
.sc-ic{display:inline-block;min-width:1.6em;text-align:center;font-size:var(--t-xs);font-weight:700;line-height:1.6;
  padding:0 3px;margin-right:2px;border-radius:var(--r-sm);border:1px solid var(--line-2)}
.sc-ic.au{background:var(--good-wash);color:var(--good);border-color:var(--good)}
.sc-ic.vi{background:var(--accent-wash);color:var(--accent);border-color:var(--accent)}
.sc-ic.doc{background:var(--attn-wash);color:var(--attn)}
.sc-n{font-weight:700;margin-left:2px}
.sf-allsc{margin-left:auto;font-weight:600}
p.sf-allsc{margin:var(--s1) 0}
.sf-tosc{margin:var(--s2) 0 0}

/* A, B, D. One scale, opened: its files as cards. */
.sc-oct{font-size:var(--t-lg);font-weight:400}
.sc-cards{list-style:none;margin:0;padding:0;display:grid;gap:var(--s3)}
.sc-card{display:flex;gap:var(--s3);align-items:flex-start;padding:var(--s3);border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface)}
.sc-body{flex:1;min-width:0}
.sc-kind{margin:0 0 2px}
.sc-meta{margin:0 0 var(--s2)}
.sc-do{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s3);align-items:flex-start}
.sc-do details.play[open]{flex-basis:100%}
.sc-watch video{display:block;width:100%;max-width:560px;margin-top:var(--s2);border-radius:var(--r-sm);background:#000}

/* C. Add several: one line per file, checked before anything is saved. */
.sc-check{width:100%;border-collapse:collapse;margin:var(--s2) 0}
.sc-check th{text-align:left;font-size:var(--t-sm);color:var(--ink-2);padding:var(--s1) var(--s2)}
.sc-check td{padding:var(--s1) var(--s2);border-top:1px solid var(--line);overflow-wrap:anywhere}
.sc-check tr.unsure select{border-color:var(--attn);background:var(--attn-wash)}
.sc-check .sc-tempo{width:5.5em}
.sc-choose{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;margin-top:var(--s3)}
.sc-choose label{flex-basis:100%}
.sc-choose .fineprint{flex-basis:100%}

/* F. Settings → Pictures. */
.pics-settings .pics-tool,.pics-settings .pics-count{margin:0 0 var(--s2)}

@media (max-width:600px){
  .sc-table thead,.sc-check thead{display:none}
  .sc-table tr,.sc-check tr{display:block;padding:var(--s2) 0;border-bottom:1px solid var(--line)}
  .sc-table td,.sc-check td{display:block;border:0;padding:2px 0}
  .sc-table tr.sc-arp td:first-child{padding-left:1em}
  .sc-table .sc-open{text-align:left}
  .sc-check td[data-label]::before{content:attr(data-label) " ";color:var(--ink-3);font-size:var(--t-xs)}
  .sc-card{gap:var(--s2)}
  .thumb-l{width:60px;height:78px}
}
/* 3.13.4 — Simon, 14 Oct: "the double line above the 'This Week' line is unnecessary". When nothing
   sits between the page heading and This week (no announcement, no Last week, no summaries card),
   the heading's own rule is enough: no second rule, no extra gap. */
.pagehead + .thisweek{border-top:0;padding-top:0;margin-top:0}
/* 3.13.4 — past announcements open to their words */
.ann-again > summary{cursor:pointer}
.ann-again-body{margin:var(--s2) 0 var(--s3);padding:var(--s2) var(--s3);border-left:3px solid var(--line-2);white-space:normal}
/* 3.13.4 — Mockup 75: paste a learner card. Two ways in on Add someone, the check, then add. */
.lc-tabs{display:flex;flex-wrap:wrap;gap:var(--s1);margin:var(--s2) 0}
.lc-tabs a{padding:var(--s1) var(--s3);border:1px solid var(--line-2);border-radius:var(--r-full);text-decoration:none;color:var(--ink);font-size:var(--t-sm)}
.lc-tabs a:hover{border-color:var(--accent);background:var(--accent-wash)}
.lc-tabs a.on{background:var(--accent);color:var(--accent-ink);border-color:var(--accent);font-weight:600}
.lc-paste textarea{width:100%;font-family:ui-monospace,Menlo,Consolas,monospace;font-size:var(--t-sm)}
.lc-do,.lc-actions{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:flex-start;margin-top:var(--s2)}
.lc-do details[open],.lc-actions details[open]{flex-basis:100%;order:3}
.lc-format > summary,.lc-change > summary{list-style:none;display:inline-flex;width:auto;max-width:100%;cursor:pointer}
.lc-format > summary::-webkit-details-marker,.lc-change > summary::-webkit-details-marker{display:none}
.lc-blank{margin:var(--s2) 0 0;padding:var(--s2) var(--s3);background:var(--surface-2);border-radius:var(--r-sm);user-select:all;white-space:pre-wrap;overflow-wrap:anywhere}
.lc-checkform{margin-top:var(--s4);border-top:1px solid var(--line);padding-top:var(--s3)}
.lc-check{width:100%;border-collapse:collapse;margin:var(--s2) 0}
.lc-check th{text-align:left;font-size:var(--t-sm);color:var(--ink-2);padding:var(--s1) var(--s2)}
.lc-check td{padding:var(--s1) var(--s2);border-top:1px solid var(--line);overflow-wrap:anywhere;vertical-align:top}
.lc-check .lc-lab{color:var(--ink-3)}
.lc-check tr.lc-bad td:first-child{color:var(--prob)}
.lc-check .tag{white-space:normal}
.lc-fields{margin-top:var(--s2)}
.lc-fields textarea{width:100%}
.lc-told{border:1px solid var(--line);border-radius:var(--r-sm);padding:var(--s2) var(--s3);margin:var(--s2) 0}
.lc-differs{margin:var(--s2) 0;padding:var(--s2) var(--s3);border-left:3px solid var(--attn);background:var(--attn-wash)}
@media (max-width:600px){
  .lc-check thead{display:none}
  .lc-check tr{display:block;padding:var(--s2) 0;border-top:1px solid var(--line)}
  .lc-check td{display:block;border:0;padding:2px 0}
  .lc-check td[data-label]::before{content:attr(data-label) ": ";color:var(--ink-3);font-size:var(--t-xs)}
}
/* 3.13.6 — Mockup 74 */
.wu-line{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2);margin:0 0 var(--s4);padding:var(--s2) var(--s4);background:var(--accent-wash);border:1px solid var(--line-2);border-left:4px solid var(--accent);border-radius:var(--r-md);overflow-wrap:anywhere}
.wu-line .btn{margin-left:auto}
.wu-line.none{background:var(--surface-2);border-left-color:var(--line-2)}
.wu-draft{border-left:4px solid var(--attn)}
.wu-meta{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2);margin:0 0 var(--s3)}
.wu-post{padding:var(--s3) var(--s4);margin:0 0 var(--s3);background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-md)}
.wu-post h3{margin:0 0 var(--s2);font-size:var(--t-md)}
.wu-lines{margin:0 0 var(--s2);padding-left:var(--s5)}
.wu-lines li{margin:var(--s1) 0;overflow-wrap:anywhere}
.wu-office-h{margin:var(--s3) 0 var(--s1)}
.wu-history{margin-top:var(--s6)}
.wu-history li{padding:var(--s1) 0;border-bottom:1px solid var(--line);overflow-wrap:anywhere}
.ann-banner p.ann-office{padding-top:var(--s2);border-top:1px dashed var(--line-2)}
.ann-again-body .ann-office{margin-top:var(--s2)}

/* 3.13.6 — Mockup 76: scale progress for the whole class (one scale, the grid, check before saving) */
.skr .skp-link,.skp-link{white-space:nowrap}
.skr .skp-link{margin-left:var(--s2)}
.skp-fold{margin-top:var(--s2)}
.skp-fold p{margin:var(--s1) 0 0}
.skp h1{font-size:1.35rem;margin:var(--s1) 0 var(--s2)}
.skp-short{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center}
.skp-table td{vertical-align:middle}
.skp-table .tag{margin-left:var(--s1)}
.skp-now.sk-fluent{color:var(--good);font-weight:600}
.skp-now.sk-progress{color:var(--attn);font-weight:600}
.skp-now.sk-never{color:var(--ink-3)}
.skp-seg{display:inline-flex;flex-wrap:wrap;border:1px solid var(--line-2);border-radius:8px;overflow:hidden;background:var(--surface)}
.skp-seg input{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;opacity:0}
.skp-seg label{padding:6px 12px;cursor:pointer;font-size:.9rem;color:var(--ink-2);border-left:1px solid var(--line);user-select:none}
.skp-seg label:first-of-type{border-left:0}
.skp-seg label:hover{background:var(--surface-2)}
.skp-seg input:checked+label{background:var(--accent);color:var(--accent-ink);font-weight:600}
.skp-seg input:focus-visible+label{outline:2px solid var(--accent);outline-offset:-2px}
.skp-check{border:1px solid var(--accent);background:var(--accent-wash);border-radius:8px;padding:var(--s3);margin:var(--s3) 0}
.skp-check p{margin:0 0 var(--s2)}
.skp-btns{display:flex;flex-wrap:wrap;gap:var(--s2)}
.skp-grid-wrap{margin-top:var(--s4);border-top:1px solid var(--line);padding-top:var(--s3)}
.skp-grid-wrap>summary{cursor:pointer}
.skp-gridscroll{overflow-x:auto;max-width:100%}
.skp-grid{border-collapse:collapse;font-size:.85rem}
.skp-grid th,.skp-grid td{border:1px solid var(--line);padding:3px 4px;text-align:center;white-space:nowrap}
.skp-grid thead th{font-weight:600;vertical-align:bottom;text-transform:none;letter-spacing:0}
.skp-grid tbody th{text-align:left;font-weight:600;position:sticky;left:0;background:var(--surface)}
.skp-grid select{font-size:.85rem;padding:1px 2px;min-width:2.6em}
.skp-grid td.sk-fluent{background:var(--good-wash)}
.skp-grid td.sk-progress{background:var(--attn-wash)}
.skp-grid td.sk-never{background:var(--surface-2)}
.card.scales .sk-whole{font-style:italic}
@media (max-width:640px){.skp-seg label{padding:6px 8px;font-size:.85rem}.skp-grid tbody th .tag{display:none}}

/* 3.13.6 — fixes */
/* The Submit report row: room round the buttons, and text beside them never too close. */
.row.sb-row{gap:12px;row-gap:12px;align-items:center;margin-top:var(--s4);padding-top:var(--s2)}
.sb-unmarked + .row.sb-row{margin-top:var(--s4)}
@media (max-width:640px){.row.sb-row{flex-direction:column;align-items:flex-start}.row.sb-row > *{margin:0}}
/* The learner's course, one click away (Learner Record key facts). */
.ls-t.ls-course a.ls-courselink{color:inherit;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px}
.ls-t.ls-course a.ls-courselink:hover,.ls-t.ls-course a.ls-courselink:focus-visible{color:var(--accent,inherit)}

/* 3.13.9 — Mockup 73 K: the concert countdown beside the penguin */
.penguin-strip .pg-count{margin-right:var(--s2);align-self:flex-end;padding-bottom:2px}


/* 3.14.0 — Mockup 73 recording (B C D L) */
/* The red line on every page while a recording of yours runs. */
.recline{position:sticky;top:0;z-index:40;display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px;
  padding:7px var(--s5);background:var(--prob);color:var(--surface);font-size:var(--t-sm,.9rem)}
.recline b{font-weight:800}
.recline-go{margin-left:auto;display:inline-flex;flex-wrap:wrap;align-items:center;gap:4px 10px}
.recline a.recgo{color:inherit;font-weight:700;text-decoration:underline;text-underline-offset:3px}
.recline .recgo-hint,.recline .recgo-else{font-weight:600}
.recline .recdot{background:var(--surface)}
.recdot{display:inline-block;width:10px;height:10px;border-radius:var(--r-full);background:var(--prob);vertical-align:middle;animation:recblink 1.2s infinite}
.recdot.still{animation:none;opacity:.6}
.recred{color:var(--prob)}
.recgo-hint{font-size:var(--t-xs,.85rem)}
.recgo-hint[hidden]{display:none}
/* Before you start: Record today's classes. */
.recday-wrap{margin-top:var(--s3)}
.recday{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:var(--s3);
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);padding:var(--s3) var(--s4)}
.recday p{margin:2px 0 0}
.recday.on{background:var(--prob-wash);border-color:var(--prob)}
.recday-go{display:inline-flex;flex-direction:column;align-items:flex-end;gap:4px}
a.recbtn{display:inline-flex;align-items:center;gap:6px;background:var(--prob);color:var(--surface);border-radius:var(--r-full);
  padding:10px 22px;font-weight:800;text-decoration:none;white-space:nowrap}
a.recbtn.sm{padding:6px 14px;font-size:var(--t-sm,.9rem)}
a.recgobtn,a.recstopbtn{display:inline-block;border-radius:var(--r-full);font-weight:800;text-decoration:none;white-space:nowrap}
a.recgobtn{background:var(--surface);color:var(--prob);border:2px solid var(--prob);padding:8px 18px}
a.recstopbtn{background:var(--prob);color:var(--surface);padding:9px 20px}
/* Done for the day: Today's recording. */
.recdone{margin:var(--s3) 0 var(--s4)}
.recdone h3{margin:0 0 var(--s2)}
.recstop{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:var(--s3);
  background:var(--prob-wash);border:1px solid var(--prob);border-radius:var(--r-md);padding:var(--s3) var(--s4);margin:var(--s2) 0}
.recstop-go{display:inline-flex;flex-direction:column;align-items:flex-end;gap:4px}
.recrow{background:var(--surface-2);border-radius:var(--r-sm);padding:var(--s2) var(--s3);margin-top:6px}
.recrow.recwarn{background:var(--attn-wash)}
@media (max-width:640px){
  .recline{padding:7px var(--s4)}
  .recline-go{margin-left:0}
  .recday,.recstop{flex-direction:column;align-items:flex-start}
  .recday-go,.recstop-go{align-items:flex-start}
}

/* 3.14.0 — Mockup 73 layout */
/* A. INFO on one line: Teaching names · Change ▸ … ♩ Metronome 𝄞 Tuner.
   The fold holds everything "Who is teaching this" held; open, it takes
   its own full-width row under the line. */
.occpanel > .grouph > span.infoteach{order:1;font-size:var(--t-base);font-weight:400;letter-spacing:0;text-transform:none;color:var(--ink);min-width:0}
.infoteach .k0,.nothappening .k0{font-size:var(--t-xs);font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3);margin-right:6px}
.occpanel > .grouph > details.teachdetail{order:2}
.occpanel > .grouph > .toolbtns{order:3;margin-left:auto}
.occpanel > .grouph > details.teachdetail.card:not([open]){border:0;padding:0;margin:0;background:none;box-shadow:none}
.occpanel > .grouph > details.teachdetail[open]{order:9;flex:1 1 100%;min-width:0;margin:0 0 var(--s2);padding:var(--s2) var(--s4) var(--s3);
  border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface);box-shadow:none}
details.teachdetail > summary{display:inline-flex;font-size:var(--t-sm);font-weight:600;color:var(--accent);cursor:pointer;text-decoration:none}
details.teachdetail > summary::before,details.teachdetail[open] > summary::before{content:none !important;display:none !important}
details.teachdetail > summary::after{content:" ▸";white-space:pre}
details.teachdetail[open] > summary::after{content:" ▾"}
details.teachdetail .nothappening{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--s1) var(--s3);margin-top:var(--s3);padding-top:var(--s3);border-top:1px solid var(--line)}
details.teachdetail .nothappening .cancelone,details.teachdetail .nothappening .didnt{margin:0;padding:0;border:0}
details.teachdetail .nothappening .retime-confirm{flex-basis:100%}
.occpanel > .grouph > details.teachdetail table.teachnow{width:100%;border-collapse:collapse}
@media (max-width:640px){
  .occpanel > .grouph > .toolbtns{margin-left:0}
  .occpanel > .grouph > span.infoteach{flex:1 1 100%}
}

/* E. PEOPLE / CONTENT / REPORT: bigger headings, their state on the right. */
.occpanel > .grouph.gh-big{padding-top:var(--s5)}
.occpanel > .grouph.gh-big > span:first-child{font-size:var(--t-md);font-weight:800;letter-spacing:.08em;color:var(--ink);
  flex:1 1 auto;border-bottom:2px solid var(--ink);padding-bottom:2px}
.occpanel > .grouph.gh-big{flex-wrap:nowrap;align-items:flex-end}
.occpanel > .grouph.gh-big > .ghstate{flex:none;margin-left:auto;font-size:var(--t-xs);font-weight:700;white-space:nowrap}

/* F. The report as one card, with room around Submit report. */
.occpanel > .rcard{margin:var(--s2) var(--s5) var(--s4);border:1px solid var(--line-2);border-radius:var(--r-md);background:var(--surface);overflow:hidden}
.occpanel > .rcard > .card{border:0;border-radius:0;margin:0;box-shadow:none}
.occpanel > .rcard > .card + .card{border-top:1px solid var(--line)}
.rcard .rfin{margin-top:var(--s4)}
.rcard .row.sb-row{margin-top:var(--s5);padding:var(--s4) 0 var(--s2);border-top:1px solid var(--line)}
@media (max-width:640px){.occpanel > .rcard{margin:var(--s2) var(--s3) var(--s4)}}

/* I. Before you start as one checklist: toilets, printing, violins. */
ul.bys{margin:0;padding:0;list-style:none}
ul.bys > li{padding:var(--s3) 0 var(--s3) 28px;border-top:1px solid var(--line);position:relative}
ul.bys > li:first-child{border-top:0;padding-top:0}
ul.bys > li::before{content:"☐";position:absolute;left:0;top:var(--s3);color:var(--ink-3);font-size:var(--t-md);line-height:1.4}
ul.bys > li:first-child::before{top:0}
ul.bys > li > p:first-child,ul.bys > li > fieldset{margin-top:0}
ul.bys > li > :last-child{margin-bottom:0}

/* N. "Minor issues – I sorted it": What did you sort? shows when chosen. */
.day-toilets .toilsort{display:none;margin:var(--s2) 0 0}
.day-toilets:has(input[value="sorted"]:checked) .toilsort{display:block}
.day-toilets .toilsort input{width:100%;max-width:32rem;margin-top:var(--s1)}

/* P. One 🖨 Print and one ▶ Play: the same button everywhere on the Day page
   (documents, pieces, spare material, scales). */
.mbtns{display:contents}
.mbtn,details.play.ti-play > summary.mbtn,details.play.ti-prints > summary.mbtn,
.sf-chips > details.play.sf-play > summary,.sf-chips > details.play.sf-prints > summary,.sf-chips > a.ico,.sf-pr a.ico{
  display:inline-flex;align-items:center;gap:4px;box-sizing:border-box;min-height:36px;margin:0;padding:6px 12px;
  font-size:var(--t-sm);font-weight:600;line-height:1.3;border:1px solid var(--line-2);border-radius:var(--r-full);
  background:var(--surface);color:var(--ink);text-decoration:none;white-space:nowrap;cursor:pointer}
.mbtn:hover,.sf-chips > details.play > summary:hover,.sf-chips > a.ico:hover{border-color:var(--accent);color:var(--accent)}
details.play > summary.mbtn::before,details.play[open] > summary.mbtn::before,
.sf-chips > details.play > summary::before,.sf-chips > details.play[open] > summary::before{content:none !important;display:none !important}
.tlist .ti-do details.play[open],.tl-earl .te-do details.play[open]{flex:1 1 100%}
/* An opened player or list takes the row under the item, so the title keeps its room. */
.tlist li.ti:has(> .ti-do details.play[open]) > .ti-do{grid-column:3 / -1;grid-row:2}
.tlist ol.spare li.ti:has(> .ti-do details.play[open]) > .ti-do{grid-column:2 / -1}
.tlist .ti-do details.play[open] > summary{width:max-content;max-width:100%;margin-bottom:var(--s1)}
.tlist .ti-do .sf-pl > span,.tl-earl .sf-pl > span{flex:0 1 auto;font-weight:600}
@media (max-width:640px){
  .tlist .ti-do{gap:var(--s2)}
  .tlist li.ti:has(> .ti-do details.play[open]) > .ti-do,.tlist ol.spare li.ti:has(> .ti-do details.play[open]) > .ti-do{grid-column:1 / -1;grid-row:auto}
}

/* 3.14.0 — Before you start: no tick-box drawn where nothing can be ticked (the toilets have their own answers). */
ul.bys > li{padding-left:0}
ul.bys > li::before{content:none}
