/* Tektura — site stylesheet
   Hand-written. No framework, no reset library.
   Everything here follows the brand guidelines (Business/Brand/Tektura brand guidelines.pdf):
   one dark, one light, one accent; IBM Plex; and the corner rule on every rectangle —
   top-right and bottom-left rounded, top-left and bottom-right square. */

/* Every page loads this sheet, and so do the staff area, the client area, the call room and
   the sign-in approval page, so anything they use stays here. What only one kind of page
   uses lives in that page's own sheet (home.css, how-we-work.css, cost.css, branding.css,
   about.css, legal.css, work.css, tools.css, contact.css), loaded after this one, so a page
   downloads what it draws and little else. A page sheet must never need to beat a later
   rule of the same weight here: being loaded later, it would win where this one used to. */

/* ---------- Fonts (self-hosted, SIL Open Font Licence) ---------- */
@font-face{font-family:"Plex";src:url("../fonts/plex-sans-400.woff2") format("woff2");font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"Plex";src:url("../fonts/plex-sans-500.woff2") format("woff2");font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:"Plex";src:url("../fonts/plex-sans-600.woff2") format("woff2");font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:"PlexMono";src:url("../fonts/plex-mono-400.woff2") format("woff2");font-weight:400;font-style:normal;font-display:swap}

/* ---------- Tokens ---------- */
:root{
  /* The measure: how far a line of reading text may run. Body text and anything smaller
     stop at the same edge, 34rem, about 73 characters of body text, so a small note lines
     up with the paragraph above it. Larger text — a lead — gets the same count of
     characters instead (52ch), so it is not squeezed. The ch is taken at the size of the
     text that uses it. Inside a card or panel the box is the measure. Nothing else sets
     a text width. */
  --measure:max(34rem,52ch);
  --ink:#12161B;
  --paper:#F2F1EE;
  --white:#FFFFFF;
  --slate:#5C6470;
  --rule:#DEDCD6;
  --signal:#C2410C;
  --signal-dark:#E8590C;
  --body:#333B45;
  /* On ink. Ink is the ground; these are the two steps above it and the two text
     weights that sit on them. Named so a tenth grey does not get invented. */
  --ink-raised:#1E242C;     /* a panel lifted off ink */
  --ink-hi:#2A313A;         /* the same panel under the pointer */
  --on-ink:#D6DADF;         /* body text on ink — 12.9:1 */
  --on-ink-dim:#A7B0BA;     /* labels, captions, small text on ink — 8.3:1 */
  /* Status, not brand. A state a thing is in — live, passed, healthy — and nothing else.
     Never a second accent, never furniture, never on a page as decoration. */
  --status:#1E6B3A;
  --status-bg:#E6EFE7;
  --tint:#F6CDBA;           /* pale orange: large type on signal or ink only — 3.5:1 on signal, so never for small text */
  /* The staff area's own few, so nothing reaches for a hex. */
  --paper-soft:#F8F7F4;     /* a lighter ground inside a white card */
  --rule-soft:#ECEAE5;      /* a hairline inside a card, lighter than rule */
  --rule-strong:#CFCBC2;    /* the line under a field, and quiet marks */
  --signal-bg:#FBE9DF;      /* the ground behind something that needs someone */
  --signal-text:#9A3412;    /* signal for small text on signal-bg */
  --field-edge:#7A818A;     /* the line round a field or a choice — 3.9:1 on white, 3.5:1 on paper */
  --signal-on-raised:#EE6418; /* signal-dark a step lighter, for small text on ink-raised — 4.8:1 */

  --sans:"Plex",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  --panel:#12161B;        /* a panel that sits against the page: ink by day, raised by night */
  --panel-ink:#F2F1EE;
  --mono:"PlexMono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;

  /* The radius scale — roughly 22% of the element's height, capped at 30px */
  --r-tag:6px;
  --r-btn:10px;
  --r-tab:16px;
  --r-card:19px;
  --r-img:30px;

  --chev:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 5l7 7-7 7"/></svg>');

  --gutter:clamp(16px,4vw,40px);
  --max:1120px;
}

/* ---------- Base ---------- */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--sans);font-size:17px;line-height:1.62;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
img,svg,video{max-width:100%;display:block}
[hidden]{display:none !important}
a{color:var(--signal);text-decoration:none;border-bottom:1px solid currentColor;transition:color .15s ease}
a:hover{color:var(--ink)}
:focus-visible{outline:3px solid var(--signal);outline-offset:3px;border-radius:2px}
/* Selected text: orange with white words, and ink with white words on anything orange, so it always shows. A high-contrast setting on the computer replaces both. */
::selection{background:var(--signal);color:var(--white)}
.htab::selection,.htab ::selection,.card.signal::selection,.card.signal ::selection,.tag.signal::selection,.tag.signal ::selection,.btn::selection,.btn ::selection,.btn.ink:hover::selection,.btn.ink:hover ::selection,.system .piece.signal::selection,.system .piece.signal ::selection,.system .piece.go .pill::selection,.system .piece.go .pill ::selection,.of-open::selection,.of-open ::selection,.of-i:nth-child(12n+5) .of-art::selection,.of-i:nth-child(12n+5) .of-art ::selection,.of-i:nth-child(12n+12) .of-art::selection,.of-i:nth-child(12n+12) .of-art ::selection,.s1-reply::selection,.s1-reply ::selection,.photo.ba .ba-tag::selection,.photo.ba .ba-tag ::selection,.ba-art .ba-l.now::selection,.ba-art .ba-l.now ::selection,.cs-row:hover .cs-go::selection,.cs-row:hover .cs-go ::selection,.sl-btn::selection,.sl-btn ::selection,.est-peek .go::selection,.est-peek .go ::selection,.cr .cr-save::selection,.cr .cr-save ::selection,.cr-hint b::selection,.cr-hint b ::selection,.cx-ring::selection,.cx-ring ::selection{background:var(--ink);color:var(--white)}
.htab.ink::selection,.htab.ink ::selection,.btn.ink:not(:hover)::selection,.btn.ink:not(:hover) ::selection{background:var(--signal);color:var(--white)}
p{margin:0 0 1em;max-width:var(--measure);text-wrap:pretty}
/* Inside a box — a card, a step, a panel — text fills the box; the box is the measure. */
:where(body:not(.staff,.client)) :is(.card,.case,.step,.q,.cell,.caveat) :is(p,li){max-width:none}
/* Lists of reading text keep the same measure; lists built as components set their own. */
:where(ul:not([class]),ol:not([class]),.ticks)>li{max-width:var(--measure);text-wrap:pretty}
p:last-child{margin-bottom:0}
strong,b{font-weight:600}
hr{border:0;border-top:1px solid var(--rule);margin:0}
.skip{position:absolute;left:-999px;top:0;background:var(--ink);color:var(--paper);padding:10px 16px;border:0;z-index:100}
.skip:focus{left:var(--gutter)}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* ---------- The corner rule ---------- */
.tab{border-bottom-left-radius:var(--r,var(--r-card));border-top-right-radius:var(--r,var(--r-card))}

/* ---------- Type ---------- */
.display{font-weight:600;font-size:clamp(34px,5.4vw,56px);line-height:1.08;letter-spacing:-0.005em;margin:0;text-wrap:balance}
h1,h2,h3,h4{margin:0;line-height:1.14;font-weight:600;text-wrap:balance}
/* Short lines share their words out evenly, and longer ones never end on one word alone.
   .nw keeps a range or a figure and its unit on one line. */
:where(.label,.tag,figcaption,.upclose,.foot-bar>span,.proc-stat span,dt,dd,th,.go,.btn,summary,strong,b,em,.lg-card-p,.in-short,.hq-hint){text-wrap:balance}
p.st-big{text-wrap:balance}
:where(li,td,.ly-d,.kp-what){text-wrap:pretty}
.nw{white-space:nowrap}
/* Headings are in sentence case. Only a section's orange tab (.htab) is in capitals. */
h2{font-size:clamp(24px,3vw,30px);letter-spacing:0}
h3,.as-h3{font-size:20px;letter-spacing:0;line-height:1.3}
h4,.as-h4{font-size:17px;letter-spacing:0.02em;text-transform:none;line-height:1.14}
.lede{font-size:clamp(18px,2vw,21px);line-height:1.5;color:var(--ink);max-width:var(--measure)}
.step p,.case .body p{font-size:15px;line-height:1.55}   /* Body small — a card or a step, where 17 is too loose */
.small{font-size:14px;line-height:1.5;color:var(--slate)}
.mono{font-family:var(--mono)}
.label{font-family:var(--mono);font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:var(--slate);line-height:1.4}
.num{font-family:var(--mono);font-variant-numeric:tabular-nums}

/* Section heading tab — the orange "entry" per section */
.htab{display:inline-block;background:var(--signal);color:var(--paper);font-weight:600;font-size:clamp(20px,2.4vw,26px);line-height:1.15;letter-spacing:0.07em;text-transform:uppercase;padding:14px 26px 14px 22px;border-bottom-left-radius:var(--r-tab);border-top-right-radius:var(--r-tab);margin:0 0 24px}
.htab.ink{background:var(--ink)}

