/* Brooklyn City College digital campus: forms, buttons and triggers.
   Loads after portal.css, classroom.css and results-exams.css, before motion.css.

   Specification, ported by hand to plain CSS (no code copied):
   - shadcn/ui Field, Input, Textarea, Native Select, Checkbox, Radio Group, Switch, Input Group
     and Button (ui.shadcn.com, MIT, (c) 2023 shadcn): the field anatomy, aria-invalid as the
     one invalid hook, the ring that hugs the control, choice cards, addons inside the frame.
   - Astryx by Meta (github.com/meta/astryx, MIT, (c) 2026 Meta Platforms, beta): mark only the
     exception (optional), error / warning / success status under the control, paired fields,
     labels beside controls for settings, a wrapping filter bar, a 16px input floor on touch.
   - GOV.UK Design System: visible labels, hints instead of placeholders, widths that match the
     answer, an error summary that repeats the inline message. IBM Carbon: three control
     heights, read-only distinct from disabled.
   Brand wins over library defaults: this sheet uses the portal's tokens, Work Sans, nothing
   under 13px, and red only for errors and destructive actions.

   The signature: the cell. Every button or trigger that carries a glyph holds it in an inset
   cell at its trailing edge, concentric with the control (a disc in a pill, a rounded square
   in a field). The cell is the logo's framed box put to work. It inverts when the control is
   armed: hovered, open or pressed.

   Weight: text controls are addressed with two :not() so each rule matches the rule it
   replaces in portal.css (0,2,1). State styling only; transitions belong to motion.css. */

:root{
  /* sizes */
  --f-h-sm:36px; --f-h:var(--control,44px); --f-h-lg:48px;
  --f-r:var(--r-control,14px);          /* fields */
  --btn-r:var(--r-pill,999px);          /* buttons. Set to var(--f-r) for square keys; the cell follows */
  --f-pad:14px;
  --f-size:15px;                        /* control text. 16px on touch */
  /* colour */
  --f-frame:#747F96;                    /* 4.0:1 on white, 3.5:1 on the canvas, 3.6:1 on a soft cell. --edge is 2.7:1 on the canvas */
  --f-quiet:var(--soft,#F2F3F7);        /* read-only, disabled, a cell at rest */
  --f-armed:var(--tint,#E3E9F7);        /* a cell under the pointer */
  --f-placeholder:#66708A;              /* 4.9:1 on white */
  --f-halo:rgba(16,30,64,.16);
  --f-halo-bad:rgba(217,0,43,.18);
  --f-bad:var(--red,#D9002B);
  --f-bad-ink:#8A001B;                  /* 9.6:1 on the wash */
  --f-bad-wash:#FFECEF;
  --f-warn-ink:var(--amber-ink,#7A4A00); --f-warn-wash:var(--amber-wash,#FFF4DF);
  --f-ok-ink:var(--ok-ink,#1F5A3D);      --f-ok-wash:var(--ok-wash,#E9F3EC);
  /* rhythm */
  --f-gap-label:6px; --f-gap-field:16px; --f-gap-group:28px;

  /* glyphs, 16px grid, 1.5px round stroke. Used as masks, so they take the colour of their cell. */
  --g-arrow:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.75 8h10.5M9 3.75 13.25 8 9 12.25'/%3E%3C/svg%3E");
  --g-check:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 8.5l3.25 3.25L13 4.75'/%3E%3C/svg%3E");
  --g-down:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 2.75v7.5M4.75 7.25 8 10.5l3.25-3.25M3 13.25h10'/%3E%3C/svg%3E");
  --g-external:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.25 3.75h6v6M12.25 3.75l-8 8'/%3E%3C/svg%3E");
  --g-plus:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 3v10M3 8h10'/%3E%3C/svg%3E");
  --g-chevron:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.75 6 8 10.25 12.25 6'/%3E%3C/svg%3E");
  --g-chevron-up:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.75 10 8 5.75 12.25 10'/%3E%3C/svg%3E");
  --g-busy:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round'%3E%3Cpath d='M8 2.25a5.75 5.75 0 1 0 5.75 5.75'/%3E%3C/svg%3E");
  --g-info:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 14.25A6.25 6.25 0 1 0 8 1.75a6.25 6.25 0 0 0 0 12.5zM8 7.5v3.25M8 5.2v.05'/%3E%3C/svg%3E");
  --g-alert:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 14.25A6.25 6.25 0 1 0 8 1.75a6.25 6.25 0 0 0 0 12.5zM8 4.75V8.5M8 10.8v.05'/%3E%3C/svg%3E");
  --g-warn:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 2.5 14.25 13.25H1.75zM8 6.5v3M8 11.2v.05'/%3E%3C/svg%3E");
  --g-ok:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 14.25A6.25 6.25 0 1 0 8 1.75a6.25 6.25 0 0 0 0 12.5zM5.25 8.25l2 2L10.75 6'/%3E%3C/svg%3E");

  /* painted glyphs for places a mask cannot reach (the background of an input or a select).
     Their colours are written in, so update them here if --navy, --soft or --tint change. */
  --p-cell-rest:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 36 36'%3E%3Crect width='36' height='36' rx='10' fill='%23F2F3F7'/%3E%3Cpath d='M13 16l5 5 5-5' fill='none' stroke='%23101E40' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --p-cell-hover:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 36 36'%3E%3Crect width='36' height='36' rx='10' fill='%23E3E9F7'/%3E%3Cpath d='M13 16l5 5 5-5' fill='none' stroke='%23101E40' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --p-cell-open:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 36 36'%3E%3Crect width='36' height='36' rx='10' fill='%23101E40'/%3E%3Cpath d='M13 16l5 5 5-5' fill='none' stroke='%23fff' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --p-cell-off:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 36 36'%3E%3Cpath d='M13 16l5 5 5-5' fill='none' stroke='%238792A7' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --p-calendar:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 36 36'%3E%3Crect width='36' height='36' rx='10' fill='%23F2F3F7'/%3E%3Cpath d='M11.5 14.5a1.5 1.5 0 0 1 1.5-1.5h10a1.5 1.5 0 0 1 1.5 1.5V23a1.5 1.5 0 0 1-1.5 1.5H13a1.5 1.5 0 0 1-1.5-1.5zM11.5 17h13M15 11.5V14M21 11.5V14' fill='none' stroke='%23101E40' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --p-lock:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%234A5670' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 7.25h8a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1zM5.25 7.25v-2a2.75 2.75 0 0 1 5.5 0v2'/%3E%3C/svg%3E");
  --p-search:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%234A5670' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 12A5 5 0 1 0 7 2a5 5 0 0 0 0 10zM10.75 10.75l3 3'/%3E%3C/svg%3E");
  --p-clear:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%234A5670' stroke-width='1.5' stroke-linecap='round'%3E%3Cpath d='M4.5 4.5l7 7M11.5 4.5l-7 7'/%3E%3C/svg%3E");
  --p-tick:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.75 8.5l2.75 2.75 5.75-6'/%3E%3C/svg%3E");
  --p-dash:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M4.25 8h7.5'/%3E%3C/svg%3E");
}
/* Touch and small screens: taller targets and a 16px floor so iOS does not zoom the page. */
@media(max-width:700px),(pointer:coarse){:root{--f-h-sm:44px;--f-h:48px;--f-h-lg:52px;--f-size:16px}}


/* ================= 1. field anatomy ================= */
/* Order: label, control, error, help. One field is one grid; fields sit 16px apart. */
.field{display:grid;gap:var(--f-gap-label);align-content:start;min-width:0}
.field label,.field-label,.cl-label,.re-filter label,.filter-group label{display:block;font-size:14px;font-weight:500;line-height:20px;color:var(--navy);letter-spacing:0}
.field small,.field-help{display:block;margin:0;font-size:13px;font-weight:400;line-height:18px;color:var(--slate)}
/* Mark the exception. Forms here are required by default, so only optional fields carry a mark.
   Until the templates print <span class="field-opt">, the mark is drawn for any optional input. */
.field-opt{font-weight:400;color:var(--slate)}
.field:not(:is(.filters,.course-search) *):has(>:is(input:not([type=search]),textarea):not([required]):not([readonly]):not(:disabled))>label:not(:has(.field-opt))::after{content:" (optional)";font-weight:400;color:var(--slate)}
/* Status under the control. */
.field-error,.field-warning,.field-ok{display:flex;align-items:flex-start;gap:6px;margin:0;font-size:13px;font-weight:500;line-height:18px}
.field-error{color:var(--f-bad-ink)}
.field-warning{color:var(--f-warn-ink)}
.field-ok{color:var(--f-ok-ink)}
.field-error::before,.field-warning::before,.field-ok::before{content:"";flex:none;width:16px;height:16px;margin-top:1px;background:currentColor;-webkit-mask:var(--g-alert) center/16px 16px no-repeat;mask:var(--g-alert) center/16px 16px no-repeat}
.field-error::before{background:var(--f-bad)}
.field-warning::before{-webkit-mask-image:var(--g-warn);mask-image:var(--g-warn)}
.field-ok::before{-webkit-mask-image:var(--g-ok);mask-image:var(--g-ok)}
/* Help and a character count share one line. */
.field-foot{display:flex;justify-content:space-between;align-items:flex-start;gap:12px}
.field-count{margin-left:auto;font-size:13px;line-height:18px;color:var(--slate);font-variant-numeric:tabular-nums;white-space:nowrap}
.field-count[data-near]{font-weight:500;color:var(--f-warn-ink)}
.field-count[data-full]{font-weight:600;color:var(--f-bad-ink)}
/* Labels beside controls, for settings. Collapses to stacked below 560px. */
.field.inline{grid-template-columns:minmax(140px,220px) minmax(0,1fr);column-gap:24px}
.field.inline>:first-child{padding-top:calc((var(--f-h) - 20px)/2)}
.field.inline>:not(:first-child){grid-column:2}
.field.inline>.choice{min-height:var(--f-h);align-items:center}
@media(max-width:560px){.field.inline{grid-template-columns:1fr}.field.inline>:first-child{padding-top:0}.field.inline>:not(:first-child){grid-column:1}.field.inline>.choice{min-height:24px}}


/* ================= 2. text controls ================= */
:is(input,select,textarea):not([type=radio]):not([type=checkbox]){
  --_cell:calc(var(--f-h) - 8px);
  --_wash:inset 0 0 0 0 transparent; --_edge:0 0 0 0 transparent; --_halo:0 0 0 0 transparent;
  box-sizing:border-box;width:100%;min-width:0;height:var(--f-h);min-height:0;margin:0;padding:0 var(--f-pad);
  border:1px solid var(--f-frame);border-radius:var(--f-r);
  background-color:var(--paper);color:var(--navy);
  font-family:var(--text);font-size:var(--f-size);font-weight:400;line-height:20px;letter-spacing:0;
  box-shadow:var(--_wash),var(--_edge),var(--_halo);
  -webkit-appearance:none;appearance:none;
}
:is(input,textarea):not([type=radio]):not([type=checkbox])::placeholder{color:var(--f-placeholder);opacity:1}
@media(hover:hover){
  :is(input,select,textarea):not([type=radio]):not([type=checkbox]):hover{border-color:var(--navy)}
}
/* Focus: the frame doubles to 2px navy (16:1 on white) and a soft halo sits outside it.
   The transparent outline becomes the indicator in forced-colours mode. */
:is(input,select,textarea):not([type=radio]):not([type=checkbox]):focus{
  border-color:var(--navy);--_edge:0 0 0 1px var(--navy);--_halo:0 0 0 4px var(--f-halo);
  outline:2px solid transparent;outline-offset:1px;
}
/* Invalid: the same 2px frame, in red, with no change in size. */
:is(input,select,textarea):not([type=radio]):not([type=checkbox])[aria-invalid=true]{
  border:1px solid var(--f-bad)!important;--_edge:0 0 0 1px var(--f-bad);
}
:is(input,select,textarea):not([type=radio]):not([type=checkbox])[aria-invalid=true]:focus{--_halo:0 0 0 4px var(--f-halo-bad)}
/* Read-only: filled, unframed, locked. It still takes focus and can be copied. */
:is(input,textarea):not([type=radio]):not([type=checkbox])[readonly]{
  border-color:transparent;background-color:var(--f-quiet);cursor:default;
  padding-right:40px;background-image:var(--p-lock);background-repeat:no-repeat;background-position:right 14px center;background-size:16px 16px;
}
:is(input,textarea):not([type=radio]):not([type=checkbox])[readonly]:focus{border-color:var(--navy)}
/* Disabled: filled, greyed, not focusable. */
:is(input,select,textarea):not([type=radio]):not([type=checkbox]):disabled{
  border-color:transparent;background-color:var(--f-quiet);color:var(--f-frame);-webkit-text-fill-color:var(--f-frame);opacity:1;cursor:not-allowed;
}
/* Browser autofill keeps the portal's own fill and ink. */
:is(input,select,textarea):not([type=radio]):not([type=checkbox]):-webkit-autofill{--_wash:inset 0 0 0 100px var(--paper);-webkit-text-fill-color:var(--navy);caret-color:var(--navy)}

/* textarea */
textarea:not([type=radio]):not([type=checkbox]){height:auto;min-height:112px;max-height:min(70vh,640px);padding:11px var(--f-pad);line-height:22px;resize:vertical;field-sizing:content}

/* widths that match the answer */
input[autocomplete="postal-code"]:not([type=radio]):not([type=checkbox]){max-width:11em}
input[type=number]:not([type=radio]):not([type=checkbox]),.cl-check input[type=number]{max-width:14em}
.w-4{max-width:6.5em}.w-10{max-width:11em}.w-20{max-width:20em}.w-30{max-width:30em}
input:is([type=number],[type=tel],[type=date]):not([type=radio]):not([type=checkbox]){font-variant-numeric:tabular-nums}

/* number: no spinners */
input[type=number]:not([type=radio]):not([type=checkbox]){-moz-appearance:textfield}
input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}

/* search: a leading glyph and the portal's own clear mark */
input[type=search]:not([type=radio]):not([type=checkbox]){padding-left:40px;background-image:var(--p-search);background-repeat:no-repeat;background-position:left 14px center;background-size:16px 16px}
input[type=search]::-webkit-search-decoration{-webkit-appearance:none}
input[type=search]::-webkit-search-cancel-button{-webkit-appearance:none;width:24px;height:24px;margin:0 -6px 0 6px;border-radius:50%;background:var(--p-clear) center/14px 14px no-repeat var(--f-quiet);cursor:pointer}


/* ================= 3. triggers in a field: the cell ================= */
/* select: the chevron sits in a cell, inset 4px, concentric with the field. */
select:not([type=radio]):not([type=checkbox]){
  padding-right:calc(var(--_cell) + 14px);
  background-image:var(--p-cell-rest);background-repeat:no-repeat;background-position:right 3px center;background-size:var(--_cell) var(--_cell);
  cursor:pointer;text-overflow:ellipsis;
}
@media(hover:hover){select:not([type=radio]):not([type=checkbox]):hover{background-image:var(--p-cell-hover)}}
select:not([type=radio]):not([type=checkbox]):is(:open,:active){background-image:var(--p-cell-open)}
select:not([type=radio]):not([type=checkbox]):disabled{background-image:var(--p-cell-off)}

/* date: the picker button becomes the same cell (Chromium and Safari; Firefox keeps its own) */
input[type=date]:not([type=radio]):not([type=checkbox]){padding-right:3px}
input[type=date]::-webkit-calendar-picker-indicator{box-sizing:border-box;width:var(--_cell);height:var(--_cell);margin:0 0 0 8px;padding:0;border-radius:calc(var(--f-r) - 4px);background:var(--p-calendar) center/100% 100% no-repeat;opacity:1;cursor:pointer}
input[type=date]::-webkit-date-and-time-value{text-align:left}
input[type=date][readonly]::-webkit-calendar-picker-indicator{display:none}
input[type=date][readonly]:not([type=radio]):not([type=checkbox]){padding-right:40px}

/* password: Show and Hide live in the cell. Pressed means the password is showing. */
.password{position:relative;display:block}
.password input:not([type=radio]):not([type=checkbox]){padding-right:calc(var(--f-pad) + 68px)}
.password button{
  position:absolute;top:4px;right:4px;bottom:4px;min-width:60px;padding:0 12px;border:0;
  border-radius:calc(var(--f-r) - 4px);background:var(--f-quiet);color:var(--navy);
  font-size:13px;font-weight:600;line-height:1;letter-spacing:0;
}
@media(hover:hover){.password button:hover{background:var(--f-armed)}}
.password button[aria-pressed=true]{background:var(--navy);color:#fff}
.password button:focus-visible{outline:2px solid var(--navy);outline-offset:1px}

/* input group: text or a button inside the frame, for units, prefixes and field actions.
   <div class="input-group"><input ...><span class="cell">kg</span></div> */
.input-group{--_cell:calc(var(--f-h) - 8px);display:flex;align-items:center;gap:4px;height:var(--f-h);padding:0 3px;border:1px solid var(--f-frame);border-radius:var(--f-r);background:var(--paper)}
.input-group>:is(input,select):not([type=radio]):not([type=checkbox]){flex:1 1 0;height:100%;padding:0 10px;border:0!important;border-radius:0;background-color:transparent;box-shadow:none;outline:0}
.input-group>.cell{display:inline-flex;align-items:center;justify-content:center;flex:none;min-width:var(--_cell);height:var(--_cell);padding:0 10px;border:0;border-radius:calc(var(--f-r) - 4px);background:var(--f-quiet);color:var(--slate);font-size:13px;font-weight:600;line-height:1;white-space:nowrap}
.input-group>button.cell{color:var(--navy);cursor:pointer}
@media(hover:hover){.input-group:hover{border-color:var(--navy)}.input-group>button.cell:hover{background:var(--f-armed)}}
.input-group>button.cell[aria-pressed=true],.input-group>button.cell[aria-expanded=true]{background:var(--navy);color:#fff}
.input-group:has(>:is(input,select):focus){border-color:var(--navy);box-shadow:0 0 0 1px var(--navy),0 0 0 4px var(--f-halo)}
.input-group:has(>[aria-invalid=true]){border-color:var(--f-bad);box-shadow:0 0 0 1px var(--f-bad)}
.input-group:has(>[aria-invalid=true]:focus){box-shadow:0 0 0 1px var(--f-bad),0 0 0 4px var(--f-halo-bad)}
.input-group:has(>:disabled){border-color:transparent;background:var(--f-quiet)}


/* ================= 4. choices ================= */
input:is([type=radio],[type=checkbox]){
  -webkit-appearance:none;appearance:none;box-sizing:border-box;flex:none;width:20px;height:20px;margin:0;
  border:1px solid var(--f-frame);background:var(--paper) center/100% 100% no-repeat;cursor:pointer;vertical-align:-4px;accent-color:var(--navy);
}
input[type=radio]{border-radius:50%}
input[type=checkbox]{border-radius:6px}
@media(hover:hover){input:is([type=radio],[type=checkbox]):hover{border-color:var(--navy)}}
input[type=radio]:checked{border-color:var(--navy);background-image:radial-gradient(circle,var(--navy) 0 4.5px,transparent 5px)}
input[type=checkbox]:checked{border-color:var(--navy);background-color:var(--navy);background-image:var(--p-tick)}
input[type=checkbox]:indeterminate{border-color:var(--navy);background-color:var(--navy);background-image:var(--p-dash)}
input:is([type=radio],[type=checkbox]):focus-visible{outline:2px solid var(--navy);outline-offset:2px}
input:is([type=radio],[type=checkbox])[aria-invalid=true]{border:1px solid var(--f-bad)!important}
input:is([type=radio],[type=checkbox]):disabled{border-color:transparent;background-color:var(--soft-2,#E6E9F0);cursor:not-allowed}
input[type=radio]:checked:disabled{background-image:radial-gradient(circle,var(--f-frame) 0 4.5px,transparent 5px)}
input[type=checkbox]:is(:checked,:indeterminate):disabled{background-color:var(--f-frame)}

/* a choice with its label: <label class="choice"><input type="checkbox"><span>Text<small>Help</small></span></label> */
.choice,.field label.choice{display:flex;align-items:flex-start;gap:10px;min-height:24px;font-size:15px;font-weight:400;line-height:22px;cursor:pointer}
.choice>input{margin-top:1px}
.choice small{display:block;font-size:13px;line-height:18px;color:var(--slate)}
.choice:has(>input:disabled){color:var(--f-frame);cursor:not-allowed}
.choices{display:grid;gap:10px;min-width:0;margin:0;padding:0;border:0}

/* switch: a key with the box as its thumb. <input type="checkbox" role="switch"> inside .choice */
input[type=checkbox][role=switch]{width:42px;height:26px;border-radius:9px;border-color:var(--f-frame);background:linear-gradient(var(--f-frame),var(--f-frame)) 3px center/18px 18px no-repeat var(--paper)}
input[type=checkbox][role=switch]:checked{border-color:var(--navy);background:linear-gradient(#fff,#fff) calc(100% - 3px) center/18px 18px no-repeat var(--navy)}
input[type=checkbox][role=switch]:disabled{border-color:transparent;background-color:var(--soft-2,#E6E9F0)}
.choice>input[role=switch]{margin-top:-2px}

/* choice card: the mark lives in a leading cell that inverts when chosen.
   Today's markup is label.cl-option > input + text; .choice-card is the same thing by name. */
.cl-option,.choice-card{
  --_cell:calc(var(--f-h) - 8px);
  position:relative;display:flex;align-items:stretch;gap:0;min-height:var(--f-h);padding:calc((var(--f-h) - 24px)/2) var(--f-pad) calc((var(--f-h) - 24px)/2) 0;
  border:1px solid var(--f-frame);border-radius:var(--f-r);background:var(--paper);box-shadow:none;
  font-size:15px;line-height:22px;color:var(--navy);cursor:pointer;
}
:is(.cl-option,.choice-card)>input{
  align-self:center;width:var(--_cell);height:var(--_cell);margin:calc((var(--f-h) - 24px)/-2 + 3px) 12px calc((var(--f-h) - 24px)/-2 + 3px) 3px;
  border:0;border-radius:calc(var(--f-r) - 4px);background-color:var(--f-quiet);
}
:is(.cl-option,.choice-card)>input[type=radio]{background-image:radial-gradient(circle,transparent 0 7px,var(--f-frame) 7.5px 8.5px,transparent 9px)}
:is(.cl-option,.choice-card)>input[type=checkbox]{background-image:linear-gradient(var(--f-quiet),var(--f-quiet)),linear-gradient(var(--f-frame),var(--f-frame));background-size:14px 14px,16px 16px;background-position:center;background-repeat:no-repeat}
@media(hover:hover){
  :is(.cl-option,.choice-card):hover{border-color:var(--navy)}
  :is(.cl-option,.choice-card):hover>input:not(:checked){background-color:var(--f-armed)}
  :is(.cl-option,.choice-card):hover>input[type=checkbox]:not(:checked){background-image:linear-gradient(var(--f-armed),var(--f-armed)),linear-gradient(var(--navy),var(--navy))}
}
:is(.cl-option,.choice-card):has(>input:checked){border-color:var(--navy);box-shadow:0 0 0 1px var(--navy)}
:is(.cl-option,.choice-card)>input:checked{background-color:var(--navy)}
:is(.cl-option,.choice-card)>input[type=radio]:checked{background-image:radial-gradient(circle,#fff 0 3.5px,transparent 4px 7px,#fff 7.5px 8.5px,transparent 9px)}
:is(.cl-option,.choice-card)>input[type=checkbox]:checked{background-image:var(--p-tick);background-size:16px 16px}
:is(.cl-option,.choice-card):has(>input[aria-invalid=true]){border-color:var(--f-bad)}
:is(.cl-option,.choice-card):has(>input:disabled){border-color:transparent;background:var(--f-quiet);color:var(--f-frame);cursor:not-allowed}
@supports selector(:has(a)){
  :is(.cl-option,.choice-card)>input:focus-visible{outline:0}
  :is(.cl-option,.choice-card):has(>input:focus-visible){border-color:var(--navy);box-shadow:0 0 0 1px var(--navy),0 0 0 4px var(--f-halo)}
}
.cl-check fieldset{display:grid;gap:8px;min-width:0;padding:0;border:0}


/* ================= 5. buttons ================= */
/* portal.css decides what fill a button takes on each surface (paper on the canvas, soft in a
   card, navy for the primary action). This sheet owns everything else: shape, size, type,
   pressed, focus, disabled, busy, and the cell. */
.btn{
  --_r:var(--btn-r);--_cell:calc(var(--f-h) - 8px);
  --_cell-bg:rgba(16,30,64,.08);--_cell-ink:var(--navy);--_g:var(--g-arrow);
  --_c:none;--_pr:20px;--_pb:6px;--_jc:center;--_ta:center;
  position:relative;display:inline-flex;align-items:center;justify-content:var(--_jc);gap:8px;box-sizing:border-box;
  min-height:var(--f-h);margin:0;padding:var(--_pb) var(--_pr) var(--_pb) 20px;border:0;border-radius:var(--_r);
  font-family:var(--text);font-size:15px;font-weight:600;line-height:20px;letter-spacing:0;text-align:var(--_ta);text-decoration:none;
  cursor:pointer;-webkit-tap-highlight-color:transparent;
}
.btn:active{box-shadow:inset 0 0 0 100px rgba(16,30,64,.07)}
.btn:is(.primary,.lime,.now):active{box-shadow:inset 0 0 0 100px rgba(0,0,0,.22)}
.btn:focus-visible{outline:2px solid var(--navy);outline-offset:2px}
.deep .btn:focus-visible,.btn.on-deep:focus-visible{outline-color:#fff}
/* sizes */
.btn.slim,.re-table .btn,.cl-save-row .btn{--f-h:var(--f-h-sm);min-height:var(--f-h-sm);padding:var(--_pb) var(--_pr) var(--_pb) 16px;font-size:14px}
.btn.slim:not([data-glyph]):not(.primary),.re-table .btn{--_pr:16px}
.btn.large{--f-h:var(--f-h-lg);min-height:var(--f-h-lg);padding-left:24px}
.btn.full{width:100%}
/* text button */
.btn.link{--_c:none!important;--_pr:0px!important;--_jc:center!important;min-height:36px;padding:0;border-radius:6px;box-shadow:none;font-weight:500;text-decoration:underline;text-underline-offset:4px;text-decoration-thickness:1px}
.btn.link:hover{text-decoration-thickness:2px}
/* destructive: red ink on the quiet fill. A solid red button is never used. */
.btn.danger{--_cell-bg:rgba(217,0,43,.10);--_cell-ink:var(--f-bad-ink);color:var(--f-bad-ink)}
@media(hover:hover){.btn.danger:hover,.tile .btn.danger:hover,.panel .btn.danger:hover,dialog .btn.danger:hover{background:var(--f-bad-wash)}}
/* disabled is final, whatever the surface */
.btn:disabled:not([type=submit]),.btn[aria-disabled=true],.btn[type=submit][aria-busy=false]:disabled{background:var(--soft,#F2F3F7)!important;color:var(--f-frame)!important;box-shadow:none;--_cell-bg:transparent!important;--_cell-ink:var(--f-frame)!important;cursor:not-allowed}

/* the cell. A primary action always carries one: an arrow to go somewhere, a tick to commit.
   Any other button gets one by naming its glyph: data-glyph="arrow | check | down | external | plus | chevron".
   data-glyph="none" removes it. An inline .icon is moved into the cell, so a button never
   shows two glyphs. */
.btn:is(.primary,.lime,.now,[data-glyph],[aria-expanded],[aria-busy=true],[target=_blank]):not([data-glyph=none]),
.btn[type=submit]:disabled:not([aria-busy=false]){--_c:"";--_pr:4px;--_pb:4px;--_jc:space-between;--_ta:left}
.btn:has(>.icon){--_c:none!important;--_pr:4px;--_pb:4px;--_jc:space-between;--_ta:left}   /* important: one cell per button, whatever else the button is */
.btn::after{content:var(--_c);flex:none;align-self:center;width:var(--_cell);height:var(--_cell);margin-left:6px;border-radius:calc(var(--_r) - 4px);background:var(--_cell-bg)}
.btn::before{content:var(--_c);position:absolute;right:4px;top:50%;width:var(--_cell);height:var(--_cell);margin-top:calc(var(--_cell)/-2);background:var(--_cell-ink);-webkit-mask:var(--_g) center/16px 16px no-repeat;mask:var(--_g) center/16px 16px no-repeat;pointer-events:none}
.btn>.icon{order:9;box-sizing:border-box;flex:none;width:var(--_cell);height:var(--_cell);margin-left:6px;padding:calc((var(--_cell) - 18px)/2);border-radius:calc(var(--_r) - 4px);background:var(--_cell-bg);color:var(--_cell-ink)}
/* which glyph */
.btn[type=submit],.btn[data-close].primary,.btn[data-action=mark-read],.btn[data-glyph=check]{--_g:var(--g-check)}
#login-form .btn[type=submit],#recovery-form .btn[type=submit],.btn[data-glyph=arrow]{--_g:var(--g-arrow)}
.btn[data-glyph=down]{--_g:var(--g-down)}
.btn:is([target=_blank],[data-glyph=external]){--_g:var(--g-external)}
.btn[data-glyph=plus]{--_g:var(--g-plus)}
.btn:is([aria-expanded],[data-glyph=chevron]){--_g:var(--g-chevron)}
/* cell colours: the inverse of the body */
.btn:is(.primary,.lime,.now){--_cell-bg:#fff;--_cell-ink:var(--navy)}
.deep .btn.primary,.btn.on-deep.primary{--_cell-bg:var(--navy);--_cell-ink:#fff}
/* armed: under the pointer a quiet button's cell inverts to navy. A primary button's cell is
   already the inverse of its body, so only the body answers. Open means armed too. */
@media(hover:hover){
  .btn:hover{--_cell-bg:var(--navy);--_cell-ink:#fff}
  .btn:is(.primary,.lime,.now):hover{--_cell-bg:#fff;--_cell-ink:var(--navy)}
  .deep .btn.primary:hover,.btn.on-deep.primary:hover{--_cell-bg:var(--navy);--_cell-ink:#fff}
  .btn.danger:hover{--_cell-bg:var(--f-bad);--_cell-ink:#fff}
}
.btn[aria-expanded=true]{--_cell-bg:var(--navy);--_cell-ink:#fff;--_g:var(--g-chevron-up)}
.btn:is(.primary,.lime,.now)[aria-expanded=true]{--_cell-bg:#fff;--_cell-ink:var(--navy)}
/* busy: the label stays, the body keeps its colour, the cell holds the spinner arc.
   motion.css turns the arc. Today the only disabled submit buttons are busy ones. */
.btn[aria-busy=true],.btn[type=submit]:disabled:not([aria-busy=false]){--_g:var(--g-busy)!important;cursor:progress}
.btn:is(.primary,.lime,.now)[type=submit]:disabled:not([aria-busy=false]),.btn:is(.primary,.lime,.now)[aria-busy=true]{background:var(--navy)!important;color:#fff!important}


/* ================= 6. messages ================= */
/* Form-level error summary. Today it holds one sentence; it also takes a heading and a list
   of buttons that move focus to each field (see forms.js). Filled, never striped. */
.error,.notice,.cl-feedback,.form-status{
  display:grid;grid-template-columns:20px minmax(0,1fr);gap:2px 10px;align-items:start;
  padding:12px 16px 12px 14px;border:0;border-radius:var(--f-r);font-size:14px;font-weight:400;line-height:20px;
}
.error>*,.notice>*,.cl-feedback>*,.form-status>*{grid-column:2;min-width:0;margin:0}
.error::before,.notice::before,.cl-feedback::before,.form-status::before{content:"";grid-area:1/1;width:20px;height:20px;background:currentColor;-webkit-mask:var(--g-info) center/18px 18px no-repeat;mask:var(--g-info) center/18px 18px no-repeat}
.error{background:var(--f-bad-wash);color:var(--f-bad-ink);font-weight:500}
.error::before{background:var(--f-bad);-webkit-mask-image:var(--g-alert);mask-image:var(--g-alert)}
.error h3,.error h2{font:600 15px/20px var(--text);color:var(--f-bad-ink)}
.error ul{display:grid;gap:2px;list-style:none;padding:0}
.error-link{display:inline;min-height:24px;padding:2px 0;border:0;background:none;color:inherit;font:inherit;font-weight:500;text-align:left;text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px;cursor:pointer}
.error-link:hover{text-decoration-thickness:2px}
.error:focus{outline:2px solid var(--f-bad);outline-offset:2px}
.notice,.form-status{background:var(--soft,#F2F3F7);color:var(--navy)}
.notice strong{font-weight:600}
.notice.amber,.form-status[data-tone=warning]{background:var(--f-warn-wash);color:var(--f-warn-ink)}
.notice.amber::before,.form-status[data-tone=warning]::before{-webkit-mask-image:var(--g-warn);mask-image:var(--g-warn)}
.form-status[data-tone=success],.cl-feedback.correct{background:var(--f-ok-wash);color:var(--f-ok-ink)}
.form-status[data-tone=success]::before,.cl-feedback.correct::before{-webkit-mask-image:var(--g-ok);mask-image:var(--g-ok)}
.cl-feedback{background:var(--soft,#F2F3F7);color:var(--navy)}
.cl-feedback strong{font-weight:600}
.cl-feedback p{margin:0;font-size:14px}
#modal-status.notice{font-weight:500}
/* a short "saved" line */
.contact-saved,.saved{display:flex;align-items:center;gap:8px;font-size:14px;font-weight:500;line-height:20px;color:var(--f-ok-ink)}
.contact-saved::before,.saved::before{content:"";flex:none;width:18px;height:18px;background:currentColor;-webkit-mask:var(--g-ok) center/18px 18px no-repeat;mask:var(--g-ok) center/18px 18px no-repeat}


/* ================= 7. form layout ================= */
.form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--f-gap-field)}
.form-grid .wide{grid-column:1/-1}
form.stack{gap:var(--f-gap-field)}
/* a named group: <fieldset class="fieldset"><legend>Address</legend> fields </fieldset> */
.fieldset{display:grid;gap:var(--f-gap-field);min-width:0;margin:0;padding:0;border:0}
.fieldset+.fieldset{margin-top:calc(var(--f-gap-group) - var(--f-gap-field))}
.fieldset>legend{float:left;width:100%;padding:0;font:600 15px/22px var(--text);color:var(--navy)}
.fieldset>legend+*{clear:both}
.fieldset>legend+.field-help{margin-top:-12px}
/* action row: the primary action last and at the trailing edge; a note may sit at the start */
.form-actions,.modal-actions,#profile-form>.row.between{display:flex;justify-content:flex-end;align-items:center;gap:8px;flex-wrap:wrap}
.form-actions,#profile-form>.row.between{margin-top:4px;padding-top:16px;border-top:1px solid var(--line,rgba(16,30,64,.10))}
.modal-actions{padding-top:8px}
.form-actions>.form-note,#profile-form>.row.between>span{margin-right:auto;font-size:13px;line-height:18px;color:var(--slate)}
#profile-form>.row.between>.row{gap:8px}
/* sign-in is the one large form */
#login-form,.form-lg{--f-h:var(--f-h-lg)}
#login-form .btn[type=submit]{margin-top:4px}

/* filters: a compact, wrapping bar. Labels stay visible. */
.re-filters,.filters,.course-search{--f-h:var(--f-h-sm)}
.re-filters{display:flex;flex-wrap:wrap;align-items:flex-end;gap:10px 12px}
.re-filter,.filter-group{display:grid;gap:4px;flex:0 1 220px;min-width:150px}
.re-filter label,.filter-group label,.filters .field label,.course-search .field label{font-size:13px;line-height:18px;color:var(--slate)}

/* notes and practice work: the writing area and its status bar are one object */
.cl-section-inner>.cl-label{margin-bottom:-8px}
.cl-check>.cl-label{margin-bottom:-8px}
.cl-section-inner>textarea:not([type=radio]):not([type=checkbox]){position:relative;z-index:1;min-height:220px;border-bottom-left-radius:0;border-bottom-right-radius:0}
.cl-section-inner>#cl-work:not([type=radio]):not([type=checkbox]){min-height:180px}
.cl-save-row{display:flex;justify-content:space-between;align-items:center;gap:8px 12px;flex-wrap:wrap;margin-top:-15px;padding:8px 8px 8px var(--f-pad);border:1px solid var(--f-frame);border-top:0;border-radius:0 0 var(--f-r) var(--f-r);background:var(--f-quiet);font-size:13px;line-height:18px;color:var(--slate)}
.cl-section-inner>textarea:focus+.cl-save-row{border-color:var(--navy)}
.cl-check .btn[type=submit]{justify-self:start}


/* ================= 8. small screens ================= */
@media(max-width:700px){
  .form-grid{grid-template-columns:1fr}
  .form-actions,.modal-actions,#profile-form>.row.between{flex-direction:column-reverse;align-items:stretch}
  .form-actions>.form-note,#profile-form>.row.between>span{margin-right:0}
  #profile-form>.row.between>.row{flex-direction:column-reverse;align-items:stretch}
  .form-actions .btn,.modal-actions .btn,#profile-form>.row.between .btn{width:100%}
  .re-filters{display:grid;grid-template-columns:repeat(2,minmax(0,1fr))}
  .re-filter,.filter-group{min-width:0}
  .cl-save-row .btn{width:100%}
  .cl-check .btn[type=submit]{justify-self:stretch}
}
@media(max-width:380px){.re-filters{grid-template-columns:1fr}}

/* forced colours: masks and painted glyphs need system colours */
@media(forced-colors:active){
  :is(input,select,textarea):not([type=radio]):not([type=checkbox]):focus,.input-group:has(:focus){outline:2px solid Highlight}
  .btn{border:1px solid ButtonText}
  .btn::before,.field-error::before,.field-warning::before,.field-ok::before,.error::before,.notice::before,.cl-feedback::before,.form-status::before,.saved::before,.contact-saved::before{forced-color-adjust:none;background:CanvasText}
  .btn::after{display:none}
  input:is([type=radio],[type=checkbox]){-webkit-appearance:auto;appearance:auto;background:none}
}