/* ---------- Layout ---------- */
.wrap{max-width:var(--max);margin:0 auto;padding-inline:var(--gutter)}
.section{padding-block:clamp(56px,8vw,104px)}
.section.pale{background:var(--white)}   /* the third ground: the thing you work through — the steps, the estimator, the terms */
.section.pale :is(.card,.step,.q,.case,.strip .cell):not(.ink){background:var(--paper)}
.grid{display:grid;gap:clamp(20px,3vw,32px)}
.g2{grid-template-columns:repeat(2,minmax(0,1fr))}
.g3{grid-template-columns:repeat(3,minmax(0,1fr))}
@media (max-width:900px){.g3{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:620px){.g2,.g3{grid-template-columns:1fr}}
.stack>*+*{margin-top:var(--stack,16px)}
.row{display:flex;flex-wrap:wrap;gap:12px 16px;align-items:center}
.dark{background:var(--ink);color:var(--paper)}
.dark .small,.dark .label{color:var(--on-ink-dim)}
.dark a{color:var(--signal-dark)}
.dark a:hover{color:var(--paper)}
.dark h2,.dark h3{color:var(--paper)}
.dark p{color:var(--on-ink)}

/* ---------- Surfaces ---------- */
.card{background:var(--white);border-bottom-left-radius:var(--r-card);border-top-right-radius:var(--r-card);padding:clamp(22px,3vw,32px)}
.card.ink{background:var(--ink);color:var(--paper)}
.card.ink .small,.card.ink .label{color:var(--on-ink-dim)}
.card.ink p{color:var(--on-ink)}
.card.signal{background:var(--signal);color:var(--paper)}
.card.signal .label,.card.signal .small{color:var(--paper)}
.card.signal p{color:var(--paper)}
.card.paper{background:var(--paper)}
.tag{display:inline-block;font-family:var(--mono);font-size:11px;letter-spacing:0.12em;text-transform:uppercase;color:var(--slate);background:var(--paper);padding:6px 11px;border-bottom-left-radius:var(--r-tag);border-top-right-radius:var(--r-tag);line-height:1.2;white-space:nowrap}
.card .tag{background:var(--paper)}
.tag.white{background:var(--white)}
.tag.ink{background:var(--ink);color:var(--paper)}
.tag.signal{background:var(--signal);color:var(--paper)}
.tag.live{background:var(--status-bg);color:var(--status)}
.photo{background:var(--ink);border-bottom-left-radius:var(--r-img);border-top-right-radius:var(--r-img);aspect-ratio:4/3;overflow:hidden;position:relative}
.photo img{width:100%;height:100%;object-fit:cover}
.photo .cap{position:absolute;left:0;right:0;bottom:0;background:var(--ink);color:var(--paper);padding:12px 18px;font-size:14px;font-weight:500;border-top-right-radius:var(--r-btn)}

/* ---------- Buttons ---------- */
.btn{display:inline-flex;align-items:center;gap:10px;background:var(--signal);color:var(--white);font-weight:500;font-size:14px;letter-spacing:0.06em;text-transform:uppercase;padding:15px 24px;border:0;border-bottom-left-radius:var(--r-btn);border-top-right-radius:var(--r-btn);line-height:1.2;cursor:pointer;transition:background .15s ease,transform .15s ease;font-family:var(--sans);white-space:nowrap}
.btn:hover{background:var(--ink);color:var(--paper)}
.btn:active{transform:translateY(1px)}
.btn.ink{background:var(--ink)}
.btn.ink:hover{background:var(--signal);color:var(--white)}
/* On an orange panel an orange hover would vanish into it, so there it turns white. */
:is(.of-open,.card.signal) .btn.ink:hover{background:var(--white);color:var(--signal)}
/* The same for the keyboard's focus ring: orange on orange can't be seen. */
:is(.of-open,.card.signal) :focus-visible{outline-color:var(--white)}
.btn.white{background:var(--white);color:var(--ink)}
.btn.white:hover{background:var(--ink);color:var(--paper)}
.btn.quiet{background:transparent;color:var(--ink);padding-inline:0;border-bottom:1px solid var(--ink);border-radius:0;text-transform:none;letter-spacing:0;font-size:16px;font-weight:500;padding-block:2px}
.btn.quiet:hover{color:var(--signal);border-color:var(--signal)}
.btn[disabled]{opacity:.55;cursor:default}

/* ---------- Header device: white bar, ink chip let into the end ---------- */
/* The header is transparent at rest — over the hero it would be paper on paper
   anyway — and becomes a solid paper bar with a hairline once you have scrolled.
   The gradient it used to carry was invisible on paper and a pale smear over the
   dark band. Padding is identical in both states so nothing jumps. */
.site-head{padding:16px 0;position:sticky;top:0;z-index:50;background:transparent;transition:background-color .18s ease,box-shadow .18s ease}
.site-head.stuck{background:var(--paper);box-shadow:0 1px 0 var(--rule)}
@media (prefers-reduced-motion:reduce){.site-head{transition:none}}
.bar{position:relative;display:flex;align-items:center;gap:24px;background:var(--white);border-bottom-left-radius:var(--r-tab);border-top-right-radius:var(--r-tab);padding:10px 18px 10px 20px;min-height:60px;box-shadow:0 1px 0 rgba(18,22,27,.03)}
.bar .brand{display:inline-flex;align-items:center;gap:12px;color:var(--ink);border:0;font-weight:600;letter-spacing:0.10em;font-size:17px;line-height:1}
.bar .brand svg{width:26px;height:26px;color:var(--ink)}
.bar nav{display:flex;gap:6px;margin-left:auto;margin-right:150px}
.bar nav a{border:0;color:var(--ink);font-size:14px;font-weight:500;letter-spacing:0.06em;text-transform:uppercase;padding:9px 12px;border-bottom-left-radius:var(--r-tag);border-top-right-radius:var(--r-tag)}
.bar nav a:hover,.bar nav a[aria-current]{background:var(--paper)}
.bar .chip{position:absolute;top:0;right:0;bottom:0;display:inline-flex;align-items:center;background:var(--ink);color:var(--paper);padding:0 22px;font-size:13px;font-weight:500;letter-spacing:0.08em;text-transform:uppercase;border:0;border-bottom-left-radius:var(--r-tab);border-top-right-radius:var(--r-tab);transition:background .15s ease}
.bar .chip:hover{background:var(--signal);color:var(--paper)}
.bar .menu{display:none;margin-left:auto;background:var(--paper);border:0;font:inherit;font-size:13px;font-weight:500;letter-spacing:0.08em;text-transform:uppercase;padding:10px 14px;border-bottom-left-radius:var(--r-tag);border-top-right-radius:var(--r-tag);cursor:pointer}
@media (max-width:860px){
  .bar nav{display:none;position:absolute;left:0;right:0;top:calc(100% + 8px);background:var(--white);flex-direction:column;padding:12px;border-bottom-left-radius:var(--r-tab);border-top-right-radius:var(--r-tab);margin:0}
  .bar nav.open{display:flex}
  .bar nav a{padding:12px 14px}
  .bar .menu{display:inline-block;margin-right:130px}
  .bar .chip{padding:0 16px;font-size:12px}
}
@media (max-width:480px){.bar .brand span{display:none}.bar .menu{margin-right:118px}}

/* ---------- Footer device: same construction ---------- */
.site-foot{padding:clamp(24px,3.5vw,44px) 0 28px}
.foot-bar{position:relative;background:var(--white);border-bottom-left-radius:var(--r-tab);border-top-right-radius:var(--r-tab);padding:14px 20px;display:flex;align-items:center;gap:16px;font-family:var(--mono);font-size:11px;letter-spacing:0.12em;text-transform:uppercase;color:var(--slate);min-height:48px;margin-top:32px}
.foot-bar .chip{position:absolute;top:0;right:0;bottom:0;display:inline-flex;align-items:center;background:var(--ink);color:var(--paper);padding:0 18px;border:0;border-bottom-left-radius:var(--r-tab);border-top-right-radius:var(--r-tab);font-family:var(--mono);letter-spacing:0.12em}
.foot-bar .chip:hover{background:var(--signal)}
.foot-grid{display:grid;grid-template-columns:1.4fr 1fr 1fr 1fr 1fr;gap:32px}
@media (max-width:960px){.foot-grid{grid-template-columns:repeat(4,1fr)}.foot-grid>:first-child{grid-column:1/-1}}
@media (max-width:560px){.foot-grid{grid-template-columns:1fr}}
.foot-grid a{border:0;color:var(--ink)}
.foot-grid a:hover{color:var(--signal)}
.foot-grid ul{list-style:none;margin:0;padding:0}
.foot-grid li{margin:0 0 8px}
/* Social links: a tag-sized tile in the mark's own shape — ink block, paper glyph, the
   corner rule — sitting in the line so the rows keep the same rhythm as the other lists. */
.foot-social .tile{display:inline-grid;place-items:center;width:24px;height:24px;margin:-6px 10px -6px 0;vertical-align:-1px;background:var(--ink);color:var(--paper);border-top-right-radius:var(--r-tag);border-bottom-left-radius:var(--r-tag);transition:background .15s}
.foot-social .gl{display:block;width:12px;height:12px}
.foot-social a:hover .tile{background:var(--signal)}
.lockup{display:inline-flex;align-items:center;gap:14px;color:var(--ink);border:0;font-weight:600;letter-spacing:0.10em;font-size:22px;line-height:1}
.lockup svg{width:40px;height:40px}
.avail{display:inline-flex;align-items:center;gap:9px;font-family:var(--mono);font-size:12px;letter-spacing:0.1em;text-transform:uppercase;color:var(--slate);background:var(--white);padding:9px 14px;border-bottom-left-radius:var(--r-tag);border-top-right-radius:var(--r-tag)}

/* The system picture: a site and the pieces behind it, drawn in the brand's own shapes */
.system{position:relative;display:grid;gap:12px;padding:8px}
.system .piece{background:var(--white);border-bottom-left-radius:var(--r-card);border-top-right-radius:var(--r-card);padding:18px 20px;display:flex;align-items:center;justify-content:space-between;gap:16px;opacity:0;transform:translateY(14px);transition:opacity .5s ease,transform .5s ease}
.system.in .piece{opacity:1;transform:none}
.system .piece:nth-child(2){transition-delay:.12s}.system .piece:nth-child(3){transition-delay:.24s}.system .piece:nth-child(4){transition-delay:.36s}.system .piece:nth-child(5){transition-delay:.48s}
.system .piece.ink{background:var(--ink);color:var(--paper)}
.system .piece.signal{background:var(--signal);color:var(--paper)}
.system .piece.signal .label{color:var(--paper)}
.system .piece.ink .label{color:var(--on-ink-dim)}
.system .piece strong{font-weight:600;font-size:16px;display:block}
.system .piece .label{margin-top:3px;display:block}
.system .link{margin-left:20px;width:2px;height:12px;background:var(--rule)}
@media (prefers-reduced-motion:reduce){.system .piece{opacity:1;transform:none;transition:none}}

/* ---------- Case study cards ---------- */
.case{display:grid;grid-template-rows:auto 1fr;background:var(--white);border-bottom-left-radius:var(--r-card);border-top-right-radius:var(--r-card);overflow:hidden;color:var(--ink);border:0;transition:transform .2s ease}
.case:hover{transform:translateY(-3px);color:var(--ink)}
.case .body p{font-size:15px;color:var(--body)}

/* Work cards: the whole page scrolls past inside the frame. --scroll is how far this
   page has to travel, --sdur how long that takes; both are set on the card. */
.photo.scroll>img{position:absolute;top:0;left:0;width:100%;height:auto;transition:transform .9s cubic-bezier(.4,0,.2,1)}

/* ---------- Steps ---------- */
.steps{counter-reset:step;display:grid;gap:12px}
.step{display:grid;grid-template-columns:64px 1fr;gap:18px;background:var(--white);padding:20px 22px;border-bottom-left-radius:var(--r-card);border-top-right-radius:var(--r-card);align-items:start}
.step .n{font-family:var(--mono);font-size:12px;letter-spacing:.12em;color:var(--paper);background:var(--ink);display:inline-flex;align-items:center;justify-content:center;width:52px;height:36px;border-bottom-left-radius:var(--r-tag);border-top-right-radius:var(--r-tag)}
.step :is(h4,.as-h4){margin-bottom:6px}
.step p{font-size:15px;color:var(--body);max-width:none}

/* ---------- Tables ---------- */
table{border-collapse:collapse;width:100%;font-size:15px}
th,td{text-align:left;padding:10px 0;border-bottom:1px solid var(--rule);vertical-align:top}
th{font-family:var(--mono);font-size:11px;letter-spacing:0.12em;text-transform:uppercase;color:var(--slate);font-weight:400}
th[scope="row"]{padding-right:16px}

/* ---------- Forms ---------- */
.field{display:grid;gap:6px;align-content:start}
/* A label is read, not scanned: ordinary type in the text colour, everywhere a form is.
   "(optional)" and other asides in it are quieter. The hint under a label says what the
   field wants, and is tied to it for screen readers. */
.field > label,.field > .lab{font-family:var(--sans);font-size:15px;line-height:1.35;letter-spacing:0;text-transform:none;color:var(--ink);font-weight:600}
.field > label .opt-l,.field > .lab .opt-l,:where(body:not(.staff,.client)) .field label span{color:var(--slate);font-weight:400}
.field .hint{font-size:13.5px;color:var(--slate);margin-top:-3px;line-height:1.4}
.field .f-err{font-size:14px;color:var(--signal);font-weight:500}
.field .f-err::before{content:"! ";font-weight:700}
/* A field's edge is always visible (3.9:1 on white, 3.5:1 on paper), so a box reads as a
   box without guessing. Focus thickens it in the signal colour. */
.input,textarea,select{width:100%;font:inherit;font-size:16px;color:var(--ink);background:var(--white);border:0;padding:13px 15px;border-bottom-left-radius:var(--r-btn);border-top-right-radius:var(--r-btn);box-shadow:inset 0 0 0 1.5px var(--edge,var(--field-edge));transition:box-shadow .15s ease}
.input::placeholder,textarea::placeholder{color:var(--slate)}
.input:focus,textarea:focus,select:focus{outline:none;box-shadow:inset 0 0 0 2.5px var(--signal)}
.input[aria-invalid=true],textarea[aria-invalid=true],select[aria-invalid=true]{box-shadow:inset 0 0 0 2px var(--signal)}
textarea{min-height:140px;resize:vertical}
.check{display:flex;gap:10px;align-items:flex-start;font-size:15px;color:var(--body)}
.check input{margin-top:5px;accent-color:var(--signal)}
.note{font-size:14px;color:var(--slate)}
.error{color:var(--signal);font-size:14px}
.ok{background:var(--ink);color:var(--paper);padding:18px 20px;border-bottom-left-radius:var(--r-card);border-top-right-radius:var(--r-card)}
.q{background:var(--white);padding:22px 24px;border-bottom-left-radius:var(--r-card);border-top-right-radius:var(--r-card)}
.q :is(h4,.as-h4){margin-bottom:12px}
.opts{display:grid;gap:8px}
.step ul{margin:8px 0 0;padding-left:20px}
.step li{margin:6px 0;color:var(--body)}
.ticks{list-style:none;padding:0;margin:12px 0 0}
.ticks li{position:relative;padding-left:28px;margin:10px 0;color:var(--body)}
.ticks li::before{content:"";position:absolute;left:2px;top:.5em;width:13px;height:7px;border-left:2px solid var(--signal);border-bottom:2px solid var(--signal);transform:rotate(-45deg)}
.htab+.card{margin-top:22px}
/* 404 */
.link-cards{grid-template-columns:repeat(4,minmax(0,1fr))}
@media (max-width:900px){.link-cards{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:520px){.link-cards{grid-template-columns:1fr}}
.link-card{display:block;color:var(--ink);border:0;transition:transform .2s ease}
.link-card:hover{transform:translateY(-3px);color:var(--ink)}
.link-card .go{display:block;margin-top:10px;font-size:16px;line-height:1.45;color:var(--body)}
/* An arrow in each card, so it reads as somewhere to go without a pointer to lift it.
   Bottom right on wide screens; on a phone, where the cards are rows, at the right of the row. */
.link-card{position:relative;padding-bottom:calc(clamp(22px,3vw,32px) + 34px)}
.link-card .arr{position:absolute;right:clamp(22px,3vw,32px);bottom:clamp(20px,2.6vw,28px);width:22px;height:22px;fill:none;stroke:var(--signal);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;transition:transform .2s ease}
.link-card:hover .arr{transform:translateX(3px)}
@media (max-width:520px){
  .link-card{padding-bottom:clamp(22px,3vw,32px);padding-right:64px}
  .link-card .arr{top:50%;bottom:auto;margin-top:-11px}
}
/* The number itself, set large in the heading's own weight and the signal orange. */
.nf-code{margin:0 0 clamp(18px,2.2vw,24px) -.035em;font-weight:600;font-size:clamp(112px,16vw,200px);line-height:.78;letter-spacing:-.05em;color:var(--signal);font-variant-numeric:tabular-nums}

/* ---------- Whatever you run: the screen draws itself ----------
   The section's one idea is that a website gets built, so the drawn screen builds:
   the chrome drops in, the nav and the headline rise, the bars measure themselves out
   from the left, and the button lands last. Transform and opacity only, so it is
   composited on the GPU and runs at whatever the display does. All of it off under
   prefers-reduced-motion, where the pane simply appears. */
@keyframes fy-up{from{opacity:0;transform:translateY(9px)}to{opacity:1;transform:none}}
@keyframes fy-pop{from{opacity:0;transform:scale(.94)}to{opacity:1;transform:none}}

/* ---------- Reveal ---------- */
.reveal{opacity:0;transform:translateY(12px);transition:opacity .5s ease,transform .5s ease}
.reveal.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){.reveal{opacity:1;transform:none;transition:none}}
/* What fades in is hidden until site.js says it is on screen. If that file never arrives
   (a dropped connection, a blocker), nothing may stay hidden for good: after four seconds
   it is simply shown. site.js puts .rv on the page the moment it runs, which switches this
   off, so with the script working nothing here ever plays. */
@keyframes rv-late{to{opacity:1;transform:none}}
html:not(.rv) :is(.reveal,.system .piece){animation:rv-late .4s ease 4s forwards}

/* ---------- Print ---------- */
@media print{.site-head,.site-foot,.btn,.avail{display:none !important}body{background:#fff}
  /* On paper: whatever was waiting to fade in is there, and a panel prints in its own
     colours. Left to the browser, the grounds are dropped and paper-coloured words on an
     ink panel (the contents and "at a glance" on the terms) print as nothing on white. */
  .reveal,.system .piece{opacity:1!important;transform:none!important;animation:none!important}
  *,*::before,*::after{-webkit-print-color-adjust:exact;print-color-adjust:exact}
  /* A scroll scene is an ordinary section on paper, not three screens of held space. */
  .scenes-live .scene{height:auto!important}
  .scenes-live .scene-pin{position:static!important;height:auto!important}
}

/* ---------- Scrollbars ---------- */
/* Same shape as everything else: an ink thumb with the corner rule, on a paper track.
   On dark surfaces the thumb is paper. Firefox gets the colours; the shape is Chromium/Safari. */
@supports not selector(::-webkit-scrollbar){
  *{scrollbar-width:thin;scrollbar-color:var(--ink) var(--paper)}
  .dark,.card.ink,.rail{scrollbar-color:var(--paper) var(--ink)}
}
::-webkit-scrollbar{width:14px;height:14px}
::-webkit-scrollbar-button{display:none;height:0;width:0}
::-webkit-scrollbar-track{background:var(--paper)}
::-webkit-scrollbar-thumb{background:var(--ink);border:3px solid var(--paper);border-bottom-left-radius:5px;border-top-right-radius:5px;background-clip:padding-box;min-height:40px}
::-webkit-scrollbar-thumb:hover{background:var(--signal);background-clip:padding-box}
::-webkit-scrollbar-corner{background:var(--paper)}
.dark::-webkit-scrollbar-track,.card.ink::-webkit-scrollbar-track,.rail::-webkit-scrollbar-track{background:var(--ink)}
.dark::-webkit-scrollbar-thumb,.card.ink::-webkit-scrollbar-thumb,.rail::-webkit-scrollbar-thumb{background:var(--paper);border-color:var(--ink)}
.dark::-webkit-scrollbar-thumb:hover,.card.ink::-webkit-scrollbar-thumb:hover,.rail::-webkit-scrollbar-thumb:hover{background:var(--signal-dark)}
.card ::-webkit-scrollbar-track,.panel ::-webkit-scrollbar-track{background:var(--white)}
.card ::-webkit-scrollbar-thumb,.panel ::-webkit-scrollbar-thumb{border-color:var(--white)}

/* ---------- The mark as a background device ----------
   The mark is a square and a band is a wide, short rectangle, so the only placement
   that does not look accidental is this one: a fraction of the band's height, sitting
   inside the top and bottom edges, running off one side. One clean cut, on one edge.
   It needs a tall band with room in it; on a short or busy band, leave it out. */
.section{position:relative;isolation:isolate}
.dark>.wrap{position:relative;z-index:1}
.mark-bg.l svg{left:-9%}

/* ---------- The system, in the hero ----------
   The four pieces as before. A spine draws down beside them and a dot walks it,
   each piece lighting as the dot arrives. The dot is ink, not signal: ink carries
   structure, and signal is already doing its one job on this view — the button.
   The switch underneath shows what a page builder gives you instead. */
.system{padding-left:30px}
/* The dot moves by transform, not by top. Animating top repaints the dot and the
   spine under it on every frame, which is what left the fringing around it. */
.system .dot{position:absolute;left:9px;top:8px;width:8px;height:8px;background:var(--ink);border-bottom-left-radius:2px;border-top-right-radius:2px;z-index:2;opacity:0;
  transform:translate3d(0,0,0);will-change:transform,opacity;
  transition:transform .7s cubic-bezier(.4,0,.2,1),opacity .28s ease}
.system.in .dot{opacity:1}
.system .piece{position:relative;z-index:1;transition:opacity .5s ease,transform .5s cubic-bezier(.2,.7,.2,1),background-color .35s,color .35s,border-bottom-left-radius .4s cubic-bezier(.2,.7,.2,1),border-top-right-radius .4s cubic-bezier(.2,.7,.2,1)}
.system .piece .pill{transition:background-color .3s,color .3s}
@media (hover:hover) and (prefers-reduced-motion:no-preference){
  .system .piece:hover{transform:translateY(-3px);border-bottom-left-radius:calc(var(--r-card) * 1.6);border-top-right-radius:calc(var(--r-card) * 1.6)}
}
/* the other state: what a page builder gives you */
.system .piece .alt{display:none}
@media (prefers-reduced-motion:reduce){.system .dot{display:none}}
@media (prefers-reduced-motion:reduce){.intro{display:none}}

/* ---------- Between pages ----------
   Cross-document view transitions: the header bar keeps its place while the old
   page's content slips out and the new page's slips in, so five documents read as
   one system. Nothing to load, nothing to script. Browsers without it simply
   navigate as they always did, and it is switched off entirely under reduced
   motion. */
@view-transition{navigation:auto}
.site-head{view-transition-name:head}
main{view-transition-name:main}
::view-transition-group(head){animation-duration:.18s}
::view-transition-old(main){animation:vt-out .12s cubic-bezier(.4,0,1,1) forwards}
::view-transition-new(main){animation:vt-in .22s cubic-bezier(0,0,.2,1) both}
@keyframes vt-out{to{opacity:0;transform:translateY(-10px)}}
@keyframes vt-in{from{opacity:0;transform:translateY(12px)}}
@media (prefers-reduced-motion:reduce){
  @view-transition{navigation:none}
  ::view-transition-old(main),::view-transition-new(main){animation:none}
}

/* Larger screens: the public site runs wider and bigger. Staff and client areas keep their own sizes. */
@media (min-width:900px){
:where(body:not(.staff,.client)){--max:1280px;font-size:18.5px}
:where(body:not(.staff,.client)) .display{font-size:clamp(40px,5.2vw,76px);line-height:1.04}
:where(body:not(.staff,.client)) .lede{font-size:clamp(20px,1.75vw,25px);max-width:var(--measure)}
:where(body:not(.staff,.client)) h2{font-size:clamp(26px,2.6vw,36px)}
:where(body:not(.staff,.client)) :is(h3,.as-h3){font-size:22px}
:where(body:not(.staff,.client)) .htab{font-size:clamp(22px,2.2vw,32px);padding:17px 32px 17px 26px}
:where(body:not(.staff,.client)) .small{font-size:15.5px}
:where(body:not(.staff,.client)) .label{font-size:12px}
:where(body:not(.staff,.client)) .btn{font-size:15.5px;padding:17px 26px}
:where(body:not(.staff,.client)) .bar nav a{font-size:15px}
:where(body:not(.staff,.client)) .bar .brand{font-size:19px}
:where(body:not(.staff,.client)) .card{padding:clamp(26px,3vw,40px)}
:where(body:not(.staff,.client)) .system .piece strong{font-size:18px}
:where(body:not(.staff,.client)) .case .body p,:where(body:not(.staff,.client)) .step p{font-size:17px}
:where(body:not(.staff,.client)) .step{padding:26px 28px;grid-template-columns:72px 1fr}
:where(body:not(.staff,.client)) .section{padding-block:clamp(56px,7vw,112px)}
}

.bar nav a.only-narrow{display:none}
/* Phones: built for a thumb. Anything tappable is at least 44px tall, nothing is squeezed
   into two columns that has to be read, and the estimate stays in view while you answer. */
@media (max-width:860px){
  .bar nav{padding:8px;gap:2px;box-shadow:0 18px 40px rgba(18,22,27,.12)}
  .bar nav a{font-size:16px;padding:14px 16px;letter-spacing:.05em}
  .bar nav a.only-narrow{display:block}
  .bar .menu{padding:12px 16px}
}
@media (max-width:560px){
  :where(body:not(.staff,.client)) .display{font-size:clamp(36px,10.4vw,44px);line-height:1.06}
  :where(body:not(.staff,.client)) .label{font-size:11.5px}
  .section{padding-block:52px}
  .card.signal .btn{width:100%;justify-content:center;min-height:48px}

  /* the system picture: one line a piece */
  .system{padding-left:22px;gap:10px}.system .dot{left:5px}
  .system .piece{padding:14px 14px 14px 16px;gap:10px}
  .system .piece strong{font-size:16px}
  .system .piece .label{font-size:12px;letter-spacing:.05em}

  /* steps: the number sits on the title's line instead of taking a column */
  :where(body:not(.staff,.client)) .step{grid-template-columns:1fr;gap:10px;padding:18px 18px 20px}
  .step .n{width:auto;height:26px;padding:0 10px;justify-self:start}

  /* the terms table: label above its line */
  table tr{display:block;padding:12px 0;border-bottom:1px solid var(--rule)}
  table th,table td{display:block;padding:0;border:0}
  table th{margin-bottom:4px}
  .bar .brand{min-height:44px}
  .q{padding:18px 16px}

  /* footer: two columns of links, each a proper target */
  .site-foot{padding-bottom:calc(20px + env(safe-area-inset-bottom))}
  .foot-grid{grid-template-columns:1fr 1fr;gap:28px 16px}
  .foot-grid>:first-child{grid-column:1/-1}
  .foot-grid li{margin:0}
  .foot-grid li a{display:block;padding:10px 0}
  .foot-bar{flex-direction:column;align-items:stretch;padding:0;gap:0;overflow:hidden}
  .foot-bar>span{padding:14px 18px;line-height:1.7}
  .foot-bar .chip{position:static;justify-content:center;min-height:48px;border-top-right-radius:0}
}
@media (max-width:374px){
  .tag{white-space:normal}
  .bar .chip{padding:0 12px;font-size:11px}
  .bar .menu{margin-right:100px;padding:10px 12px}
}
@media (max-width:860px){
  .est-peek .label{color:var(--on-ink-dim);display:block;font-size:10.5px}
}

/* Over a dark section the header turns with it: the strip goes ink, the bar a step
   lighter, the words paper, and Book a call takes the signal so it keeps its shape.
   Solid colours only — the same blocks, swapped — and it turns back on paper. */
.bar,.bar .brand,.bar .brand svg,.bar nav a,.bar .menu{transition:background-color .2s ease,color .2s ease}
.site-head.stuck.on-dark,.site-head.top-dark{background:var(--ink);box-shadow:0 1px 0 rgba(255,255,255,.08)}
.site-head.on-dark .bar{background:var(--ink-raised);box-shadow:none}
.site-head.on-dark .bar .brand,.site-head.on-dark .bar .brand svg,.site-head.on-dark .bar nav a{color:var(--paper)}
.site-head.on-dark .bar nav a:hover,.site-head.on-dark .bar nav a[aria-current]{background:var(--ink-hi)}
.site-head.on-dark .bar .chip{background:var(--paper);color:var(--ink)}
.site-head.on-dark .bar .chip:hover{background:var(--signal);color:var(--paper)}
.site-head.on-dark .bar .menu{background:var(--ink-hi);color:var(--paper)}
@media (max-width:860px){.site-head.on-dark .bar nav{background:var(--ink-raised);box-shadow:0 18px 40px rgba(0,0,0,.35)}}
@media (prefers-reduced-motion:reduce){.bar,.bar .brand,.bar .brand svg,.bar nav a,.bar .menu{transition:none}}

/* Justified text. Every running line of text on the public site is justified and
   hyphenated on screens wider than a tablet — paragraphs, cards, steps, lists, the
   estimator, the footer. A paragraph's last line stays left, so one-liners are unchanged.
   Phones stay left-aligned: at that measure justifying opens gaps between words. The
   staff area, the client area and the call room are screens to work in, not pages to
   read, and stay left-aligned too. */
@media (min-width:861px){
  :where(body:not(.staff,.client,.cx)) :is(main,.site-foot) :is(p,li,td,.small,.note){
    text-align:justify;hyphens:auto;-webkit-hyphens:auto;hyphenate-limit-chars:7 3 3}
  /* Boxes too narrow for it (the footer's first column, the cells under the home hero)
     stay left-aligned: under about thirty characters a line, justifying opens gaps. */
  :where(body:not(.staff,.client,.cx)) :is(.foot-grid>:first-child p,.strip .cell .small){text-align:left;hyphens:manual;-webkit-hyphens:manual}
}

/* Balance inside every box: the same space on the left as the right, and the same at
   the bottom as the top. The last thing in a box drops its outside margin, so a
   paragraph's own spacing doesn't add a strip under the text. */
:where(body:not(.staff,.client)) :is(.card,.case .body,.step>div,.q,.strip .cell)>:last-child{margin-bottom:0}
:where(body:not(.staff,.client)) :is(.card,.case .body,.step>div,.q,.strip .cell)>:last-child>:last-child{margin-bottom:0}
@media (min-width:561px){
  :where(body:not(.staff,.client)) .q{padding:24px}
  :where(body:not(.staff,.client)) .step{padding:24px}
}
@media (max-width:560px){
  :where(body:not(.staff,.client)) .q{padding:18px}
  :where(body:not(.staff,.client)) .step{padding:18px}
}

/* Room to breathe: two-column rows sit further apart, and steps carry more space inside
   and between, so a large lede beside a stack of steps doesn't feel packed. */
@media (min-width:861px){
  :where(body:not(.staff,.client)) .g2{column-gap:72px}
  :where(body:not(.staff,.client)) .steps{gap:14px}
  :where(body:not(.staff,.client)) .step{padding:32px;column-gap:24px}
}

/* ---- What we can build into it. Twenty-five parts, drawn from the brand's own pieces.
   The SLOT owns the ground — ink, paper or signal, in a fixed pattern — and the part owns
   the drawing, so the grid keeps its chequer however the tiles turn over. Every drawing
   is built from the same handful of primitives, which take their colour from the ground
   they land on. ---- */
.of{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(10px,1.3vw,16px);margin-top:26px}
.of .sq,.of .cell,.of .stamp i,.of .tick,.of .cal i{transition:background-color .4s ease}
@keyframes of-note{0%{transform:scale(1)}30%{transform:scale(1.09)}100%{transform:scale(1)}}
.of .counting{display:inline-block;transform-origin:left center;animation:of-note .5s cubic-bezier(.3,1.3,.4,1)}
/* A row that arrives, and one that makes way for it. */
.of [data-in]{max-height:0;opacity:0;overflow:hidden;margin-top:-7px;
  transition:max-height .42s cubic-bezier(.3,.8,.3,1),opacity .3s ease,margin-top .42s cubic-bezier(.3,.8,.3,1)}
.of [data-in].shown{max-height:46px;opacity:1;margin-top:0}
.of [data-out]{max-height:46px;opacity:1;overflow:hidden;
  transition:max-height .42s cubic-bezier(.3,.8,.3,1),opacity .28s ease,margin-top .42s cubic-bezier(.3,.8,.3,1)}
.of [data-out].gone{max-height:0;opacity:0;margin-top:-7px}
.of .dim{opacity:.55;transition:opacity .35s ease}

/* the primitives */
.of .big{font-weight:600;font-size:clamp(16px,1.9vw,21px);line-height:1;letter-spacing:-.01em;font-variant-numeric:tabular-nums}
.of .mono{font-family:var(--mono);font-size:11px;letter-spacing:.02em;color:var(--strong)}
.of .r{display:block;height:6px;border-radius:2px;background:var(--line)}
.of .r.hi{background:var(--accent)}.of .r.mid{background:var(--strong)}
.of .file{width:22px;height:28px;border-radius:2px;background:var(--line);position:relative;flex:none}
.of .file::after{content:"";position:absolute;left:4px;right:4px;bottom:4px;height:5px;border-radius:2px;background:var(--accent)}
.of .bars{display:flex;align-items:flex-end;gap:5px;height:34px}
.of .bars i{flex:1;border-radius:2px;background:var(--line)}
.of .bars i.hi{background:var(--accent)}
.of .qr{display:grid;grid-template-columns:repeat(5,1fr);gap:3px;width:44px}
.of .qr span{aspect-ratio:1;border-radius:1px;background:var(--soft)}
.of .qr span.on{background:var(--accent)}
.of .page{width:24px;height:31px;border-radius:2px;background:var(--line);display:grid;align-content:center;gap:4px;padding:0 5px}
.of .page i{display:block;height:3px;border-radius:1px;background:var(--soft)}
.of .field{background:var(--soft);border-radius:3px;padding:6px 8px;display:flex;align-items:center;gap:7px}
.of .amt{font-family:var(--mono);font-size:10.5px;color:var(--strong);flex:none;font-variant-numeric:tabular-nums}
.of .rule{height:1px;background:var(--line);margin:1px 0}
.of .tag{font-family:var(--mono);font-size:8.5px;letter-spacing:.09em;text-transform:uppercase;line-height:1.5;
  padding:2px 5px;border-radius:var(--r-tag);background:var(--soft);color:currentColor;opacity:.72;flex:none}
.of .tag.on{background:var(--accent);color:var(--paper);opacity:1}
.of .r.hl{background:var(--accent);opacity:.8}
.of .stage{height:3px;border-radius:2px;background:var(--strong);opacity:.45}
.of .cal b{font-family:var(--mono);font-size:7.5px;font-weight:400;text-align:center;color:var(--strong)}
.of .rail{width:28px;display:grid;gap:5px;align-content:start;flex:none}
.of .rail i{height:5px;border-radius:2px;background:var(--soft)}
.of .rail i.on{background:var(--accent)}
.of .az i{font-family:var(--mono);font-size:7px;line-height:1;color:currentColor;opacity:.6}
.of .tick{width:7px;height:7px;border-radius:50%;background:var(--accent);flex:none}
.of .tick.off{background:var(--soft)}
.of .code{background:var(--soft);border-radius:3px;padding:7px 8px;display:grid;gap:4px}

/* a few more shapes the newer tiles need */
.of .star{width:9px;height:9px;flex:none;background:var(--accent);
  clip-path:polygon(50% 0,61% 35%,98% 35%,68% 57%,79% 91%,50% 70%,21% 91%,32% 57%,2% 35%,39% 35%)}
.of .star.off{background:var(--soft)}
@media (max-width:1000px){.of{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:520px){.of{grid-template-columns:1fr}}
@media (prefers-reduced-motion:no-preference){
  @keyframes of-fill{0%{transform:scaleX(.06)}13%{transform:scaleX(1)}100%{transform:scaleX(1)}}
  @keyframes of-grow{0%{transform:scaleY(.16)}13%{transform:scaleY(1)}100%{transform:scaleY(1)}}
  @keyframes of-rise{0%{transform:translateY(5px);opacity:0}11%{transform:none;opacity:1}100%{transform:none;opacity:1}}
  @keyframes of-light{0%{opacity:.16}8%{opacity:1}100%{opacity:1}}
  .of .r.hi,.of .file::after{transform-origin:left;animation:of-fill 9s var(--d,0s) infinite cubic-bezier(.3,.8,.3,1)}
  .of .bars i{transform-origin:bottom;animation:of-grow 9s calc(var(--d,0s) + var(--b,0s)) infinite cubic-bezier(.3,.8,.3,1)}
  .of .bars i:nth-child(2){--b:.07s}.of .bars i:nth-child(3){--b:.14s}.of .bars i:nth-child(4){--b:.21s}
  .of .bars i:nth-child(5){--b:.28s}.of .bars i:nth-child(6){--b:.35s}
  .of .sq.on,.of .cell.on,.of .qr span.on{animation:of-light 9s calc(var(--d,0s) + var(--b,0s)) infinite}
  .of .qr span.on:nth-child(2n){--b:.28s}.of .qr span.on:nth-child(3n){--b:.5s}
  .of .big{animation:of-rise 9s var(--d,0s) infinite cubic-bezier(.3,.8,.3,1)}
}
.wk-stand{font-size:19px;line-height:1.5;color:var(--body);max-width:var(--measure);margin:16px 0 0;text-align:left}
.wk-band.white{background:var(--white)}
/* Whatever the page is scrolled to (an in-page link's heading, the website check's answer,
   something reached with the keyboard, forwards or back) stops just below the sticky
   header, not under it: the header's height and a little more. A scroll-margin on the
   thing itself is added to this. */
html:has(>body>.site-head){scroll-padding-top:112px}
@media (max-width:560px){html:has(>body>.site-head){scroll-padding-top:87px}}
@supports not selector(:has(a)){
  :where(body:not(.staff,.client)) main :is([id],a,button,input,select,textarea,summary,[tabindex]){scroll-margin-top:112px}
}
/* and something reached with the keyboard stops short of the bottom edge */
:where(body:not(.staff,.client)) main :is(a,button,input,select,textarea,summary,[tabindex]){scroll-margin-bottom:24px}

/* The header starts large and settles. At the very top of a page the bar is taller and
   the logo bigger; the moment the page moves, it eases down to its working size. The
   header gives the height it loses back as margin underneath, over the same time, so
   the page below doesn't move while it happens. Phones keep the compact bar. */
@media (min-width:861px){
  :where(body:not(.staff,.client)){--head-grow:32px}
  .site-head{transition:background-color .18s ease,box-shadow .18s ease,margin-bottom .3s cubic-bezier(.2,.7,.2,1)}
  :where(body:not(.staff,.client)) .bar{height:64px}
  .bar{transition:height .3s cubic-bezier(.2,.7,.2,1),padding .3s cubic-bezier(.2,.7,.2,1),background-color .2s ease}
  .bar .brand{transition:font-size .3s cubic-bezier(.2,.7,.2,1),gap .3s cubic-bezier(.2,.7,.2,1),color .2s ease}
  .bar .brand svg{transition:width .3s cubic-bezier(.2,.7,.2,1),height .3s cubic-bezier(.2,.7,.2,1),color .2s ease}
  :where(body:not(.staff,.client)) .site-head:not(.stuck) .bar{height:calc(64px + var(--head-grow));padding-left:28px}
  :where(body:not(.staff,.client)) .site-head:not(.stuck) .bar .brand{font-size:26px;gap:18px}
  :where(body:not(.staff,.client)) .site-head:not(.stuck) .bar .brand svg{width:46px;height:46px}
  :where(body:not(.staff,.client)) .site-head.stuck{margin-bottom:var(--head-grow)}
}
@media (min-width:861px) and (prefers-reduced-motion:reduce){
  .site-head,.bar,.bar .brand,.bar .brand svg{transition:none}
}

/* The opening section sits 72px under the header on laptops and desktops — closer than the
   space between sections further down, so the header and the page's first words read
   as one. */
@media (min-width:861px){
  :where(body:not(.staff,.client)) main>section:first-child{padding-top:72px}
}

/* ---------- The site drafts itself ----------
   Driven by assets/js/motion.js, which adds every class here and takes them away again
   once each piece has played. Without the script, or with reduced motion, none of it
   applies and the page is simply there. Ink draws the lines; signal is never a line. */
.m-wait main :is(.card,.case,.htab,.strip .cell,.steps,.hero .display){opacity:0}
.m-ready main .reveal{opacity:1;transform:none;transition:none}

/* drafted */
.m-dr{position:relative;isolation:isolate}
.m-dr>.m-fill{position:absolute;inset:0;z-index:-1;background:var(--fill);border-top-right-radius:inherit;border-bottom-left-radius:inherit;
  clip-path:inset(100% 0 0 0);transition:clip-path .55s cubic-bezier(.5,0,.2,1) calc(var(--d,0ms) + .5s)}
.m-dr>.m-line{position:absolute;inset:0;width:100%;height:100%;z-index:2;pointer-events:none;overflow:visible}
.m-dr>.m-line path{fill:none;stroke:var(--line);stroke-width:1.5;vector-effect:non-scaling-stroke;stroke-dasharray:var(--len);stroke-dashoffset:var(--len);
  transition:stroke-dashoffset .75s cubic-bezier(.4,0,.25,1) var(--d,0ms),opacity .3s ease calc(var(--d,0ms) + 1.05s)}
.m-dr>:not(.m-fill):not(.m-line){opacity:0;transition:opacity .45s ease calc(var(--d,0ms) + .85s)}
.m-dr.on>.m-fill{clip-path:inset(0 0 0 0)}
.m-dr.on>.m-line path{stroke-dashoffset:0;opacity:0}
.m-dr.on>:not(.m-fill):not(.m-line){opacity:1}

/* brackets */
.m-cf{position:relative;opacity:0;transform:translateY(14px);border-top-right-radius:0!important;border-bottom-left-radius:0!important;
  transition:opacity .5s ease var(--d,0ms),transform .6s cubic-bezier(.2,.7,.2,1) var(--d,0ms),
    border-top-right-radius .45s cubic-bezier(.2,.7,.2,1) calc(var(--d,0ms) + .45s),border-bottom-left-radius .45s cubic-bezier(.2,.7,.2,1) calc(var(--d,0ms) + .45s)}
.m-cf.on{opacity:1;transform:none;border-top-right-radius:var(--rr)!important;border-bottom-left-radius:var(--rr)!important}
.m-cf>.m-brk{position:absolute;inset:-6px;width:calc(100% + 12px);height:calc(100% + 12px);pointer-events:none;overflow:visible;z-index:3}
.m-cf>.m-brk path{fill:none;stroke:var(--line);stroke-width:1.5;vector-effect:non-scaling-stroke;stroke-dasharray:120;stroke-dashoffset:120;
  transition:stroke-dashoffset .6s cubic-bezier(.4,0,.25,1) calc(var(--d,0ms) + .3s),opacity .4s ease calc(var(--d,0ms) + 1.1s)}
.m-cf.on>.m-brk path{stroke-dashoffset:0;opacity:0}

/* headline */
.m-set .m-ln{display:block;overflow:hidden;padding-bottom:.08em;margin-bottom:-.08em}
.m-set .m-ln>span{display:inline-block;transform:translateY(108%);transition:transform .9s cubic-bezier(.2,.8,.2,1)}
.m-set.on .m-ln>span{transform:none}
.m-dw>b>span,.m-dw>.small{opacity:0;transition:opacity .5s ease calc(var(--d,0ms) + .35s)}
.m-dw>b{color:transparent;transition:color .5s ease calc(var(--d,0ms) + .35s)}
.m-dw.on>b{color:inherit}
.m-dw.on>.small{opacity:1}

/* light steps: in sequence, with a line drawn beside them */
.m-sq{position:relative}
.m-sq>.m-spine{position:absolute;left:-22px;top:30px;width:1.5px;height:calc(100% - 60px);background:var(--ink);opacity:.35;transform:scaleY(0);transform-origin:top;transition:transform 1.1s cubic-bezier(.4,0,.25,1) .1s}
.m-sq.on>.m-spine{transform:none}
@media (max-width:860px){.m-sq>.m-spine{display:none}}

/* tabs slide out */
.m-tab{clip-path:inset(0 100% 0 0);transition:clip-path .6s cubic-bezier(.6,0,.2,1)}
.m-tab.on{clip-path:inset(0 0 0 0)}

/* the mark on a dark band draws, then fills */
.m-mark svg path{fill:transparent;stroke:currentColor;stroke-width:.6;stroke-dasharray:760;stroke-dashoffset:760;transition:stroke-dashoffset 1.6s cubic-bezier(.4,0,.25,1),fill .9s ease 1.4s}
.m-mark.on svg path{stroke-dashoffset:0;fill:currentColor}

/* printing: the finished page, at once, without the intro in front of it */
.m-print *{transition:none!important}
@media print{.intro{display:none!important}.m-line,.m-brk,.m-spine{display:none!important}}

/* The day breakdown: one job, named pieces. Hover a piece to see it move. */
.days{margin-top:28px;position:relative}
.drow .dd{font-family:var(--mono);font-size:10.5px;letter-spacing:.08em;color:var(--slate);white-space:nowrap}

/* ---------- The steps, drawn (how we work) ---------- */

/* ---------- How we work: the steps, as one stage that plays ----------
   The ink ground is spent here because this is the argument the page most
   wants to win: four steps, and the first two cost nothing. */

/* ---------- How we work: the four steps as a story ----------
   The words scroll; beside them one stage plays the job out as you go — an email in, a
   call, a quote in days, the deposit, the site drafting itself week by week, then live.
   Every moving part is driven by how far down its step you are (--p1…--p4, 0 to 1), so
   scrolling back plays it backwards. Nothing moves for anyone who asked for less motion:
   each step's finished picture is simply shown. Without the script the stage is left out
   and the steps read as a list. */
.story{background:var(--ink);color:var(--paper);padding:clamp(48px,7vw,96px) 0 clamp(40px,6vw,80px)}
.s3-page .b{--t:clamp(0,(var(--p3) - .15 - var(--k)*.1)*6,1);--c:clamp(0,(var(--p4) - .25 - var(--k)*.05)*5,1);background:var(--paper);box-shadow:inset 0 0 0 1.5px #C9C6BE;border-top-right-radius:8px;border-bottom-left-radius:8px;opacity:var(--t);transform:translateY(calc((1 - var(--t))*16px));transition:background-color .01s}
[data-scrub]{--p:1}
.ce{display:inline-flex;cursor:pointer}
.ce span{display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:10px 16px;font-size:15px;font-weight:500;line-height:1.25;background:var(--white);color:var(--ink);box-shadow:inset 0 0 0 1.5px var(--field-edge);border-top-right-radius:var(--r-btn);border-bottom-left-radius:var(--r-btn);transition:background .15s,box-shadow .15s}
.ce:hover span{box-shadow:inset 0 0 0 1.5px var(--ink)}
.ce input:checked+span{background:var(--ink);color:var(--paper);box-shadow:none}
.ce input:checked+span::before{content:"";width:11px;height:6px;border-left:2px solid currentColor;border-bottom:2px solid currentColor;transform:translateY(-2px) rotate(-45deg)}
/* Two rules, not one list: a browser that does not know :has() throws away the whole of a
   rule it appears in, and the chips would lose their ring along with the tiles. */
:is(.ce,.lvl-e,.lk,.af) input:focus-visible+span{outline:2.5px solid var(--signal);outline-offset:3px}
.te:has(input:focus-visible){outline:2.5px solid var(--signal);outline-offset:3px}
@supports not selector(:has(a)){.te:focus-within{outline:2.5px solid var(--signal);outline-offset:3px}}
/* Where to start */
.levels{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.lvl-e>span{flex:1;display:flex;flex-direction:column;gap:6px;padding:16px 16px 18px;background:var(--white);box-shadow:inset 0 0 0 1.5px var(--field-edge);border-top-right-radius:var(--r-card);border-bottom-left-radius:var(--r-card);transition:background .15s}
/* Tiles */
.tiles-e{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.te{position:relative;display:flex;flex-direction:column;gap:6px;padding:14px 14px 16px;background:var(--white);box-shadow:inset 0 0 0 1.5px var(--field-edge);border-top-right-radius:var(--r-btn);border-bottom-left-radius:var(--r-btn);cursor:pointer;transition:background .15s}
/* The look */
.looks{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
/* After launch */
.afters{display:grid;grid-template-columns:1fr 1fr;gap:10px}
@media (max-width:980px){.levels,.tiles-e{grid-template-columns:repeat(2,1fr)}}
@media (max-width:540px){.levels,.looks,.afters{grid-template-columns:1fr}}
/* The result: where it sits, what it is, a small picture of it */
@media (prefers-reduced-motion:reduce){.ce span,.te,.lvl-e>span{transition:none}}
/* 24 Sep 2026, second copy: an edge cache kept the first */

/* ---------- Scroll scenes (scenes.js) ----------
   A scene is tall; inside it one screen's worth sticks under the header while you scroll
   through, and --p (0 to 1) says how far. Until the script says otherwise — and always for
   anyone who asked for less motion — a scene is an ordinary section, shown finished. */
.scene{--p:1;position:relative}
.scenes-live .scene{height:260vh;padding-block:0}
.scene-pin{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,6fr);gap:clamp(28px,5vw,72px);align-items:center;padding-block:clamp(48px,7vw,88px)}
.scenes-live .scene-pin{position:sticky;top:var(--head-h,80px);height:calc(100vh - var(--head-h,80px));padding-block:24px}
@media (max-width:860px){
  .scene-pin{grid-template-columns:minmax(0,1fr);gap:18px}
  .scenes-live .scene-pin{align-content:start;padding-block:14px}
}
.scenes-live .ab-k{font-size:13px;margin-bottom:16px}
.of .tx.s{font-size:10.5px;color:var(--strong)}
.of .tag{font-size:9px;padding:2px 6px}
.of .mono{font-size:11px}
.of .row{display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:6px;background:var(--soft);min-width:0}
.of .dot{width:7px;height:7px;border-radius:50%;background:var(--accent);flex:none}
.of .field{padding:5px 8px;gap:8px}
.of .post{aspect-ratio:1;border-radius:4px;background:var(--soft);position:relative;overflow:hidden}
.of .post::after{content:"";position:absolute;left:18%;right:18%;bottom:18%;height:14%;border-radius:2px;background:var(--strong)}
.of .phone{width:38px;height:62px;border-radius:8px;border:2px solid var(--strong);padding:8px 5px;display:grid;grid-template-columns:repeat(2,1fr);gap:4px;align-content:start;flex:none}
.of .phone i{aspect-ratio:1;border-radius:3px;background:var(--line)}
.of .phone i.on{background:var(--accent)}
.of .code{padding:6px 8px;gap:2px}
.of .tx.s,.of .amt,.of .mono,.of .cal b,.of .az i{color:var(--mute)}
.of .tag{opacity:1;color:var(--mute)}.of .tag.on{color:var(--paper)}

/* The contact page: when suits them for the call */
.when{border:0;padding:0;margin-inline:0;margin-bottom:0;min-width:0;grid-template-columns:minmax(0,1fr)}
.when legend{padding:0;margin-bottom:6px}
.when .ce input{position:absolute;opacity:0;width:1px;height:1px;margin:0}
.when .hint{margin-bottom:2px}
.when .chips-e{margin-bottom:4px}
/* Tap areas 44px tall round small links, without moving anything: the case studies'
   crumb and the ticket page's card fees */
.cf-crumb a,.tf-own summary{position:relative}
.cf-crumb a::before{content:"";position:absolute;inset:-12px -6px}
.tf-own summary::after{content:"";position:absolute;inset:-10px 0}
.chk-i.fair .chk-dot{background:#B7791F}
.chk-i.poor .chk-dot{background:var(--signal)}
.cl-print{margin-top:22px;display:flex;flex-wrap:wrap;align-items:center;gap:14px}
@media print{
  .site-head,.site-foot,.skip,.cl-print,.intro,#est-peek{display:none!important}
  body{background:#fff}
  .lede{font-size:12pt}
}

/* Phones: the same moves, quicker. Everything is readable within half a second of
   arriving; the lines and corners finish around it. */
.m-lite .m-dr>.m-fill{transition-duration:.4s;transition-delay:calc(var(--d,0ms) + .12s)}
.m-lite .m-dr>.m-line path{transition:stroke-dashoffset .5s cubic-bezier(.4,0,.25,1) var(--d,0ms),opacity .25s ease calc(var(--d,0ms) + .55s)}
.m-lite .m-dr>:not(.m-fill):not(.m-line){transition:opacity .3s ease calc(var(--d,0ms) + .22s)}
.m-lite .m-cf{transition:opacity .3s ease var(--d,0ms),transform .4s cubic-bezier(.2,.7,.2,1) var(--d,0ms),
  border-top-right-radius .3s ease calc(var(--d,0ms) + .25s),border-bottom-left-radius .3s ease calc(var(--d,0ms) + .25s)}
.m-lite .m-cf>.m-brk path{transition:stroke-dashoffset .4s cubic-bezier(.4,0,.25,1) calc(var(--d,0ms) + .15s),opacity .3s ease calc(var(--d,0ms) + .6s)}
.m-lite .m-dw>b,.m-lite .m-dw>b>span,.m-lite .m-dw>.small{transition-delay:calc(var(--d,0ms) + .15s)}
.m-lite .m-tab{transition-duration:.4s}

/* ---------- Phones, second pass ----------
   Measured at 360 and 390 wide. The header gives back a third of its height, the small
   capitals never drop below 12px, anything tapped is 44px, the scroll scenes ask for
   less swiping, and the footer is two columns all the way down. */
@media (max-width:560px){
  .site-head{padding:8px 0}
  .bar{min-height:54px;padding:5px 14px 5px 16px;gap:12px}
  .bar .brand{min-height:44px}
  .bar .menu{padding:12px 14px;min-height:44px}
  :where(body:not(.staff,.client)) :is(.label,.tag,.fy-cue,.ba-tag,.ab-k,.wk-meta,.proc-stat span,.qtopic summary em,.drow .dd,figcaption,table th,.glance dt){font-size:12px}
  .foot-grid{gap:22px 16px}
}
@media (max-width:700px){
  .scenes-live .scene{height:190vh}
}
main{overflow-x:clip}

/* ---------- Using the width: the call questions, the cost page ----------
   Big ledes are left-aligned: at 25px and over, justifying opens gaps between words
   that are hard to read past. */
@media (min-width:861px){ :where(body:not(.staff,.client,.cx)) main .section .lede{text-align:left;hyphens:manual} }
/* Numbered clauses: 3.1, 3.2 and 3.2.1, so any line can be pointed to */
.terms .step{counter-increment:sec}
.terms{counter-reset:sec}
/* Legal wording reads left-aligned: justified lines in numbered clauses open gaps */
main .section :is(.terms,.priv-body) :is(p,li,td){text-align:left!important;hyphens:manual}

/* ---------- Hover: big enough to see without looking for it ----------
   Anything you can click answers the pointer clearly, all to the same degree: cards lift, cast a shadow and
   round their brand corners further; plain links go ink with a thicker underline;
   the menu fills in ink. Only on devices with a real pointer. */
@media (hover:hover){
  :where(body:not(.staff,.client,.cx)) a:not([class]):hover{box-shadow:0 1px 0 currentColor}
  .case,.link-card{transition:transform .25s cubic-bezier(.3,.8,.3,1),box-shadow .25s ease,border-radius .3s ease}
  .case:hover,.link-card:hover{transform:translateY(-6px);box-shadow:0 22px 40px -24px rgba(18,22,27,.55)}
  .case:hover{border-bottom-left-radius:calc(var(--r-card) * 1.6);border-top-right-radius:calc(var(--r-card) * 1.6)}
  .bar nav a:hover{background:var(--ink);color:var(--paper)}
  .site-head.on-dark .bar nav a:hover{background:var(--paper);color:var(--ink)}
  .ce:hover span{box-shadow:inset 0 0 0 2.5px var(--ink)}
}
@media (hover:hover) and (prefers-reduced-motion:no-preference){
  .system .piece:hover{transform:translateY(-6px);box-shadow:0 20px 36px -22px rgba(18,22,27,.55)}
}

/* Step numbers, big enough to read the order at a glance. The terms keep their small
   numbered tags, since there they sit beside clause headings. */
.steps:not(.terms) .step .n{background:none;width:auto;height:auto;padding:0;font-family:inherit;font-size:clamp(34px,3.4vw,46px);font-weight:600;line-height:.9;letter-spacing:-.03em;color:var(--signal);font-variant-numeric:tabular-nums}
.section.dark .steps:not(.terms) .step .n{color:#FF6A2B}
/* Phone type scale. On a phone the public pages use seven text sizes, each with one job:
   12 labels, 15 secondary text, 17 body, 18 card titles, 20 the intro paragraph, 22 sub-headings,
   28 section headings. Each stylesheet ends with its own share of these rules, written against the
   same selectors that set the sizes in the first place. */
@media (max-width:520px){
  /* labels and tags */
  :where(body:not(.staff,.client)) footer .foot-bar span{font-size:12px}
  /* secondary text */
  :where(body:not(.staff,.client)) .small,:where(body:not(.staff,.client)) main .small a,:where(body:not(.staff,.client)) main .hq-hint span,:where(body:not(.staff,.client)) main .small time,:where(body:not(.staff,.client)) main .sum-foot span,:where(body:not(.staff,.client)) main .drop strong,:where(body:not(.staff,.client)) main .drop strong>span,:where(body:not(.staff,.client)) main .days-total strong,:where(body:not(.staff,.client)) main .days-total strong>span,:where(body:not(.staff,.client)) main .sum-foot a,:where(body:not(.staff,.client)) main .lk span>em>a,:where(body:not(.staff,.client)) main .af span>em>b,:where(body:not(.staff,.client)) .field .hint{font-size:15px}
  /* body text inside cards and lists */
  :where(body:not(.staff,.client)) main .of-open p>b,:where(body:not(.staff,.client)) main .st-end b,:where(body:not(.staff,.client)) main .card p>a,:where(body:not(.staff,.client)) main .sstep p>a{font-size:17px}
  /* the intro paragraph */
  :where(body:not(.staff,.client)) .lede,:where(body:not(.staff,.client)) .wk-stand{font-size:20px}
  /* sub-headings */
  /* these carry a size in a style attribute */
  :where(body:not(.staff,.client)) main .as-h3,:where(body:not(.staff,.client)) main .card h2:not(:where(.chk-g)),:where(body:not(.staff,.client)) main .card div>h3{font-size:22px!important}
  /* spacing: one gap under every section title, one button height */
  :where(body:not(.staff,.client)) main .htab,:where(body:not(.staff,.client)) main .wk-head .htab{margin-bottom:24px}
  /* !important because several of these carry their own margin in a style attribute */
  :where(body:not(.staff,.client)) main .htab+*{margin-top:0!important}
  :where(body:not(.staff,.client)) main .btn:not(.quiet){min-height:48px;padding-block:13px}
}
/* A finger needs more to aim at than a mouse does. On a touch screen of any width, the
   small links and buttons take an invisible margin round them (never a bigger box), so
   they look exactly as they did and are 44px or so to press. */
@media (pointer:coarse){
  .btn.quiet,.upclose a,.photo.ba .ba-tag,.c-out,.c-back,.live-link{position:relative}
  .photo.ba .ba-tag{position:absolute}
  .btn.quiet::after,.upclose a::after,.c-out::after,.c-back::after,.live-link::after{content:"";position:absolute;inset:-11px -6px}
  .upclose a::after{inset:-14px -8px}
  .photo.ba .ba-tag::after{content:"";position:absolute;inset:0 0 -12px -8px}
}
/* The narrowest phones: a button's words may take two lines. Held to one, "Book a free
   20-minute call" is wider than a 320px screen less its margins and ran off the edge. */
@media (max-width:374px){
  :where(body:not(.staff,.client)) main .btn:not(.quiet){white-space:normal;text-align:center;justify-content:center}
}
/* Under 340px the fixed gap kept beside Menu for the chip is no longer sure to be enough, so the
   chip takes its place in the row and the two cannot meet whatever the font measures. Last in the
   file: the phone rules above set the same properties. */
@media (max-width:339px){.bar{gap:8px}.bar .brand{flex:none}.bar .menu{margin-right:0;padding-inline:10px}.bar .chip{position:static;flex:none;align-self:stretch;margin:-5px -14px -5px 0;padding:0 10px;white-space:nowrap}}

/* Phones: labels that are read, never under 12px. (The little screens drawn inside the
   pictures keep their own sizes: they are pictures of screens.) */
@media (max-width:700px){
  .piece .pill span,.st-mlab span,.s3-weeks span,.foot-bar .chip,.cr-scale span,.cr-plan-k span,.bb-tag,.gus-sw i,.cb-sw span,.mk-aa small{font-size:12px!important}
}
/* The same floor at every width: labels, tags and fine print that are read. */
.foot-bar>span,.foot-bar .chip,main .tag:not(.of-art .tag),.piece .pill span,.ly-n,.ha-row em,.ha-link em,
.wk-facts i,.cf-meas li>span,.cf-p figcaption span,.cf-in figcaption span,.cs-chrome .cs-url,
.proc-stat span,.st-mlab span,.qtopic summary em,.drow .dd,.halves span,.table-wrap th,.cf-table th,.glance dt,.ab-k:not(.scenes-live .ab-k),.lg-go,
.bb-tag,.mk-aa small,.gus-art figcaption,.gus-sw i,.cb-sw span,.cr-doc em,.cr-scale span,.cr-plan-k span,.est-peek .pk-price .label,
.auth .brandline .label,.c-brandline .label,.pw .peek{font-size:12px!important}
@media (min-width:561px){.est-peek .pk-prog{font-size:12px!important}}
@media (min-width:701px){.s1-from{font-size:12px!important}}

/* ---------- Windows contrast themes (forced colours) ----------
   A contrast theme drops shadows and gradients and paints every ground in its own colour,
   and here those draw a field's edge, a choice's outline, what is chosen and a button's
   shape. So in a contrast theme they get real lines: borders round fields, choices and
   buttons, the theme's highlight colour round a chosen answer, and the price bar, the
   sign-in switches and the plus and minus on the question topics drawn the same way.
   None of it applies anywhere else. Element names and ids outrank the page sheets that
   load after this one. */
@media (forced-colors:active){
  .input,textarea,select,.ce span,.lvl-e>span,.te,.lk>span,.af>span,.stepper,.seg{border:1px solid CanvasText}
  .input:focus,textarea:focus,select:focus{outline:2px solid Highlight;outline-offset:1px}
  .btn:not(.quiet),#est-peek .go{border:1px solid}
  div.seg button{border:1px solid Canvas}
  label:is(.ce,.lvl-e,.lk,.af) input:checked+span,label.te.on,div.seg button[aria-pressed=true]{border-color:Highlight}
  label:is(.ce,.lvl-e,.lk,.af) input:checked:not(:focus-visible)+span,label.te.on:not(:focus-within),div.seg button[aria-pressed=true]:not(:focus-visible){outline:2px solid Highlight;outline-offset:-3px}
  label.te:has(input:checked){border-color:Highlight}
  label.te:has(input:checked):not(:has(input:focus-visible)){outline:2px solid Highlight;outline-offset:-3px}
  #est-peek{background:Canvas;border:2px solid CanvasText}
  label:is(.toggle,.c-toggle) i{border:1px solid CanvasText}
  label:is(.toggle,.c-toggle) i::after{background:CanvasText}
  label:is(.toggle,.c-toggle) input:checked+i{border-color:Highlight}
  label:is(.toggle,.c-toggle) input:checked+i::after{background:Highlight}
  details.qtopic>summary::after{content:"+";display:grid;place-items:center;border:1px solid CanvasText;font:500 17px/1 var(--mono)}
  details.qtopic[open]>summary::after{content:"\2212"}
}
