/* Optimised Handling: clinician workspace. Clean, dense, PhysioTools-style layout on the Thrive palette. */
:root{--tp-ink:#0b1f19;--tp-forest:#0d3d35;--tp-leaf:#2c6b52;--tp-gold:#d9a441;--tp-text:#17302a;--tp-muted:#5a6f68;--tp-line:#dfe6e2;--tp-bg:#f4f6f5;--tp-red:#e0524a;--tp-amber:#e7b34a;--tp-green:#3f9d6d;--tp-font:"Instrument Sans",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif}
*{box-sizing:border-box}
html{overflow-x:clip}
body.tp-body{margin:0;background:var(--tp-bg);color:var(--tp-text);font:15px/1.5 var(--tp-font);-webkit-font-smoothing:antialiased;min-height:100vh}
body.tp-body a{color:var(--tp-leaf)}
body.tp-body button{font-family:inherit}
h1,h2,h3{margin:0;color:var(--tp-text);line-height:1.15}
.tp-logo{display:inline-flex;align-items:center;gap:10px;font-weight:700;letter-spacing:.14em;font-size:14px;color:var(--tp-forest);text-decoration:none}
.tp-logo span{width:34px;height:34px;border-radius:9px;background:var(--tp-forest);color:#fff;display:grid;place-items:center;font-size:13px;letter-spacing:.06em}
.tp-eyebrow{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--tp-leaf);font-weight:600}
.tp-btn{appearance:none;border:0;border-radius:10px;padding:11px 18px;background:var(--tp-forest);color:#fff;font-weight:600;font-size:14px;cursor:pointer}
.tp-btn--ghost{background:#fff;color:var(--tp-forest);border:1px solid var(--tp-line)}
/* A button that happens to be a link was losing its colour to the sheet's link rule,
   which is a step more specific: leaf green text on the forest green button, 1.92:1.
   "Email the code to the care agency" is the primary action on the screen that issues a
   plan, and it was all but invisible. */
body.tp-body a.tp-btn{color:#fff}
body.tp-body a.tp-btn--ghost{color:var(--tp-forest)}
body.tp-body a.tp-btn:hover{color:#fff}
body.tp-body a.tp-btn--ghost:hover{color:var(--tp-forest)}
.tp-linkbtn{appearance:none;border:0;background:none;padding:0;color:var(--tp-leaf);font-size:13px;cursor:pointer;text-decoration:underline;text-underline-offset:3px}
/* A control that destroys something does not look like one that opens something. */
.tp-linkbtn--del{color:#a3271a;font-weight:600}
.tp-linkbtn--del:hover{color:#7d1d13}
.tp-linkbtn--del[disabled]{opacity:.55;cursor:default;text-decoration:none}
/* Read aloud, never drawn. */
.tp-vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}

/* ---------------------------------------------------------------------------
   v20: the pack leaves the foot of the screen, and the library keeps its controls
   ------------------------------------------------------------------------- */

/* The search box, the current client and the sort controls used to scroll away, so by the
   time a clinician reached the foot of 54 procedures everything that narrows the list was
   off screen. The bar now holds directly under the section row. It is kept to its two
   existing lines: the library is what the screen is for, and the sticky part must not eat
   into it. */
.tp{--tp-stick:118px}
.tp-mainbar .tp-libbar{margin-bottom:8px}
.tp-mainbar .tp-toolbar{margin-bottom:0}
/* Only where there is room for it. Below 980 the search takes a line of its own and the
   filters collapse behind a button, so pinning the bar would hold 150px of controls over a
   short screen; there it scrolls with the page, as the filter rail already does. */
@media (min-width:981px){
  .tp-mainbar{position:sticky;top:var(--tp-stick);z-index:16;background:var(--tp-bg);
    margin:-8px 0 10px;padding:8px 0 6px;border-bottom:1px solid var(--tp-line)}
  /* Anything scrolled to in the library clears the bar rather than hiding behind it. */
  .tp-list>*{scroll-margin-top:calc(var(--tp-stick) + 96px)}
}
/* A pinned bar on a short window costs more than it gives, so there it lets go. */
@media (max-height:620px){.tp-mainbar{position:static}}

/* Reading down the library, the section row is not what the clinician is looking at, so it
   slides up behind the top bar and gives its height back to the list. Scrolling up is how
   anyone reaches for a tab, so the first movement upwards brings it straight back. It
   travels on a transform, which takes no space out of the flow: nothing below it jumps. */
.tp-sections{transition:transform .3s cubic-bezier(.2,.7,.2,1)}
@media (min-width:981px){
  .tp-mainbar{transition:top .3s cubic-bezier(.2,.7,.2,1)}
}

/* ---------------------------------------------------------------------------
   Everything above the library stays put, and gives back height instead.

   The section row used to slide away entirely on the way down, so the tabs and
   Edit plan left the screen exactly when a clinician had scrolled far enough to
   want them. They stay. What happens instead is that the bar under them draws
   itself in: the search and the filter button lose a few pixels of height and
   the padding closes up, which returns about twenty pixels to the list without
   anything leaving it. Scroll back to the top and it opens out again.
   ------------------------------------------------------------------------- */
.tp-libbar,.tp-libbar .tp-search input,.tp-libbar .tp-side__toggle,
.tp-toolbar,.tp-mainbar{transition:height .25s cubic-bezier(.2,.7,.2,1),
  min-height .25s cubic-bezier(.2,.7,.2,1),margin .25s cubic-bezier(.2,.7,.2,1),
  padding .25s cubic-bezier(.2,.7,.2,1),font-size .25s cubic-bezier(.2,.7,.2,1)}
@media (min-width:981px){
  .tp.is-down .tp-mainbar{padding-top:5px;padding-bottom:4px}
  .tp.is-down .tp-libbar{margin-bottom:5px}
  .tp.is-down .tp-libbar .tp-search input{height:33px}
  .tp.is-down .tp-libbar .tp-side__toggle{min-height:33px}
  .tp.is-down .tp-toolbar{font-size:12.5px}
  .tp.is-down .tp-toolbar .tp-sort select,
  .tp.is-down .tp-toolbar .tp-sort span{height:32px}
  .tp.is-down .tp-viewtoggle button{min-height:32px}
}
@media (prefers-reduced-motion:reduce){
  .tp-libbar,.tp-libbar .tp-search input,.tp-libbar .tp-side__toggle,
  .tp-toolbar,.tp-mainbar{transition:none}
}

/* Room under the count and sort row, so the first row of cards is not pressed
   against the controls above it. */
.tp-toolbar{margin-bottom:18px}
.tp-mainbar .tp-toolbar{margin-bottom:0}
.tp-mainbar{margin-bottom:18px!important}
@media (prefers-reduced-motion:reduce){.tp-sections,.tp-mainbar{transition:none}}

/* Pack editor carries the count now that the tray has gone, and says so when the pack has
   something in it. */
.tp-packbtn.is-ready{box-shadow:0 0 0 2px rgba(217,164,65,.38)}
.tp-packbtn.is-ready b{background:var(--tp-gold);color:#17302a}

/* Clearing the pack is destructive, so it does not look like Print. */
.tp-btn--del{color:#a3271a;border-color:#e8cdc8}
.tp-btn--del:hover{color:#7d1d13;border-color:#d9b3ad;background:#fdf3f1}

/* The account dot reports a live subscription. It breathes and sends one soft ring
   outwards; it does not flash. */
.tp-account__btn i.is-ok{background:var(--tp-green);animation:tpLive 2.8s ease-out infinite}
@keyframes tpLive{
  0%{box-shadow:0 0 0 0 rgba(63,157,109,.55);opacity:1}
  55%{box-shadow:0 0 0 7px rgba(63,157,109,0);opacity:.72}
  100%{box-shadow:0 0 0 0 rgba(63,157,109,0);opacity:1}
}
@media (prefers-reduced-motion:reduce){.tp-account__btn i.is-ok{animation:none}}
[hidden]{display:none!important}

/* login */
.tp-login{min-height:100vh;display:grid;place-items:center;align-content:center;gap:0;padding:32px 20px;background:linear-gradient(180deg,#eef3f0,#f7f9f8)}
.tp-login__card{width:min(440px,100%);background:#fff;border:1px solid var(--tp-line);border-radius:18px;padding:32px 30px;box-shadow:0 30px 60px -40px rgba(13,61,53,.4);display:grid;gap:14px}
.tp-login__card h1{font-size:26px;margin-top:6px}
.tp-login__card p{margin:0;color:var(--tp-muted);font-size:14.5px}
.tp-login__card form{display:grid;gap:12px}
.tp-login__card form p{margin:0}
.tp-login__card label{display:block;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--tp-leaf);font-weight:600;margin-bottom:6px}
.tp-login__card input[type=text],.tp-login__card input[type=password]{width:100%;font:inherit;padding:11px 12px;border:1px solid var(--tp-line);border-radius:10px;background:#fff}
.tp-login__card input[type=text]:focus,.tp-login__card input[type=password]:focus{outline:2px solid var(--tp-gold);border-color:var(--tp-gold)}
.tp-login__card .login-remember label{display:flex;align-items:center;gap:8px;text-transform:none;letter-spacing:0;font-size:13.5px;color:var(--tp-muted);font-weight:500}
.tp-login__card .login-submit input{width:100%;appearance:none;border:0;border-radius:10px;padding:12px;background:var(--tp-forest);color:#fff;font:600 15px var(--tp-font);cursor:pointer}
.tp-login__links{display:flex;justify-content:space-between;gap:12px;font-size:13.5px;flex-wrap:wrap}
.tp-login__note{font-size:12.5px!important;border-top:1px solid var(--tp-line);padding-top:12px}
.tp-login__foot{margin:18px 0 0;font-size:13px;color:var(--tp-muted)}

/* shell */
.tp{min-height:100vh;display:flex;flex-direction:column;padding-bottom:28px}
.tp-top{display:flex;align-items:center;justify-content:space-between;gap:20px;padding:10px 22px;background:#fff;border-bottom:1px solid var(--tp-line);position:sticky;top:0;z-index:20}
.tp-nav{display:flex;gap:4px;flex-wrap:wrap}
.tp-nav button,.tp-nav a{appearance:none;border:0;background:none;padding:10px 14px;font-size:13px;letter-spacing:.12em;text-transform:uppercase;color:var(--tp-muted);cursor:pointer;text-decoration:none;border-bottom:2px solid transparent;font-weight:600}
.tp-nav button.is-on{color:var(--tp-forest);border-bottom-color:var(--tp-forest)}
.tp-nav button:hover,.tp-nav a:hover{color:var(--tp-forest)}
.tp-sub{display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;padding:8px 22px;font-size:13px;color:var(--tp-muted);background:#fbfcfb;border-bottom:1px solid var(--tp-line)}
.tp-sub b{color:var(--tp-forest)}
.tp-view{padding:20px 22px}
/* No cap: an app screen uses the window it is given. The views carry their own gutters. */
.tp-panel{background:#fff;border:1px solid var(--tp-line);border-radius:14px;padding:22px 24px}
.tp-panel h2{font-size:22px;margin-bottom:8px}
.tp-panel p{color:var(--tp-muted);margin:0 0 12px}
.tp-home{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:24px;align-items:start}
.tp-home h1{font-size:28px;margin-bottom:10px}
.tp-home p{color:var(--tp-muted);max-width:60ch}
.tp-home__actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:16px}
.tp-stats{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:1fr 1fr;gap:10px}
.tp-stats li{background:#fff;border:1px solid var(--tp-line);border-radius:12px;padding:14px;font-size:12.5px;color:var(--tp-muted)}
.tp-stats b{display:block;font-size:26px;color:var(--tp-forest);line-height:1.1;margin-bottom:2px}
.tp-form{display:grid;gap:12px;max-width:480px}
.tp-form label{display:grid;gap:6px;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--tp-leaf);font-weight:600}
.tp-form input,.tp-form select{font:inherit;padding:10px 12px;border:1px solid var(--tp-line);border-radius:10px;background:#fff}
.tp-form button{justify-self:start}

/* work area */
.tp-work{display:grid;grid-template-columns:260px minmax(0,1fr);gap:18px;align-items:start}
.tp-side{background:#fff;border:1px solid var(--tp-line);border-radius:14px;padding:12px;position:sticky;top:64px;display:grid;gap:10px}
.tp-search{position:relative;display:block}
.tp-search input{width:100%;font:inherit;padding:10px 36px 10px 12px;border:1px solid var(--tp-line);border-radius:10px;background:var(--tp-bg)}
.tp-search i{position:absolute;right:12px;top:50%;width:14px;height:14px;border:2px solid var(--tp-muted);border-radius:50%;transform:translateY(-60%)}
.tp-search i::after{content:"";position:absolute;width:2px;height:7px;background:var(--tp-muted);right:-4px;bottom:-6px;transform:rotate(-45deg)}
.tp-filter{border-top:1px solid var(--tp-line);padding:10px 0 6px;display:grid;gap:6px}
.tp-filter__title{display:block;font:600 12px var(--tp-font);letter-spacing:.1em;text-transform:uppercase;color:var(--tp-leaf);padding:0 4px}
.tp-filter__title b{font-weight:600;color:var(--tp-muted);letter-spacing:0;text-transform:none}
.tp-filter__opts{display:grid;gap:2px}
.tp-filter__opts label{display:flex;align-items:center;gap:10px;font-size:14px;color:var(--tp-text);cursor:pointer;padding:7px 8px;border-radius:8px;min-height:36px}
.tp-filter__opts label:hover{background:var(--tp-bg)}
.tp-filter__opts label span{flex:1}
.tp-filter__opts label em{font-style:normal;font-size:12px;color:var(--tp-muted)}
.tp-filter__opts input{width:18px;height:18px;accent-color:var(--tp-forest);flex:none}
.tp-filter--client select{width:100%;font:inherit;padding:10px 12px;border:1px solid var(--tp-forest);border-radius:10px;background:#fff;color:var(--tp-text)}
.tp-side{max-height:calc(100vh - 80px);overflow:auto;scrollbar-width:thin}
.tp-main{min-width:0}
.tp-toolbar{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:10px}
.tp-tabs{display:inline-flex;border:1px solid var(--tp-line);border-radius:10px;overflow:hidden;background:#fff}
.tp-tabs button{appearance:none;border:0;background:none;padding:9px 14px;font:600 13px var(--tp-font);color:var(--tp-muted);cursor:pointer}
.tp-tabs button.is-on{background:var(--tp-forest);color:#fff}
.tp-toolbar__links{display:flex;gap:14px;font-size:13px}
.tp-list__head{display:grid;grid-template-columns:60px 30px 30px minmax(0,1fr) 150px 60px 170px 170px;gap:8px;padding:6px 10px;font-size:11.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--tp-muted)}
.tp-list{display:grid;gap:10px}
.tp-row{background:#fff;border:1px solid var(--tp-line);border-radius:12px;overflow:hidden;transition:border-color .2s,box-shadow .2s}
.tp-row.is-selected{border-color:var(--tp-forest);box-shadow:0 0 0 2px rgba(13,61,53,.12)}
.tp-row__head{display:grid;grid-template-columns:60px 30px 30px minmax(0,1fr) 150px 60px 170px 170px;gap:8px;align-items:center;padding:8px 10px;border-bottom:1px solid var(--tp-line);font-size:13.5px}
.tp-row__head i{width:24px;height:24px;display:grid;place-items:center;color:var(--tp-muted);font-style:normal;font-size:16px}
.tp-row__head button{appearance:none;border:0;background:none;width:26px;height:26px;border-radius:6px;display:grid;place-items:center;color:var(--tp-muted);cursor:pointer;font-size:15px}
.tp-row__head button:hover{background:var(--tp-bg);color:var(--tp-forest)}
.tp-row__head button.is-on{color:var(--tp-gold)}
.tp-row__check{display:grid;place-items:center;height:32px;border-radius:8px;background:var(--tp-bg);cursor:pointer}
.tp-row__check input{width:20px;height:20px;accent-color:var(--tp-forest);cursor:pointer}
.tp-row__check input:disabled{opacity:.35;cursor:not-allowed}
.tp-row__clients{display:flex;flex-wrap:wrap;gap:4px;align-items:center}
.tp-row__clients b{font-size:11.5px;padding:3px 8px;border-radius:999px;background:#e8f1ec;color:var(--tp-forest);font-weight:600}
.tp-row__clients:empty{display:none}
.tp-toolbar__count{font-size:13.5px;color:var(--tp-muted)}.tp-toolbar__count b{color:var(--tp-forest);font-size:15px}
.tp-form--row{grid-template-columns:1fr 160px auto;align-items:end;max-width:640px}
.tp-table{width:100%;border-collapse:collapse;font-size:14px;margin-top:16px}
.tp-table th,.tp-table td{border-bottom:1px solid var(--tp-line);padding:10px 8px;text-align:left}
.tp-table th{font-size:11.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--tp-leaf)}
.tp-table tr.is-on td{background:#f2f7f4}
.tp-table__act{text-align:right;white-space:nowrap}
/* On a phone the client list was a six-column table 494px wide inside a 390px screen: it
   pushed the whole page 141px sideways, because nothing above it scrolls. A table that
   cannot fit is not a table on that screen, so each client becomes a card and each cell
   carries the column heading it lost. The reference and the actions keep the full width;
   everything between is a labelled line. */
@media (max-width:640px){
  .tp-table,.tp-table tbody,.tp-table tr,.tp-table td{display:block;width:auto}
  .tp-table{margin-top:14px}
  .tp-table thead{display:none}
  .tp-table tr{border:1px solid var(--tp-line);border-radius:12px;padding:13px 15px;margin:0 0 10px;background:#fff}
  .tp-table tr.is-on{border-color:var(--tp-forest);box-shadow:inset 0 0 0 1px var(--tp-forest)}
  .tp-table tr.is-on td{background:none}
  .tp-table td{border:0;padding:5px 0;display:grid;grid-template-columns:minmax(0,13ch) minmax(0,1fr);gap:12px;align-items:baseline}
  .tp-table td::before{content:attr(data-l);font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--tp-muted);line-height:1.5}
  .tp-table td:not([data-l]){grid-template-columns:minmax(0,1fr)}
  .tp-table td:not([data-l])::before{content:none}
  .tp-table td:first-child{padding:0 0 10px;margin-bottom:7px;border-bottom:1px solid var(--tp-line);font-size:15px}
  .tp-table td.tp-table__act{display:flex;flex-wrap:wrap;align-items:center;gap:16px;padding-top:12px;text-align:left;white-space:normal}
  .tp-table small{display:inline}
}

/* v22 lives at the foot of this sheet, because several of its rules override rules
   written further up. See the block after the registration styles. */


.tp-btn--small{padding:6px 12px;font-size:12.5px;border-radius:8px}
.tp-gloss{display:grid;grid-template-columns:180px 1fr;gap:6px 14px;font-size:14px}
.tp-gloss dt{font-weight:600;color:var(--tp-text)}.tp-gloss dd{margin:0;color:var(--tp-muted)}
.tp-pack__contents{margin:10px 0 0;color:#5a6f68;font-size:13px}
.tp-pack__cover h3{font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--tp-leaf);margin-top:14px}
.tp-pack__principles{margin:0;padding-left:20px;font-size:13.5px;display:grid;gap:3px;columns:2}
.tp-row__title{font-weight:600;color:var(--tp-text);cursor:pointer}
.tp-row__meta{color:var(--tp-muted);font-size:13px}
.tp-row__strip{display:flex;gap:14px;padding:10px;align-items:center;overflow:visible}
/* What the procedure is, beside the picture of it. */
.tp-row__summary{margin:0;flex:1 1 auto;min-width:0;font-size:13.5px;line-height:1.55;color:var(--tp-text);
  cursor:pointer;display:grid;gap:5px;align-content:center}
/* The detail line reads as a label on the summary, not as more of the sentence, so it
   sits on the same tinted ground the Sort control uses and hugs its own text. */
.tp-row__summary em{justify-self:start;display:inline-block;font-style:normal;font-size:11.5px;
  letter-spacing:.06em;text-transform:uppercase;color:var(--tp-muted);
  padding:4px 11px;border-radius:999px;background:#f2f6f4;border:1px solid var(--tp-line)}
@media (max-width:980px){.tp-row__strip{align-items:flex-start}.tp-row__summary{font-size:13px}}
.tp-thumb{width:82px;height:82px;flex:none;border:1px solid var(--tp-line);border-radius:8px;background:#fff;display:grid;place-items:center;overflow:hidden}
.tp-thumb img{width:100%;height:100%;object-fit:contain;padding:6px}
.tp-thumb--info{color:var(--tp-forest);font:italic 700 34px Georgia,serif;cursor:pointer}
.tp-thumb--more{background:#dfe4ea;color:#4f5c73;font-weight:700;font-size:18px;cursor:pointer}
.tp-thumb--step{font-size:11px;padding:8px;line-height:1.3;color:var(--tp-muted);text-align:left;align-content:start;display:block}
.tp-thumb--step b{display:block;color:var(--tp-forest);font-size:12px;margin-bottom:2px}
.tp-empty{color:var(--tp-muted);padding:20px}
/* Verified. The seal everyone already knows, in the site's green rather than a
   social network's blue, because this is a clinical claim and not a celebrity one. */
.tp-badge{display:inline-grid;place-items:center;width:16px;height:16px;margin-left:6px;
  vertical-align:-3px;line-height:0}
.tp-badge svg{display:block;width:16px;height:16px;overflow:visible}
.tp-badge__seal{fill:var(--tp-leaf)}
.tp-badge__tick{fill:none;stroke:#fff;stroke-width:2.6;stroke-linecap:round;stroke-linejoin:round}

/* equipment */
.tp-equip{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:14px;margin-top:8px}
.tp-equip__item{border:1px solid var(--tp-line);border-radius:12px;padding:12px;display:grid;gap:6px;background:#fff}
.tp-equip__img{aspect-ratio:1/1;border-radius:8px;background:var(--tp-bg);display:grid;place-items:center;overflow:hidden;color:var(--tp-muted);font-size:12px}
.tp-equip__img img{width:100%;height:100%;object-fit:contain;padding:8px}
.tp-equip__item h3{font-size:15px}
.tp-equip__item p{font-size:12.5px;color:var(--tp-muted);margin:0}
.tp-equip__actions{display:flex;justify-content:space-between;gap:8px;font-size:12.5px;flex-wrap:wrap}

/* help */
.tp-help ol,.tp-help ul{padding-left:20px;color:var(--tp-text);display:grid;gap:6px}
.tp-help h3{font-size:16px;margin:16px 0 8px}

/* tray */

/* modal (plan detail) */
.tp-modal{position:fixed;inset:0;background:rgba(11,31,25,.55);z-index:40;display:grid;place-items:center;padding:20px}
.tp-modal__card{background:#fff;border-radius:16px;width:min(860px,100%);max-height:88vh;overflow:auto;padding:26px 28px;position:relative}
/* The close button is written before the body it sits over, so without a stacking order
   of its own the gallery painted straight over it and the only way out of the procedure
   was the Escape key. It stays on top, and carries enough of a ground to be legible
   against a photograph or a film frame. */
.tp-modal__close{position:absolute;top:12px;right:12px;z-index:6;appearance:none;border:1px solid var(--tp-line);
  background:rgba(255,255,255,.94);color:var(--tp-forest);width:34px;height:34px;border-radius:50%;cursor:pointer;
  box-shadow:0 4px 14px -6px rgba(13,61,53,.5);backdrop-filter:blur(3px);transition:background .2s,border-color .2s}
.tp-modal__close:hover{background:#fff;border-color:var(--tp-forest)}

/* plan document (modal + pack) */
.tp-doc{display:grid;gap:14px}
.tp-doc__head{display:grid;grid-template-columns:120px minmax(0,1fr);gap:16px;align-items:start}
.tp-doc__head img{width:120px;height:120px;object-fit:contain;border:1px solid var(--tp-line);border-radius:10px;background:#fff}
.tp-doc__head h2{font-size:22px;margin:4px 0 6px}
.tp-doc__chips{display:flex;flex-wrap:wrap;gap:6px}
.tp-doc__chips span{font-size:12px;padding:4px 9px;border-radius:999px;background:var(--tp-bg);border:1px solid var(--tp-line)}
.tp-doc__summary{color:var(--tp-muted);margin:6px 0 0}
.tp-doc section{border-top:1px solid var(--tp-line);padding-top:10px}
.tp-doc h3{font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--tp-leaf);margin-bottom:6px}
.tp-doc ol,.tp-doc ul{margin:0;padding-left:20px;display:grid;gap:5px;font-size:14px}
.tp-doc ol{list-style:decimal}.tp-doc ul{list-style:disc}
.tp-doc ol li::marker{color:var(--tp-gold);font-weight:700}
.tp-doc table{width:100%;border-collapse:collapse;font-size:13px}
.tp-doc th,.tp-doc td{border:1px solid var(--tp-line);padding:7px 9px;text-align:left;height:34px}
.tp-doc th{background:var(--tp-bg)}
.tp-doc__evidence li{font-size:12.5px;color:var(--tp-muted)}
.tp-doc__note{font-size:12.5px;color:var(--tp-muted);border-top:1px solid var(--tp-line);padding-top:8px}
.tp-pack{padding:20px 22px;display:grid;gap:22px}
.tp-pack__section{display:flex;align-items:center;gap:10px;margin:34px 0 10px;padding-bottom:8px;border-bottom:2px solid var(--tp-forest,#0d3d35);font-size:clamp(17px,2vw,22px);line-height:1.1;letter-spacing:-.01em;color:var(--tp-forest,#0d3d35)}
.tp-pack__section span{flex:1}
.tp-pack__section b{flex:none;background:var(--tp-forest,#0d3d35);color:#fff;border-radius:999px;padding:2px 10px;font-size:12px;font-weight:700}
.tp-pack__section:first-of-type{margin-top:18px}
@media print{.tp-pack__section{break-after:avoid;page-break-after:avoid;margin-top:18px}}
.tp-pack__cover{background:#fff;border:1px solid var(--tp-line);border-radius:14px;padding:22px 24px;display:grid;gap:8px}
.tp-pack__cover h1{font-size:24px}
.tp-pack__cover dl{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin:8px 0 0}
.tp-pack__cover dt{font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--tp-leaf)}
.tp-pack__cover dd{margin:0;font-weight:600}
.tp-pack__plan{background:#fff;border:1px solid var(--tp-line);border-radius:14px;padding:22px 24px}
.tp-pack__bar{display:flex;gap:10px;justify-content:flex-end}

@media (max-width:980px){.tp-work{grid-template-columns:1fr}.tp-side{position:static;max-height:none}.tp-home{grid-template-columns:1fr}.tp-list__head{display:none}.tp-row__head{grid-template-columns:60px 30px 30px minmax(0,1fr)}.tp-row__head .tp-row__meta{display:none}.tp-row__clients,.tp-row__extra{grid-column:1/-1}.tp-pack__cover dl{grid-template-columns:1fr 1fr}.tp-form--row{grid-template-columns:1fr}.tp-gloss{grid-template-columns:1fr}.tp-pack__principles{columns:1}}
@media (max-width:600px){.tp-top{padding:8px 12px}.tp-nav button,.tp-nav a{padding:8px 8px;font-size:11.5px}.tp-view{padding:12px}.tp-doc__head{grid-template-columns:80px 1fr}.tp-doc__head img{width:80px;height:80px}}
@media print{body.tp-body{background:#fff}.tp-top,.tp-sub,.tp-view,.tp-modal,.tp-pack__bar{display:none!important}.tp{padding:0}.tp-pack{display:grid!important;padding:0}.tp-pack__plan,.tp-pack__cover{border:0;border-radius:0;padding:0 0 18px;break-inside:avoid}.tp-pack__plan{break-before:page}.tp-doc__head img{-webkit-print-color-adjust:exact;print-color-adjust:exact}}

/* additional information column + note row */
.tp-row__extra{min-width:0}
.tp-row__extra small{color:var(--tp-muted);font-size:12px}
.tp-extra{appearance:none;width:100%;text-align:left;border:1px dashed var(--tp-line);border-radius:8px;background:#fff;color:var(--tp-leaf);font:inherit;font-size:12.5px;padding:6px 9px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tp-extra.has-text{border-style:solid;border-color:var(--tp-gold);background:#fff9ec;color:var(--tp-text)}
.tp-extra:hover{border-color:var(--tp-forest)}
.tp-row__note{border-top:1px solid var(--tp-line);padding:10px 12px 12px;background:#fffdf7;display:grid;gap:8px}
.tp-row__note label{display:grid;gap:6px;font-size:12.5px;color:var(--tp-forest);font-weight:600}
/* "Demonstrated to" is the one single-line field among these, and it was never added to
   this rule: it rendered with the browser's own inset border and 13px default face, 22px
   tall, in the middle of a designed form. */
.tp-row__note textarea,.tp-doc--edit textarea,.tp-edit__notes textarea,.tp-edit__notes input{width:100%;font:inherit;font-size:14px;line-height:1.5;padding:9px 11px;border:1px solid var(--tp-line);border-radius:10px;background:#fff;color:var(--tp-text);resize:vertical}
.tp-row__note textarea:focus,.tp-doc--edit textarea:focus,.tp-doc--edit input:focus,.tp-edit__notes textarea:focus,.tp-edit__notes input:focus{outline:2px solid var(--tp-gold);border-color:var(--tp-gold)}
.tp-edit__notes input{resize:none}
.tp-row__note-actions{display:flex;gap:12px;align-items:center}
.tp-code{font:600 13px ui-monospace,SFMono-Regular,Menlo,monospace;background:#e8f1ec;color:var(--tp-forest);padding:3px 8px;border-radius:6px;letter-spacing:.06em}
.tp-table small{color:var(--tp-muted);font-size:12px;display:block}

/* pack editor */
.tp-pack__bar--top{justify-content:flex-start;align-items:center;flex-wrap:wrap;position:sticky;top:58px;z-index:10;background:var(--tp-bg);padding:8px 0}
.tp-pack__spacer{flex:1}
.tp-pack__modes{display:inline-flex;border:1px solid var(--tp-line);border-radius:10px;overflow:hidden;background:#fff}
.tp-pack__modes button{appearance:none;border:0;background:none;padding:9px 16px;font:600 13px var(--tp-font);color:var(--tp-muted);cursor:pointer}
.tp-pack__modes button.is-on{background:var(--tp-forest);color:#fff}
.tp-pack__cover--edit{border-color:var(--tp-gold)}
.tp-edit__notes{display:grid;gap:6px;font-size:13px;font-weight:600;color:var(--tp-forest);margin-top:10px}
.tp-edit__hint{font-size:12.5px;color:var(--tp-muted);margin:2px 0 6px}
.tp-doc--edit h3 .tp-linkbtn{font-size:11px;letter-spacing:0;text-transform:none;font-weight:500;margin-left:8px}
.tp-edit__grid{display:grid;grid-template-columns:1fr 1fr;gap:10px 14px}
.tp-edit__grid label{display:grid;gap:5px;font-size:12.5px;color:var(--tp-forest);font-weight:600}
.tp-edit__grid input{font:inherit;font-size:14px;padding:9px 11px;border:1px solid var(--tp-line);border-radius:10px;background:#fff;color:var(--tp-text)}
.tp-doc__extra{background:#fff9ec;border:1px solid #f1dfb5!important;border-radius:10px;padding:10px 12px!important}
.tp-doc__extra p{margin:0;font-size:14px}
.tp-pack__notes{margin:0;font-size:14px;background:#fff9ec;border:1px solid #f1dfb5;border-radius:10px;padding:10px 12px}
.tp-pack__code{margin:4px 0 0;font-size:13.5px;color:var(--tp-muted)}
.tp-pack__code b{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--tp-forest);letter-spacing:.06em}

/* saved panel */
.tp-saved{display:grid;gap:12px}
.tp-saved h2{font-size:22px}
.tp-saved__code{font:700 34px/1.1 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.12em;color:var(--tp-forest);background:#e8f1ec;border:1px dashed var(--tp-leaf);border-radius:12px;padding:16px 20px;text-align:center}
.tp-saved p{margin:0;color:var(--tp-muted);font-size:14px}
.tp-saved__actions{display:flex;flex-wrap:wrap;gap:10px}
.tp-saved__actions .tp-btn{text-decoration:none;display:inline-flex;align-items:center}
.tp-saved__note{font-size:12.5px!important;border-top:1px solid var(--tp-line);padding-top:10px}

/* shared-plan viewer */
.tp--viewer{padding-bottom:40px}
.tp-nav__code{font-size:13px;color:var(--tp-muted);padding:10px 4px}
.tp-nav__code b{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--tp-forest);letter-spacing:.06em}
.tp-nav .tp-btn--small{align-self:center}
.tp-viewer__foot{max-width:900px;margin:0 22px;font-size:13px;color:var(--tp-muted)}

/* login page: sign in + plan code side by side */
.tp-login__grid{display:grid;grid-template-columns:minmax(0,440px) minmax(0,400px);gap:20px;align-items:start;justify-content:center;width:100%}
.tp-login__card--code h2{font-size:22px}
.tp-codeform{display:grid;gap:6px}
.tp-codeform label{font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--tp-leaf);font-weight:600}
.tp-codeform div{display:flex;gap:8px}
.tp-codeform input{flex:1;min-width:0;font:600 17px ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.1em;text-transform:uppercase;padding:10px 12px;border:1px solid var(--tp-line);border-radius:10px}
.tp-codeform input:focus{outline:2px solid var(--tp-gold);border-color:var(--tp-gold)}
.tp-codeform__err{color:#b3261e!important;font-weight:600}
@media (max-width:980px){.tp-login__grid{grid-template-columns:1fr;max-width:480px}.tp-edit__grid{grid-template-columns:1fr}.tp-pack__bar--top{top:0}}
@media print{.tp-viewer__foot,.tp-nav{display:none!important}.tp-doc__extra,.tp-pack__notes{-webkit-print-color-adjust:exact;print-color-adjust:exact}}

/* v2.1: document control line, acknowledgement, pilot offer */
.tp-doc__control{font-size:11.5px;color:var(--tp-muted);margin:0;padding-top:6px;border-top:1px dashed var(--tp-line);letter-spacing:.01em}
.tp-ack{padding:0 22px 10px}
.tp-ack__card{background:#fff;border:1px solid var(--tp-line);border-radius:14px;padding:22px 24px;max-width:900px;display:grid;gap:8px}
.tp-ack__card h2{font-size:20px}
.tp-ack__card p{margin:0;color:var(--tp-muted);font-size:14px}
.tp-ack__form{display:grid;grid-template-columns:1fr 1fr 1fr auto;gap:10px;align-items:end;margin-top:6px}
.tp-ack__form label{display:grid;gap:5px;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--tp-leaf);font-weight:600}
.tp-ack__form input{font:inherit;padding:10px 12px;border:1px solid var(--tp-line);border-radius:10px;background:#fff;color:var(--tp-text)}
.tp-ack__form input:focus{outline:2px solid var(--tp-gold);border-color:var(--tp-gold)}
.tp-ack__form [data-ack-msg]{grid-column:1/-1}
.tp-ack__done{margin:0;padding:12px 14px;background:#e8f1ec;border-radius:10px;color:var(--tp-forest);font-weight:600;font-size:14px}
.tp-login__pilot{display:grid;gap:4px;font-size:13.5px;background:#fff9ec;border:1px solid #f1dfb5;border-radius:12px;padding:12px 14px;color:var(--tp-text)}
.tp-login__pilot b{color:var(--tp-forest)}
.tp-login__pilot a{font-weight:600}
@media (max-width:980px){.tp-ack__form{grid-template-columns:1fr}}
@media print{.tp-ack{display:none!important}.tp-doc__control{-webkit-print-color-adjust:exact;print-color-adjust:exact}}

/* v3: account pages (sign in, plan code, create account, verification, set password) */
.tp-auth{min-height:100vh;display:grid;align-content:start;justify-items:center;gap:18px;padding:40px 20px 40px;background:#f4f6f5}
.tp-auth__logo{display:inline-flex;align-items:center;gap:10px;text-decoration:none;color:var(--tp-forest);font-size:26px;font-weight:700;letter-spacing:-.01em;margin-top:8px}
.tp-auth__logo img{width:36px;height:auto}
.tp-auth__logo b{color:var(--tp-leaf);font-weight:700}
.tp-auth__links{display:flex;gap:22px;font-size:15px}
.tp-auth__links a{color:var(--tp-leaf);text-decoration:none}
.tp-auth__links a:hover{text-decoration:underline}
.tp-auth__card{width:min(720px,100%);background:#fff;border:1px solid var(--tp-line);border-radius:6px;padding:34px 36px 30px;box-shadow:0 12px 30px -20px rgba(13,61,53,.35);display:grid;gap:14px;margin-top:6px}
.tp-auth__card--wide{width:min(980px,100%)}
.tp-auth__card h1{font-size:30px;font-weight:700;letter-spacing:-.01em}
.tp-auth__intro{margin:0;color:var(--tp-muted);font-size:15px}
.tp-auth__tabs{display:flex;gap:0;border-bottom:1px solid var(--tp-line);margin:-6px 0 6px}
.tp-auth__tabs a{padding:10px 14px 12px;color:var(--tp-muted);text-decoration:none;font-weight:600;font-size:14px;border-bottom:2px solid transparent;margin-bottom:-1px}
.tp-auth__tabs a[aria-selected=true]{color:var(--tp-forest);border-bottom-color:var(--tp-forest)}
.tp-auth__form{display:grid;gap:14px}
.tp-auth__form label{display:grid;gap:6px;font-size:15px;color:var(--tp-text)}
.tp-auth__lbl{display:flex;justify-content:space-between;align-items:baseline}
.tp-auth__lbl a{font-size:14px;color:var(--tp-leaf)}
.tp-auth__form input:not([type=checkbox]),.tp-auth__form select{width:100%;font:inherit;font-size:16px;padding:11px 12px;border:1px solid #cfd8d4;border-radius:4px;background:#fff;color:var(--tp-text)}
.tp-auth__form input:focus,.tp-auth__form select:focus{outline:2px solid var(--tp-gold);border-color:var(--tp-gold)}
.tp-auth__row{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.tp-auth__remember{display:flex!important;align-items:center;gap:10px;background:#f4f6f5;border-radius:4px;padding:12px 14px;font-size:15px}
.tp-auth__remember input{width:18px;height:18px;accent-color:var(--tp-forest)}
.tp-auth__btn{appearance:none;border:0;border-radius:4px;padding:12px 22px;background:var(--tp-forest);color:#fff;font:600 15px var(--tp-font);cursor:pointer;justify-self:start;min-width:130px}
.tp-auth__btn:hover{background:#0a3029}
.tp-auth__btn:disabled{opacity:.6;cursor:wait}
.tp-auth__btn--ghost{background:#fff;color:var(--tp-forest);border:1px solid var(--tp-forest)}
.tp-auth__small{margin:0;font-size:13.5px;color:var(--tp-muted)}
.tp-auth__hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.tp-auth__ok{margin:0;padding:10px 12px;background:#e8f1ec;border-radius:6px;color:var(--tp-forest);font-size:14px}
.tp-auth__foot{font-size:13px;color:var(--tp-muted);margin:6px 0 0;text-align:center}
.tp-done{display:grid;gap:12px;justify-items:start;padding-bottom:22px;border-bottom:1px solid var(--tp-line)}
.tp-done__mail{width:56px;height:56px;border-radius:50%;background:#e8f1ec;color:var(--tp-forest);display:grid;place-items:center}
.tp-done__mail svg{width:30px;height:30px}
.tp-done__resend{display:flex;flex-wrap:wrap;gap:10px;align-items:center;width:100%}
.tp-done__resend input{flex:1;min-width:220px;font:inherit;font-size:15px;padding:10px 12px;border:1px solid #cfd8d4;border-radius:4px}
.tp-days{display:grid;grid-template-columns:repeat(3,1fr);gap:0;margin-top:8px}
.tp-day{padding:22px 22px 18px;border-left:1px solid var(--tp-line);display:grid;gap:8px;align-content:start}
.tp-day:first-child{border-left:0;padding-left:0}
.tp-day__label{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--tp-gold);font-weight:700}
.tp-day h2{font-size:17px;line-height:1.3}
.tp-day ul{margin:0;padding-left:18px;color:var(--tp-muted);font-size:14px;display:grid;gap:5px;list-style:disc}
.tp-day li::marker{color:var(--tp-leaf)}
@media (max-width:820px){.tp-days{grid-template-columns:1fr}.tp-day{border-left:0;padding-left:0;border-top:1px solid var(--tp-line);padding-top:18px}.tp-day:first-child{border-top:0}.tp-auth__row{grid-template-columns:1fr}.tp-auth__card{padding:26px 22px}}

/* v4: library as a card grid with animated scenes, sort and view toggle, tabbed detail */
.tp-scene{display:block;width:100%;height:100%;background:radial-gradient(120% 90% at 50% 100%,#1c4a41 0,#0d3d35 50%,#0b1f19 100%)}
.tp-scene .skin{fill:url(#gSkin)}.tp-scene .body{fill:url(#gBody)}
.tp-scene .limb{fill:none;stroke:#cfe3d8;stroke-width:7;stroke-linecap:round;stroke-linejoin:round}
.tp-scene .gsh{fill:rgba(0,0,0,.35)}.tp-scene .floor{fill:url(#gFloor)}
.tp-scene .gold{fill:url(#gGold)}.tp-scene .red{fill:#e0524a}
.tp-scene .strap{fill:none;stroke:url(#gGold);stroke-width:4;stroke-linecap:round}
.tp-scene .sling{fill:none;stroke:url(#gGold);stroke-width:5;stroke-linecap:round}
.tp-scene .sling--1{stroke:#9fd3b6}.tp-scene .sling--2{stroke:#f3cf7f}
.tp-scene .frame{fill:none;stroke:url(#gGold);stroke-width:5;stroke-linecap:round;stroke-linejoin:round}
.tp-scene .card{fill:rgba(255,255,255,.14);stroke:rgba(255,255,255,.35);stroke-width:1}
.tp-scene .rail{fill:url(#gRail)}
.tp-scene .bt{font:700 15px var(--tp-font);fill:#0b1f19}
.tp-scene .s{opacity:0;animation:tpFrames 7.5s infinite}
.tp-scene .s1{animation-delay:-5s}.tp-scene .s2{animation-delay:-2.5s}
@keyframes tpFrames{0%{opacity:0}4%,30%{opacity:1}34%,100%{opacity:0}}
@media (prefers-reduced-motion:reduce){.tp-scene .s{animation:none;opacity:0}.tp-scene .s2{opacity:1}}

.tp-list--grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px}
.tp-card{background:#fff;border:1px solid var(--tp-line);border-radius:14px;overflow:hidden;display:flex;flex-direction:column;transition:transform .25s,box-shadow .25s,border-color .2s;position:relative}
.tp-card:hover{transform:translateY(-3px);box-shadow:0 22px 40px -30px rgba(13,61,53,.5);border-color:#b9cfc5}
.tp-card.is-selected{border-color:var(--tp-forest);box-shadow:0 0 0 2px rgba(13,61,53,.12)}
.tp-card__scene{position:relative;aspect-ratio:16/10;cursor:pointer;overflow:hidden}
.tp-card__badge{position:absolute;left:10px;top:10px;font-size:11px;letter-spacing:.06em;text-transform:uppercase;font-weight:700;color:#0b1f19;background:var(--tp-gold);padding:4px 9px;border-radius:999px}
.tp-card.is-selected .tp-card__badge{background:#9fd3b6}
.tp-card__fav{position:absolute;right:8px;top:6px;appearance:none;border:0;background:rgba(255,255,255,.14);color:#fff;width:32px;height:32px;border-radius:50%;font-size:17px;cursor:pointer;display:grid;place-items:center}
.tp-card__fav.is-on{color:var(--tp-gold);background:rgba(255,255,255,.22)}
.tp-card__body{padding:12px 14px 8px;display:grid;gap:6px;flex:1;align-content:start}
.tp-card__group{font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--tp-leaf);font-weight:600}
.tp-card h3{font-size:15.5px;line-height:1.3;cursor:pointer}
.tp-card h3 mark,.tp-row__title mark{background:#fff3c4;color:inherit;border-radius:3px;padding:0 2px}
.tp-card__body p{margin:0;font-size:13px;color:var(--tp-muted);line-height:1.45}
.tp-card__eq{display:flex;gap:6px;align-items:center;min-height:30px}
.tp-card__eq img{width:30px;height:30px;object-fit:contain;border:1px solid var(--tp-line);border-radius:6px;background:#fff;padding:2px}
.tp-card__eq i{width:30px;height:30px;border:1px dashed var(--tp-line);border-radius:6px;display:grid;place-items:center;font:600 10px var(--tp-font);color:var(--tp-muted);font-style:normal}
.tp-card__eq--none{width:auto!important;padding:0 8px;letter-spacing:.04em}
.tp-card__clients{display:flex;flex-wrap:wrap;gap:4px}
.tp-card__clients b{font-size:11px;padding:2px 8px;border-radius:999px;background:#e8f1ec;color:var(--tp-forest);font-weight:600}
.tp-card__extra{background:#fff9ec;border:1px solid #f1dfb5;border-radius:8px;padding:6px 8px!important;color:var(--tp-text)!important;font-size:12.5px!important}
.tp-card__foot{display:flex;gap:12px;align-items:center;padding:8px 14px 12px;border-top:1px solid var(--tp-line)}
.tp-card__add{appearance:none;border:1px solid var(--tp-forest);background:#fff;color:var(--tp-forest);border-radius:999px;padding:8px 14px;font:600 13px var(--tp-font);cursor:pointer;transition:background .2s,color .2s}
.tp-card__add:hover{background:#e8f1ec}
.tp-card__add.is-on{background:var(--tp-forest);color:#fff}
.tp-card__add:disabled{opacity:.45;cursor:not-allowed}
.tp-card .tp-row__note{border-top:1px solid var(--tp-line)}
.tp-thumb--scene{width:132px}.tp-thumb--scene .tp-scene{border-radius:7px}


.tp-toolbar__tools{display:flex;gap:14px;align-items:center;font-size:13px}
.tp-sort{display:inline-flex;gap:6px;align-items:center;color:var(--tp-muted)}
.tp-sort select{font:inherit;font-size:13px;padding:6px 8px;border:1px solid var(--tp-line);border-radius:8px;background:#fff}
.tp-viewtoggle{display:inline-flex;border:1px solid var(--tp-line);border-radius:8px;overflow:hidden;background:#fff}
.tp-viewtoggle button{appearance:none;border:0;background:none;width:34px;height:32px;font-size:16px;color:var(--tp-muted);cursor:pointer}
.tp-viewtoggle button.is-on{background:var(--tp-forest);color:#fff}

.tp-doctabs{display:flex;flex-wrap:wrap;gap:4px;border-bottom:1px solid var(--tp-line);padding-bottom:8px}
.tp-doctabs button{appearance:none;border:1px solid var(--tp-line);background:#fff;border-radius:999px;padding:6px 12px;font:600 12.5px var(--tp-font);color:var(--tp-muted);cursor:pointer}
.tp-doctabs button.is-on{background:var(--tp-forest);color:#fff;border-color:var(--tp-forest)}
.tp-modal__scene{aspect-ratio:16/7;border-radius:12px;overflow:hidden;margin-bottom:14px}
.tp-modal__scene .tp-scene{height:100%}

/* v5: Optimised Handling brand, uploaded media on cards */
.tp-logo{gap:9px;letter-spacing:0;font-size:15px;text-transform:none}
.tp-logo img{width:30px;height:auto;display:block}
.tp-logo span{width:auto;height:auto;border-radius:0;background:none;color:var(--tp-forest);display:grid;line-height:1.05;font-size:15px;letter-spacing:-.01em}
.tp-logo span b{font-weight:700}
.tp-logo span small{font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--tp-muted);font-weight:600;margin-top:2px}
.tp-auth__logo span{display:grid;line-height:1.05}
.tp-auth__logo span small{font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--tp-muted);font-weight:600;margin-top:3px}
.tp-scene--video,.tp-scene--img{object-fit:cover;background:#0b1f19}
.tp-scene--embed{border:0;background:#0b1f19}
.tp-card__play{position:absolute;right:10px;bottom:10px;width:30px;height:30px;border-radius:50%;background:var(--tp-gold);color:#0b1f19;display:grid;place-items:center;font-size:12px;padding-left:2px}
.tp-modal__scene:has(.tp-scene--embed),.tp-modal__scene:has(.tp-scene--video){aspect-ratio:16/9}

/* v6: pricing, account and subscription, custom procedures */
.tp-pricing{width:min(1040px,100%);display:grid;gap:26px;margin-top:6px}
.tp-pricing__head{text-align:center;display:grid;gap:12px;justify-items:center}
.tp-pricing__head h1{font-size:34px;font-weight:700;letter-spacing:-.01em;margin:0}
.tp-pricing__head .tp-auth__intro{max-width:640px}
.tp-pricing__toggle{display:inline-flex;background:#fff;border:1px solid var(--tp-line);border-radius:999px;padding:4px;margin-top:4px}
.tp-pricing__toggle button{appearance:none;border:0;background:transparent;border-radius:999px;padding:9px 18px;font:600 14px var(--tp-font);color:var(--tp-muted);cursor:pointer;display:inline-flex;gap:8px;align-items:center}
.tp-pricing__toggle button small{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;background:#e8f1ec;color:var(--tp-forest);border-radius:999px;padding:3px 8px}
.tp-pricing__toggle button[aria-pressed=true]{background:var(--tp-forest);color:#fff}
.tp-pricing__toggle button[aria-pressed=true] small{background:rgba(255,255,255,.18);color:#fff}
.tp-pricing__grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px}
@media (max-width:1180px){.tp-pricing__grid{grid-template-columns:1fr 1fr}.tp-price--enterprise{grid-column:1/-1}}
.tp-price{background:#fff;border:1px solid var(--tp-line);border-radius:8px;padding:30px 32px 26px;display:grid;gap:14px;align-content:start;box-shadow:0 12px 30px -20px rgba(13,61,53,.35)}
.tp-price--standard{border-color:var(--tp-forest);border-width:2px}
.tp-price__amount{display:grid}
.tp-price__amount span{display:grid;gap:2px}
.tp-price__amount b{font-size:44px;line-height:1;font-weight:700;letter-spacing:-.02em;color:var(--tp-forest)}
.tp-price__amount small{font-size:14px;color:var(--tp-muted)}
.tp-price__lead{margin:0;font-size:15px;color:var(--tp-text)}
.tp-price__list{list-style:none;margin:0;padding:0;display:grid;gap:9px;font-size:15px}
.tp-price__list li{padding-left:26px;position:relative}
.tp-price__list li::before{content:"";position:absolute;left:0;top:4px;width:16px;height:16px;border-radius:50%;background:#e8f1ec url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 8.5l2.5 2.5L12 5.5' fill='none' stroke='%230d3d35' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/12px no-repeat}
.tp-price .tp-auth__btn{margin-top:6px;width:100%;text-align:center;text-decoration:none}
.tp-price__a,.tp-price__amount .tp-price__a{display:none}
.tp-pricing.is-annual .tp-price__a{display:inline}.tp-pricing.is-annual .tp-price__amount .tp-price__a{display:grid}
.tp-pricing.is-annual .tp-price__m,.tp-pricing.is-annual .tp-price__amount .tp-price__m{display:none}
/* The questions open one at a time. Native <details>, so it works with a keyboard and
   without JavaScript; the open one is animated where the browser can animate to auto. */
.tp-pricing__faqhead{width:min(820px,100%);margin:30px auto 0;display:flex;align-items:center;gap:12px;
  font-size:12px;font-weight:700;letter-spacing:.2em;text-transform:uppercase;color:var(--tp-leaf)}
.tp-pricing__faqhead::before{content:"";flex:none;width:26px;height:2px;border-radius:2px;background:linear-gradient(90deg,var(--tp-gold),#e07a5f)}
.tp-pricing__faq{width:min(820px,100%);margin:14px auto 0;display:grid;gap:12px}

/* Keyboard focus: a gold ring reads on the dark buttons, the dark halo behind it reads on
   the white page, so one treatment works on every call to action here. */
.tp-auth__btn:focus-visible,.tp-pricing__toggle button:focus-visible,.tp-auth__acts .tp-auth__btn:focus-visible{
  outline:3px solid var(--tp-gold);outline-offset:2px;box-shadow:0 0 0 6px rgba(13,61,53,.25)}
/* Plain links, not the buttons: a button that happens to be a link keeps the gold ring. */
.tp-auth__links a:not(.tp-auth__btn):focus-visible,.tp-auth__after a:not(.tp-auth__btn):focus-visible,
.tp-linkbtn:focus-visible,.tp-price a:not(.tp-auth__btn):focus-visible,.tp-auth__intro a:not(.tp-auth__btn):focus-visible{
  outline:2px solid var(--tp-forest);outline-offset:3px;border-radius:4px}
.tp-pricing__faq details{background:#fff;border:1px solid var(--tp-line);border-radius:10px;overflow:hidden;transition:border-color .25s,box-shadow .25s}
.tp-pricing__faq details[open]{border-color:var(--tp-leaf);box-shadow:0 12px 30px -24px rgba(13,61,53,.55)}
.tp-pricing__faq summary{display:flex;align-items:center;gap:16px;padding:17px 20px;cursor:pointer;font-weight:700;font-size:16px;line-height:1.35;color:var(--tp-text);list-style:none;transition:color .2s}
.tp-pricing__faq summary::-webkit-details-marker{display:none}
.tp-pricing__faq summary:hover{color:var(--tp-forest)}
.tp-pricing__faq summary:focus-visible{outline:2px solid var(--tp-forest);outline-offset:-2px;border-radius:10px}
.tp-pricing__faq summary::after{content:"";margin-left:auto;flex:none;width:10px;height:10px;border-right:2px solid var(--tp-leaf);border-bottom:2px solid var(--tp-leaf);
  transform:translateY(-3px) rotate(45deg);transition:transform .3s cubic-bezier(.2,.7,.2,1)}
.tp-pricing__faq details[open] summary::after{transform:translateY(2px) rotate(225deg)}
.tp-pricing__faq p{margin:0;padding:0 20px 18px;font-size:14.5px;line-height:1.7;color:var(--tp-muted);max-width:74ch}
.tp-pricing__faq a{color:var(--tp-leaf)}
@supports (interpolate-size:allow-keywords){
  .tp-pricing__faq{interpolate-size:allow-keywords}
  .tp-pricing__faq details::details-content{block-size:0;overflow:hidden;transition:block-size .34s cubic-bezier(.2,.7,.2,1),content-visibility .34s allow-discrete}
  .tp-pricing__faq details[open]::details-content{block-size:auto}
}
.tp-pricing__faq details[open] p{animation:tpFaqIn .38s ease .04s both}
@keyframes tpFaqIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  .tp-pricing__faq summary::after,.tp-pricing__faq details,.tp-pricing__faq details::details-content{transition:none}
  .tp-pricing__faq details[open] p{animation:none}
}
@media (max-width:820px){.tp-pricing__grid{grid-template-columns:1fr}.tp-pricing__head h1{font-size:28px}.tp-price{padding:24px 22px}}

/* ---------------------------------------------------------------------------
   v54: the three prices line up
   ------------------------------------------------------------------------- */

/* The grid held four cards, not three: an <article> was opened and never closed, so the
   browser repaired it by wrapping Team and Enterprise inside an empty Enterprise card.
   That is why nothing lined up. With the stray tag gone the rest is arithmetic.

   Each card is a column that ends on its button: the list of what you get takes up the
   slack, so the three buttons sit on one line however many points are listed above them,
   and the note under the button is given the room the longest of the three needs so it
   cannot push its own button out of step. */
.tp-price{display:flex;flex-direction:column;gap:14px}
.tp-price__list{flex:1 1 auto}
.tp-price>.tp-auth__btn{margin-top:auto}
.tp-price>.tp-auth__small{margin:0;min-height:4.6em}

/* The recommended card was drawn with a border twice as thick as the others, which moved
   everything inside it a pixel out of line with its neighbours. The ring is drawn inside
   the card now, so all three keep the same box. */
.tp-price--standard{border-width:1px;box-shadow:0 0 0 1px var(--tp-forest) inset,
  0 12px 30px -20px rgba(13,61,53,.35)}

@media (max-width:820px){
  .tp-price>.tp-auth__small{min-height:0}
}
.tp-nav__account small{font-size:10.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;background:var(--tp-gold);color:#0b1f19;border-radius:999px;padding:2px 7px;margin-left:4px;vertical-align:middle}
.tp-locked{margin:14px 24px 0;padding:12px 16px;background:#fff4e5;border:1px solid #f1d9a8;border-radius:8px;font-size:14.5px;color:#5a3d00;max-width:1100px}
.tp-account h2{margin:0 0 16px;font-size:24px}
.tp-account__grid{display:grid;grid-template-columns:1.2fr 1fr;gap:18px}
.tp-account__card{border:1px solid var(--tp-line);border-radius:10px;padding:20px 22px;display:grid;gap:10px;align-content:start}
.tp-account__card h3{margin:0;font-size:22px}
.tp-account__card h3.is-ok{color:var(--tp-forest)}.tp-account__card h3.is-off{color:#b3261e}
.tp-account__card h4{margin:10px 0 0;font-size:15px}
.tp-account__card p{margin:0;font-size:14.5px}
.tp-account__plans{display:grid;gap:10px;margin-top:6px;justify-items:start}
.tp-account__plans .tp-btn{text-decoration:none}
.tp-account__small{font-size:13px;color:var(--tp-muted)}
.tp-account__small a{color:var(--tp-leaf)}
.tp-account__dl{display:grid;grid-template-columns:auto 1fr;gap:6px 14px;margin:0;font-size:14.5px}
.tp-account__dl dt{color:var(--tp-muted)}.tp-account__dl dd{margin:0}
.tp-account__pw{display:grid;gap:10px}
.tp-account__pw label{display:grid;gap:4px;font-size:14px}
.tp-account__pw input{font:inherit;padding:9px 10px;border:1px solid #cfd8d4;border-radius:4px}
.tp-account__pw .tp-codeform__err.is-ok{color:var(--tp-forest)}
@media (max-width:820px){.tp-account__grid{grid-template-columns:1fr}}
.tp-edit__title{display:grid;gap:4px;font-size:13px;color:var(--tp-muted);margin:4px 0 8px}
.tp-edit__title input{font:700 22px var(--tp-font);color:var(--tp-forest);padding:8px 10px;border:1px solid #cfd8d4;border-radius:6px;width:100%}

/* v7: readability. Muted text at 7.7:1, gold text only on dark surfaces, no text under 11.5px; the pricing call-to-action is a link and must not take the link colour. */
:root{--tp-muted:#44574f}
a.tp-auth__btn,.tp-price .tp-auth__btn,.tp-auth__btn:visited{color:#fff}
a.tp-auth__btn--ghost,.tp-price .tp-auth__btn--ghost{color:var(--tp-forest)}
.tp-auth__foot,.tp-auth__small,.tp-account__small,.tp-pricing__faq p,.tp-price__amount small,.tp-auth__intro,.tp-viewer__foot{color:var(--tp-muted)}
.tp-logo span,.tp-linkbtn,.tp-login__foot,.tp-nav button,.tp-nav a,.tp-sub,.tp-toolbar__links,.tp-pack__contents,.tp-row__meta,.tp-doc table,.tp-edit__notes,.tp-nav__code,.tp-viewer__foot,.tp-auth__foot,.tp-card__body p,.tp-toolbar__tools,.tp-sort select,.tp-account__small,.tp-edit__title{font-size:13.5px}
.tp-eyebrow,.tp-login__card label,.tp-form label,.tp-filter__opts label em,.tp-row__clients select,.tp-pack__cover h3,.tp-thumb--step,.tp-thumb--step b,.tp-badge,.tp-equip__img,.tp-doc__chips span,.tp-doc h3,.tp-pack__cover dt,.tp-row__extra small,.tp-table small,.tp-doc--edit h3 .tp-linkbtn,.tp-codeform label,.tp-ack__form label,.tp-day__label,.tp-card__badge,.tp-card__group,.tp-card__clients b,.tp-auth__logo span small,.tp-card__play,.tp-pricing__toggle button small{font-size:12.5px}
.tp-logo span small,.tp-nav__account small{font-size:11.5px}
.tp-row__head button.is-on,.tp-day__label{color:#8a5a0b}
.tp-doc ol li::marker{color:var(--tp-leaf)}

/* v8: responsive workspace. Desktop: logo left, sections centre, account right. Under 980px the sections fold into a Menu button and the filter column folds behind a Filters button, so the library is one scroll away on a phone. Touch targets at least 40px on small screens. */
.tp-top{gap:12px}
.tp-nav{flex:1;justify-content:center;flex-wrap:nowrap;align-items:center}
.tp-nav__right{display:flex;gap:4px;margin-left:auto;padding-left:10px;border-left:1px solid var(--tp-line)}
.tp-nav__account small{display:inline-block;margin-left:6px;padding:2px 7px;border-radius:999px;background:#e8f1ec;color:var(--tp-forest);font-size:11.5px;letter-spacing:.04em;text-transform:none;font-weight:700;vertical-align:1px}
.tp-nav__account.is-on small{background:#fde8e6;color:#b3261e}
.tp-menu{display:none;appearance:none;border:1px solid var(--tp-line);background:#fff;border-radius:10px;padding:8px 12px;align-items:center;gap:8px;font:600 13px var(--tp-font);color:var(--tp-forest);cursor:pointer;min-height:40px}
.tp-menu i{display:none}
.tp-side__toggle{display:none;appearance:none;border:1px solid var(--tp-line);background:#fff;border-radius:10px;padding:10px 14px;font:600 14px var(--tp-font);color:var(--tp-forest);cursor:pointer;min-height:44px;align-items:center;gap:8px;justify-content:space-between;width:100%}
.tp-side__toggle b{font-weight:600;color:var(--tp-muted)}
.tp-side__toggle i{width:8px;height:8px;border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(45deg);margin-left:auto;transition:transform .2s}
.tp-side.is-open .tp-side__toggle i{transform:rotate(-135deg)}
@media (max-width:980px){
  .tp-top{position:sticky;top:0;flex-wrap:nowrap;padding:8px 14px;min-height:56px}
  .tp-menu{display:grid;gap:4px;align-content:center;justify-items:center;width:44px;height:40px;padding:0;margin-left:auto}
  .tp-menu[aria-expanded="true"]{background:var(--tp-forest);color:#fff;border-color:var(--tp-forest)}
  .tp-menu i{display:block;width:16px;height:2px;background:currentColor;border-radius:2px}
  .tp-menu span{display:none}
  .tp-nav{display:none;position:absolute;left:0;right:0;top:100%;background:#fff;border-bottom:1px solid var(--tp-line);box-shadow:0 12px 30px rgba(11,31,25,.12);flex-direction:column;align-items:stretch;padding:6px 8px 10px;gap:0}
  .tp-nav.is-open{display:flex}
  .tp-nav button,.tp-nav a{text-align:left;padding:13px 12px;font-size:13.5px;min-height:44px;border-bottom:0;border-left:3px solid transparent;border-radius:8px}
  .tp-nav button.is-on{border-left-color:var(--tp-forest);background:#f0f5f2}
  .tp-nav__right{flex-direction:column;margin:6px 0 0;padding:8px 0 0;border-left:0;border-top:1px solid var(--tp-line)}
  .tp-sub{padding:7px 14px;font-size:12.5px;gap:4px 14px}
  .tp-side{gap:10px;padding:10px}
  .tp-side__toggle{display:flex}
  .tp-side>.tp-filter:not(.tp-filter--client),.tp-side>.tp-filters,.tp-side>[data-filters-clear]{display:none}
  .tp-side.is-open>.tp-filter:not(.tp-filter--client),.tp-side.is-open>.tp-filters{display:grid}
  .tp-side.is-open>[data-filters-clear]{display:inline-flex}
  .tp-filter--client{display:grid;grid-template-columns:1fr auto;align-items:center;gap:6px 10px}
  .tp-filter--client .tp-filter__title{grid-column:1/-1}
  .tp-linkbtn{min-height:40px;display:inline-flex;align-items:center}
  .tp-card__fav,.tp-viewtoggle button{min-width:40px;min-height:40px}
  .tp-card__add{min-height:40px}
  .tp-sort select{min-height:40px}
}
@media (max-width:600px){
  .tp-logo span{font-size:13px}
  .tp-sub span:last-child:not(:first-child){display:none}
  .tp-toolbar{flex-wrap:wrap;gap:8px}
  .tp-pack__bar--top{display:grid;grid-template-columns:1fr 1fr;gap:8px;top:56px}
  .tp-pack__spacer{display:none}
  .tp-pack__modes{grid-column:1/-1;display:flex}
  .tp-pack__modes button{flex:1}
  .tp-pack__bar--top .tp-btn{justify-content:center;text-align:center}
  .tp-pack__cover dl{grid-template-columns:1fr}
  .tp-auth__links a{padding:9px 8px;min-height:40px;display:inline-flex;align-items:center}
  .tp-auth__btn{width:100%;justify-content:center}
}

/* v9: Physitrack app pattern. One header row: logo, Library / Clients / Help with icons, Pack editor button with a count, account menu with a status dot. A second row of section tabs (Procedures, Quick-start packs, Equipment) with "Custom procedure" on the right. Cards: select circle, star and open on top, scene, title, carer dots and group tag below; a selected card is outlined. */
.tp-top{padding:0 22px;min-height:60px;gap:16px}
.tp-nav--primary{flex:0 1 auto;justify-content:flex-start;margin-left:6px;align-self:stretch}
.tp-nav--primary button,.tp-nav--primary a{display:inline-flex;align-items:center;gap:8px;text-transform:none;letter-spacing:0;font-size:14.5px;font-weight:600;padding:0 12px;min-height:60px;border-bottom:3px solid transparent;border-radius:0;color:var(--tp-muted)}
.tp-nav--primary button svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.tp-nav--primary button.is-on{color:var(--tp-forest);border-bottom-color:var(--tp-forest)}
.tp-nav__mobile{display:none}
.tp-top__right{display:flex;align-items:center;gap:10px;margin-left:auto}
.tp-packbtn{appearance:none;border:0;background:var(--tp-forest);color:#fff;border-radius:10px;padding:0 14px;min-height:40px;display:inline-flex;align-items:center;gap:8px;font:600 14px var(--tp-font);cursor:pointer;transition:background .2s}
.tp-packbtn:hover{background:var(--tp-leaf)}
.tp-packbtn svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linejoin:round}
.tp-packbtn b{background:#fff;color:var(--tp-forest);border-radius:999px;min-width:22px;height:22px;padding:0 6px;display:inline-grid;place-items:center;font-size:12.5px}
.tp-account{position:relative}
.tp-account__btn{appearance:none;border:1px solid transparent;background:none;border-radius:10px;padding:6px 8px;min-height:40px;display:inline-flex;align-items:center;gap:8px;font:600 14px var(--tp-font);color:var(--tp-text);cursor:pointer}
.tp-account__btn:hover,.tp-account__btn[aria-expanded="true"]{border-color:var(--tp-line);background:#fff}
.tp-account__btn i{width:9px;height:9px;border-radius:50%;background:#b3261e}
.tp-account__btn i.is-ok{background:#3f9d6d}
.tp-account__btn svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:1.6}
.tp-account__menu{position:absolute;right:0;top:calc(100% + 6px);width:250px;background:#fff;border:1px solid var(--tp-line);border-radius:12px;box-shadow:0 18px 40px -20px rgba(11,31,25,.35);padding:6px;display:grid;z-index:40}
.tp-account__status{display:block;padding:8px 12px 10px;font-size:12.5px;color:var(--tp-muted);border-bottom:1px solid var(--tp-line);margin-bottom:4px}
.tp-account__menu button,.tp-account__menu a{appearance:none;border:0;background:none;text-align:left;padding:10px 12px;border-radius:8px;font:500 14px var(--tp-font);color:var(--tp-text);cursor:pointer;text-decoration:none;display:block}
.tp-account__menu button:hover,.tp-account__menu a:hover{background:#f0f5f2;color:var(--tp-forest)}
.tp-account__out{color:#b3261e!important;border-top:1px solid var(--tp-line);border-radius:0 0 8px 8px!important;margin-top:4px}
.tp-sections{display:flex;align-items:center;gap:4px;padding:0 22px;background:#fff;border-bottom:1px solid var(--tp-line);position:sticky;top:60px;z-index:19}
.tp-sections button{appearance:none;border:0;background:none;padding:0 10px;min-height:46px;font:600 14px var(--tp-font);color:var(--tp-muted);cursor:pointer;border-bottom:3px solid transparent;margin-bottom:-1px}
.tp-sections button.is-on{color:var(--tp-forest);border-bottom-color:var(--tp-forest)}
.tp-sections button:hover{color:var(--tp-forest)}
.tp-sections .tp-newbtn{margin-left:auto;border:1px solid var(--tp-line);border-radius:10px;min-height:36px;padding:0 12px;display:inline-flex;align-items:center;gap:6px;color:var(--tp-forest);background:#fff;margin-bottom:0}
.tp-sections .tp-newbtn svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}
.tp-sections .tp-newbtn:hover{border-color:var(--tp-forest)}
.tp-sub{padding:8px 22px}
.tp-side{top:118px}
.tp-pack__bar--top{top:60px}
.tp-card{border-radius:12px}
.tp-card__top{display:flex;justify-content:space-between;align-items:center;padding:8px 8px 0}
.tp-card__top button{appearance:none;border:0;background:none;width:36px;height:36px;border-radius:8px;display:grid;place-items:center;color:var(--tp-forest);cursor:pointer;position:static;font-size:0}
.tp-card__top button svg{width:22px;height:22px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.tp-card__top button:hover{background:#f0f5f2}
.tp-card__check .tick{opacity:0}
.tp-card.is-selected .tp-card__check svg circle{fill:var(--tp-forest)}
.tp-card.is-selected .tp-card__check .tick{opacity:1;stroke:#fff}
.tp-card__fav.is-on svg path{fill:var(--tp-gold);stroke:var(--tp-gold)}
.tp-card__scene{margin:6px 12px 0;border-radius:10px;aspect-ratio:16/10}
.tp-card__scene .tp-scene{border-radius:10px}
.tp-card__body{padding:10px 14px 6px;gap:5px}
.tp-card__body h3{font-size:15.5px;line-height:1.3}
.tp-card__body p{font-size:13px;color:var(--tp-muted);margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.tp-card__foot{display:flex;align-items:center;gap:10px;padding:6px 14px 12px;border-top:0}
.tp-card__dots{display:inline-flex;gap:3px}
.tp-card__dots i{width:7px;height:7px;border-radius:50%;background:var(--tp-forest);display:block}
.tp-card__tag{font-size:11.5px;letter-spacing:.04em;color:var(--tp-muted);background:#f0f2f1;border-radius:6px;padding:3px 7px;margin-left:auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:60%}
.tp-card__foot .tp-linkbtn{margin-left:0;font-size:12.5px}
.tp-card.is-selected{border-color:var(--tp-forest);box-shadow:0 0 0 1px var(--tp-forest)}
@media (max-width:980px){
  .tp-top{padding:0 14px;min-height:56px;gap:10px}
  .tp-nav--primary{position:absolute;margin:0}
  .tp-nav--primary button,.tp-nav--primary a{min-height:44px;padding:0 12px;border-bottom:0}
  .tp-nav--primary button.is-on{background:#f0f5f2;border-left:3px solid var(--tp-forest)}
  .tp-nav__mobile{display:flex;flex-direction:column;border-top:1px solid var(--tp-line);margin-top:6px;padding-top:6px}
  .tp-nav__mobile a{text-decoration:none}
  .tp-account__menu{right:-52px}
  .tp-sections{top:56px;overflow-x:auto;scrollbar-width:none;padding:0 14px;gap:0}
  .tp-sections button{white-space:nowrap}
  .tp-side{top:auto}
  .tp-pack__bar--top{top:56px}
}
@media (max-width:600px){
  .tp-account__btn span{display:none}
  .tp-packbtn{padding:0 10px;white-space:nowrap;font-size:13px}
  .tp-packbtn svg{display:none}
  .tp-sections .tp-newbtn{min-height:32px;padding:0 8px;font-size:13px}
  .tp-card__top{padding:6px 4px 0}
  .tp-card__scene{margin:4px 10px 0}
  .tp-card__body{padding:8px 10px 4px}
  .tp-card__foot{padding:4px 10px 10px}
}

/* v10: policy layer and sling fields. Thrive guidance box (read-only, from the policy backend), sling / size / loop selects in the editor, colour swatches on the printed plan. */
.tp-doc__guidance{background:#eef5f1;border:1px solid #cfe0d6!important;border-radius:10px;padding:10px 12px!important}
.tp-doc__guidance h3{color:var(--tp-forest)}
.tp-doc__guidance p{margin:0;font-size:14px}
.tp-edit__sling{background:#fbfcfb;border:1px solid var(--tp-line);border-radius:10px;padding:12px 14px!important}
.tp-edit__grid select{font:inherit;font-size:14px;padding:9px 11px;border:1px solid var(--tp-line);border-radius:10px;background:#fff;color:var(--tp-text)}
.tp-edit__brands{margin-top:10px;font-size:13.5px}
.tp-edit__brands summary{cursor:pointer;color:var(--tp-forest);font-weight:600}
.tp-edit__brands ul{margin:8px 0 0 18px;display:grid;gap:6px;color:var(--tp-muted)}
.tp-swatch{display:inline-block;width:14px;height:14px;border-radius:50%;border:1px solid rgba(0,0,0,.25);vertical-align:-2px;margin-right:6px}

/* v12: contact details on the plan, and the check before printing, saving or sending. */
.tp-pack__contact{margin:16px 0 0;background:#f2f7f4;border:1px solid var(--tp-line);border-left:4px solid var(--tp-forest);border-radius:10px;padding:14px 16px}
.tp-pack__contact h3{font-size:14.5px;color:var(--tp-forest);margin:0 0 4px}
.tp-pack__contact p{margin:0 0 10px;font-size:13.5px;color:var(--tp-muted)}
.tp-pack__contact dl{margin:0;display:grid;gap:6px;grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}
.tp-pack__contact dt{font-size:11.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--tp-leaf);font-weight:700}
.tp-pack__contact dd{margin:2px 0 0;font-size:14px;font-weight:600;color:var(--tp-text)}
.tp-contact{background:#fff;border:1px solid var(--tp-line);border-radius:12px;padding:16px 18px;margin:0 0 16px}
.tp-contact h3{font-size:15px;margin:0 0 4px}
.tp-contact p{margin:0 0 12px;font-size:13.5px;color:var(--tp-muted)}
.tp-contact__grid{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}
.tp-contact label{display:grid;gap:4px;font-size:12.5px;font-weight:600;color:var(--tp-forest)}
.tp-contact input{font:inherit;padding:9px 11px;border:1px solid var(--tp-line);border-radius:10px;background:#fff;color:var(--tp-text)}
.tp-contact__foot{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-top:12px}
.tp-contact__msg{font-size:13px;color:var(--tp-leaf);margin:0}
.tp-gate{position:fixed;inset:0;z-index:200;background:rgba(11,31,25,.55);backdrop-filter:blur(3px);display:grid;place-items:center;padding:20px}
.tp-gate__card{width:min(620px,100%);max-height:90vh;overflow:auto;background:#fff;border-radius:16px;padding:24px 26px;box-shadow:0 40px 80px -40px rgba(0,0,0,.6);display:grid;gap:10px}
.tp-gate__card h2{font-size:22px;margin:2px 0 0}
.tp-gate__card>p{margin:0;color:var(--tp-muted);font-size:14.5px}
.tp-gate__list{margin:8px 0 0;display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));background:#f7f9f8;border:1px solid var(--tp-line);border-radius:10px;padding:12px 14px}
.tp-gate__list dt{font-size:11.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--tp-leaf);font-weight:700}
.tp-gate__list dd{margin:2px 0 0;font-size:14px;font-weight:600}
.tp-gate__list em{font-style:normal;color:var(--tp-muted);font-weight:500}
.tp-gate__grid{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}
.tp-gate__form label{display:grid;gap:4px;font-size:12.5px;font-weight:600;color:var(--tp-forest)}
.tp-gate__form input{font:inherit;padding:9px 11px;border:1px solid var(--tp-line);border-radius:10px}
.tp-gate__msg{margin:0;font-size:13.5px;color:#a3271a;min-height:1em}
.tp-gate__acts{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-top:6px}
.tp-gate__acts .tp-btn[disabled]{opacity:.45;cursor:not-allowed}
@media print{.tp-gate{display:none}.tp-pack__contact{break-inside:avoid}}
@media (max-width:980px){.tp-list--grid{grid-template-columns:repeat(auto-fill,minmax(210px,1fr))}}
/* v15: the filter rail follows the pattern exactly: the Filter row is pinned at the top of
   the panel and the facets scroll underneath it, and the search sits above the library
   rather than in the rail. */
@media (min-width:981px){
  .tp-side{display:flex;flex-direction:column;max-height:calc(100vh - 128px);overflow:hidden;padding:10px 10px 4px}
  .tp-side__scroll{flex:1;min-height:0;overflow-y:auto;scrollbar-width:thin;padding-right:2px}
  .tp-filterhead{flex:none;border-bottom:1px solid #e2eae6;margin-bottom:6px}
}
.tp-filterhead__msg:empty{display:none;margin:0}
@media (max-width:980px){.tp-side:not(.is-open){gap:6px;padding-bottom:8px}}
.tp-libbar{display:flex;align-items:center;gap:12px;margin:0 0 10px;flex-wrap:wrap}
.tp-libbar .tp-search{flex:1;min-width:220px}
.tp-libbar .tp-search input{height:38px;border-radius:8px;background:#fff;font-size:14px;padding:8px 34px 8px 12px}
.tp-libbar__client{display:flex;align-items:center;gap:8px;font-size:12.5px;font-weight:600;color:var(--tp-muted);white-space:nowrap}
.tp-libbar__client select{font:inherit;font-size:13.5px;font-weight:400;color:var(--tp-text);height:38px;padding:0 10px;border:1px solid var(--tp-line);border-radius:8px;background:#fff;max-width:230px}
.tp-libbar .tp-linkbtn{font-size:12.5px;white-space:nowrap}
@media (max-width:980px){
  .tp-libbar{gap:8px}
  .tp-libbar .tp-search{flex:1 1 100%}
  /* the facets collapse behind the Filters button; the Filter row stays */
  .tp-side__scroll{display:none}
  .tp-side.is-open .tp-side__scroll{display:grid;gap:10px}
  .tp-side__toggle{order:-1}
}

/* v14: a standard clinical typeface, a filter header the way clinicians expect it, and the
   pack tray out of the way until there is something in the pack. */
:root{--tp-font:"Open Sans",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif}
.tp-filterhead{display:flex;align-items:center;gap:8px;padding:2px 2px 8px}
.tp-filterhead svg{width:16px;height:16px;flex:none;color:var(--tp-forest)}
.tp-filterhead b{font-size:15px;font-weight:700;color:var(--tp-text);margin-right:auto}
.tp-filterhead__clear{appearance:none;border:0;background:none;padding:4px 6px;font:inherit;font-size:12.5px;color:var(--tp-leaf);cursor:pointer;text-decoration:underline;text-underline-offset:3px}
.tp-filterhead__clear:hover{color:var(--tp-forest)}
.tp-filterhead__save{appearance:none;border:0;background:var(--tp-forest);color:#fff;font:inherit;font-size:12.5px;font-weight:600;height:30px;padding:0 14px;border-radius:6px;cursor:pointer}
.tp-filterhead__save:hover{background:var(--tp-leaf)}
.tp-filterhead__msg{margin:0 2px 6px;font-size:12.5px;color:var(--tp-leaf);min-height:1em}
/* On a narrow screen the facets already sit behind a "Filters" disclosure, so the funnel and
   the word are noise: keep only Clear and Save, right aligned under it. */
@media (max-width:980px){.tp-filterhead{justify-content:flex-end;padding-top:0}.tp-filterhead svg,.tp-filterhead b{display:none}}

/* v13: the library screen, tightened to the pattern clinicians already know from other
   clinical libraries: a fixed filter rail on the left with counted, tickable facets, and a
   dense card grid on the right. Thrive's own type and colour; only the layout, the density
   and the interaction pattern are shared. One accent, one radius scale, no decoration. */
@media (min-width:981px){.tp-work{grid-template-columns:288px minmax(0,1fr);gap:26px}}
.tp-side{background:#f7faf9;border-color:#e2eae6;border-radius:10px;padding:10px;gap:8px}
.tp-side .tp-search input{height:38px;padding:8px 34px 8px 12px;border-radius:8px;background:#fff;font-size:14px}
.tp-filter{border-top:1px solid #e2eae6;padding:10px 0 4px;gap:4px}
.tp-filter:first-of-type{border-top:0;padding-top:2px}
.tp-filter__title{font:600 12.5px var(--tp-font);letter-spacing:0;text-transform:none;color:var(--tp-muted);padding:0 2px 2px}
.tp-filter__title{display:flex;align-items:baseline}
.tp-filter__title::after{content:":";order:2}
.tp-filter__title b{color:var(--tp-forest);font-weight:700;margin-left:6px;order:3}
.tp-filter__title b:empty{margin:0}
.tp-filter__find{width:100%;font:inherit;font-size:13px;height:32px;padding:6px 10px;margin:2px 0 4px;border:1px solid #cfdcd7;border-radius:8px;background:#fff}
.tp-filter--long .tp-filter__opts{max-height:232px;overflow:auto;scrollbar-width:thin}
.tp-filter__opts label{gap:8px;font-size:13.5px;padding:3px 6px;border-radius:6px;min-height:26px}
.tp-filter__opts label em{font-size:12.5px;font-weight:700;color:var(--tp-forest);font-style:normal}
.tp-filter__opts label em::before{content:"("}
.tp-filter__opts label em::after{content:")"}
.tp-filter__opts label:has(input:checked){background:var(--tp-forest);color:#fff}
.tp-filter__opts label:has(input:checked) em{color:#fff}
.tp-filter__opts label:hover:not(:has(input:checked)){background:#eaf1ee}

/* Cards: one row of controls, a fixed picture area, a two-line title, one line of meta. */
.tp-list--grid{grid-template-columns:repeat(auto-fill,minmax(212px,1fr));gap:20px}
.tp-card{border-radius:10px;transition:border-color .2s,box-shadow .2s}
.tp-card:hover{transform:none;box-shadow:none;border-color:var(--tp-leaf)}
.tp-card__scene{margin:8px 8px 0;border-radius:8px;aspect-ratio:4/3}
.tp-card__scene .tp-scene{border-radius:8px}
.tp-card__body{padding:8px 10px 4px;gap:4px}
.tp-card__body h3{font-size:14.5px;line-height:1.35;font-weight:600;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.tp-card__body p{display:none}
.tp-card__group{font-size:11px;letter-spacing:.06em}
.tp-card__foot{padding:4px 10px 10px;gap:8px}
.tp-card__tag{font-size:11px;padding:2px 6px}
@media (min-width:1560px){.tp-list--grid{grid-template-columns:repeat(auto-fill,minmax(236px,1fr))}}
@media (min-width:981px) and (max-width:1100px){.tp-work{grid-template-columns:248px minmax(0,1fr);gap:18px}}
/* Below 980 the rail stacks above the library (rule further up the file). Keep it short so the
   cards are still the first thing on screen, and drop to two cards a row on a phone. */
@media (max-width:980px){
  .tp-work{gap:14px}
  .tp-side{padding:10px;gap:6px}
  .tp-filter--long .tp-filter__opts{max-height:168px}
  .tp-list--grid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:12px}
}

@media (max-width:600px){.tp-list--grid{grid-template-columns:1fr 1fr;gap:10px}.tp-card__body{padding:10px 10px 6px}.tp-card h3{font-size:14px}.tp-card__foot{padding:6px 10px 10px;gap:8px;flex-wrap:wrap}.tp-toolbar__tools{width:100%;justify-content:space-between}}

/* v16: the account screens: sign in, open a plan with a code, create account, verify and set
   password, all follow one pattern: a pale page, the mark and the account links centred above,
   one narrow white card, labels stacked over full-width fields, a tinted strip for the remember
   option and a full-width primary action. The same layout from a phone to a desktop. */
.tp-auth{background:#f7faf9;padding:34px 16px 56px;gap:0}
.tp-auth__logo{flex-direction:column;gap:8px;margin:0 0 16px;font-size:23px;text-align:center}
.tp-auth__logo img{width:42px}
/* The account routes live at the foot of the page now, under the card, not above it. */
.tp-auth__links--foot{justify-content:center;gap:20px;font-size:13.5px;margin:22px 0 0;flex-wrap:wrap}
.tp-auth__links--foot a{color:var(--tp-muted)}
.tp-auth__links--foot a:hover{color:var(--tp-forest)}
.tp-auth__logo{margin-bottom:22px}
.tp-auth__card{width:min(534px,100%);border-radius:5px;padding:28px 30px 26px;box-shadow:0 1px 3px rgba(13,61,53,.09);gap:15px;margin:0}
.tp-auth__card--wide{width:min(680px,100%)}
.tp-auth__card h1{font-size:24px;letter-spacing:0}
.tp-auth__intro{font-size:14.5px;line-height:1.55}
.tp-auth__tabs{margin:-4px 0 4px}
.tp-auth__form{gap:15px}
.tp-auth__form label{gap:5px;font-size:15.5px;color:#666}
.tp-auth__form input:not([type=checkbox]),.tp-auth__form select{height:40px;padding:8px 11px;font-size:15px;border:1px solid #ccc;border-radius:4px;color:var(--tp-text)}
.tp-auth__form select{padding:0 10px}
.tp-auth__form label small{display:block;font-weight:400;color:var(--tp-muted);font-size:12.5px;margin-top:2px;line-height:1.45}
.tp-auth__form input:focus,.tp-auth__form select:focus{outline:2px solid var(--tp-forest);outline-offset:0;border-color:var(--tp-forest)}
.tp-auth__remember{background:#f9f9f9;border:1px solid #eef2f1;border-radius:5px;padding:13px 14px;font-size:14.5px;color:var(--tp-text)}
.tp-auth__form > .tp-auth__btn{width:100%;justify-self:stretch;height:48px;border-radius:4px;font-size:16px;padding:0 18px}
.tp-auth__small{font-size:13.5px;line-height:1.55}
.tp-auth__foot{margin-top:20px;max-width:56ch;line-height:1.6}
@media (max-width:600px){
  .tp-auth{padding:22px 14px 44px}
  .tp-auth__card{padding:22px 18px 20px}
  .tp-auth__card h1{font-size:21px}
  .tp-auth__logo{font-size:20px;margin-bottom:12px}
  .tp-auth__links--foot{gap:14px;font-size:13px;margin-top:18px}
  .tp-auth__row{grid-template-columns:1fr}
}

/* The client form issues its reference from the site, so its note sits under the whole row. */
.tp-form__note{margin:6px 0 0;font-size:12.5px;color:var(--tp-muted);flex:1 1 100%;line-height:1.5}

/* v17: create account. The form runs down the left of the screen on white, and a deep green
   panel on the right shows what the first month looks like, one card at a time. Rounded
   fields, a two-step progress bar and a trial badge. The panel is decoration: it is hidden
   from assistive technology, folds away below 980px, and holds still under reduced motion. */
.tp-auth--split{padding:0;background:#fff;min-height:100vh;align-content:start;justify-items:stretch;gap:0}
@media (min-width:981px){
  .tp-auth--split{display:grid;grid-template-columns:minmax(0,1fr) minmax(360px,.72fr);column-gap:0;align-content:start}
  /* Everything except the panel runs down the left, left aligned and capped for readability. */
  .tp-auth--split > *{grid-column:1;justify-self:stretch;max-width:560px;margin-left:clamp(28px,7vw,96px);margin-right:28px}
  .tp-auth--split > .tp-auth__logo{flex-direction:row;align-items:center;text-align:left;gap:12px;margin-top:38px;margin-bottom:22px;font-size:21px}
  .tp-auth--split > .tp-auth__links--foot{justify-content:flex-start;margin-top:28px}
  .tp-auth--split > .tp-auth__foot{margin-top:12px;margin-bottom:44px;text-align:left}
  /* The panel keeps pace with the form and fills the height of the screen. */
  .tp-auth--split > .tp-reg__side{grid-column:2;grid-row:1/span 30;align-self:start;position:sticky;top:0;height:100vh;max-width:none;margin:0}
}
@media (max-width:980px){
  /* On a phone the form is the page: one white column, no card edges to fight the fields. */
  .tp-auth--split{padding:24px 20px 48px;background:#fff}
  .tp-auth--split > *{width:min(520px,100%)}
  .tp-auth--split > .tp-reg__side{display:none}
}
.tp-auth--split > .tp-auth__card{background:#fff;border:0;box-shadow:none;padding:0;width:min(560px,100%)}
.tp-reg__progress{display:flex;gap:6px;margin:0 0 10px;padding:0}
.tp-reg__progress i{height:7px;border-radius:5px;background:#e7ebe9;flex:1}
.tp-reg__progress i.is-on{background:var(--tp-leaf);flex:2.2;transform-origin:left center;animation:tpRegFill .9s cubic-bezier(.2,.7,.2,1) both}
@keyframes tpRegFill{from{transform:scaleX(.12)}to{transform:scaleX(1)}}
.tp-reg__step{margin:0;font-size:12.5px;color:var(--tp-muted);letter-spacing:.01em}
.tp-reg__badge{justify-self:start;display:inline-block;background:#eaf5ec;color:#2f5d33;border-radius:999px;padding:6px 14px;font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase}
.tp-reg__card h1{font-size:clamp(26px,3.2vw,35px);font-weight:600;line-height:1.08;letter-spacing:-.02em;margin:2px 0 0}
/* Rounded fields, the way the reference registration screen does it. */
.tp-reg__card .tp-auth__form label{font-size:12.5px;font-weight:600;color:var(--tp-text);gap:7px}
.tp-reg__card .tp-auth__form label small{font-weight:400}
.tp-reg__card .tp-auth__form input:not([type=checkbox]),.tp-reg__card .tp-auth__form select{height:48px;border-radius:999px;border:1px solid #cbd5d1;padding:12px 19px;font-size:16px}
.tp-reg__card .tp-auth__form select{padding:0 16px}
.tp-reg__card .tp-auth__form input:focus,.tp-reg__card .tp-auth__form select:focus{outline:0;border-color:var(--tp-forest);box-shadow:0 0 0 4px rgba(13,61,53,.12)}
.tp-reg__card .tp-auth__form > .tp-auth__btn{width:auto;justify-self:start;height:48px;border-radius:999px;padding:0 30px;font-size:15px}
@media (max-width:600px){.tp-reg__card .tp-auth__form > .tp-auth__btn{width:100%;justify-self:stretch}}
/* Fields arrive in order once, then stay put. */
.tp-reg__card .tp-auth__form > *{animation:tpRegIn .5s cubic-bezier(.2,.7,.2,1) both;animation-delay:calc(60ms + var(--i,0) * 45ms)}
@keyframes tpRegIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

/* v18: sign in, verify and set password join the create-account layout: the same pill
   fields, the same staggered arrival and the same panel beside the form. Sign in gets a
   full-width action, because there is only one thing to do on that screen. */
.tp-auth--split .tp-auth__card h1{font-size:clamp(25px,2.6vw,31px);font-weight:600;line-height:1.12;letter-spacing:-.02em}
.tp-auth--split .tp-auth__card .tp-auth__form label{font-size:12.5px;font-weight:600;color:var(--tp-text);gap:7px}
.tp-auth--split .tp-auth__card .tp-auth__form label small{font-weight:400}
.tp-auth--split .tp-auth__card .tp-auth__form input:not([type=checkbox]),
.tp-auth--split .tp-auth__card .tp-auth__form select{height:48px;border-radius:999px;border:1px solid #cbd5d1;padding:12px 19px;font-size:16px}
.tp-auth--split .tp-auth__card .tp-auth__form select{padding:0 16px}
.tp-auth--split .tp-auth__card .tp-auth__form input:focus,
.tp-auth--split .tp-auth__card .tp-auth__form select:focus{outline:0;border-color:var(--tp-forest);box-shadow:0 0 0 4px rgba(13,61,53,.12)}
.tp-auth--split .tp-auth__card .tp-auth__form > .tp-auth__btn{height:48px;border-radius:999px;font-size:15px;padding:0 30px}
.tp-auth--split .tp-auth__remember{border-radius:999px;padding:12px 20px}
.tp-auth--signin .tp-auth__form > .tp-auth__btn{width:100%;justify-self:stretch}
/* Sign in is a short screen, so it sits nearer the middle of the tall panel beside it. */
@media (min-width:981px){.tp-auth--signin > .tp-auth__logo{margin-top:clamp(38px,13vh,130px)}}
/* The card's own blocks arrive in order; the fields inside a form keep their own sequence. */
.tp-auth--split .tp-auth__card > *:not(form){animation:tpRegIn .5s cubic-bezier(.2,.7,.2,1) both;animation-delay:calc(60ms + var(--i,0) * 45ms)}
.tp-auth--split .tp-auth__card .tp-auth__form > *{animation:tpRegIn .5s cubic-bezier(.2,.7,.2,1) both;animation-delay:calc(120ms + var(--i,0) * 45ms)}
/* The tab underline slides across rather than jumping. */
.tp-auth--split .tp-auth__tabs a{position:relative;border-bottom-color:transparent;transition:color .25s}
.tp-auth--split .tp-auth__tabs a::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;background:var(--tp-forest);transform:scaleX(0);transform-origin:left center;transition:transform .4s cubic-bezier(.2,.7,.2,1)}
.tp-auth--split .tp-auth__tabs a[aria-selected=true]::after{transform:scaleX(1)}
/* A light crosses the primary action on hover. */
.tp-auth--split .tp-auth__btn{position:relative;overflow:hidden}
.tp-auth--split .tp-auth__btn::after{content:"";position:absolute;top:0;bottom:0;width:45%;left:-60%;pointer-events:none;background:linear-gradient(100deg,transparent,rgba(255,255,255,.3),transparent);transform:skewX(-18deg)}
.tp-auth--split .tp-auth__btn:hover::after{animation:tpSheen .8s cubic-bezier(.3,.7,.3,1)}
@keyframes tpSheen{to{left:120%}}
@media (prefers-reduced-motion:reduce){
  .tp-auth--split .tp-auth__card > *:not(form),.tp-auth--split .tp-auth__card .tp-auth__form > *{animation:none}
  .tp-auth--split .tp-auth__tabs a::after{transition:none}
  .tp-auth--split .tp-auth__btn:hover::after{animation:none}
}

/* v19: fields and dropdowns given room, the heading types itself, and the panel says which
   card of the set you are looking at.

   The native dropdown arrow sits hard against the edge of a rounded field and looks pinched,
   so the arrow is drawn here instead, with real space around it on both sides. */
.tp-auth--split .tp-auth__card .tp-auth__form select{
  appearance:none;-webkit-appearance:none;-moz-appearance:none;
  padding:0 48px 0 20px;line-height:46px;cursor:pointer;
  background-color:#fff;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='8' viewBox='0 0 13 8'%3E%3Cpath d='M1.4 1.4 6.5 6.5l5.1-5.1' fill='none' stroke='%230d3d35' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 20px center;background-size:13px 8px}
.tp-auth--split .tp-auth__card .tp-auth__form select::-ms-expand{display:none}
.tp-auth--split .tp-auth__card .tp-auth__form select:hover{border-color:#a9bdb7}
/* Room to breathe: more air between fields, and between a field and the note under it. */
.tp-auth--split .tp-auth__card .tp-auth__form{gap:19px}
.tp-auth--split .tp-auth__card .tp-auth__form label{gap:8px}
.tp-auth--split .tp-auth__card .tp-auth__form label small{margin-top:4px;padding:0 4px;line-height:1.5}
.tp-auth--split .tp-auth__card .tp-auth__row{gap:16px}
.tp-auth--split .tp-auth__card .tp-auth__form > p{margin:0;padding:0 4px}
.tp-auth--split .tp-auth__card [data-prefix-preview]{min-height:1.4em;color:var(--tp-leaf);font-size:13px;line-height:1.5;padding:0 4px}
.tp-auth--split .tp-auth__card .tp-auth__form input::placeholder{color:#98a8a3}

/* The heading, plainly: what the page is, and one quiet line underneath naming who it is
   for, which types itself through the professions. No gradient, no glow, no rule. The
   caret appears only once the script takes over, so nothing blinks on a still page. */
.tp-reg__meta{display:flex;align-items:center;gap:14px;margin:0;flex-wrap:wrap}
.tp-reg__step{font-size:12.5px;color:var(--tp-muted)}
.tp-reg__card h1{font-size:clamp(27px,3vw,35px);font-weight:700;line-height:1.14;letter-spacing:-.02em;margin:0;min-height:2.28em}
.tp-type{color:var(--tp-leaf)}
.tp-type i{font-style:inherit}
.tp-type.is-live::after{content:"";display:inline-block;width:2px;height:.9em;margin-left:3px;vertical-align:-.1em;background:var(--tp-leaf);
  animation:tpCaret 1.05s steps(1) infinite}
@keyframes tpCaret{0%,49%{opacity:1}50%,100%{opacity:0}}
@media (prefers-reduced-motion:reduce){.tp-type.is-live::after{animation:none;opacity:0}}

/* ---------------------------------------------------------------------------
   The panel beside the form, the way the reference registration screen does
   it: a pale full-height illustration, and one white card over it that moves
   through the first day, the first week and the first month.
   ------------------------------------------------------------------------- */
.tp-reg__art{position:absolute;inset:0;width:100%;height:100%;display:block;pointer-events:none}
.tp-reg__art .stem{transform-origin:50% 100%;animation:tpGrow 1.4s cubic-bezier(.2,.7,.2,1) both}
.tp-reg__art .stem:nth-of-type(2){animation-delay:.18s}
.tp-reg__art .stem:nth-of-type(3){animation-delay:.34s}
@keyframes tpGrow{from{transform:scaleY(.05);opacity:0}to{transform:scaleY(1);opacity:1}}
.tp-reg__art .sway{transform-origin:50% 100%;animation:tpSway 9s ease-in-out infinite alternate}
.tp-reg__art .sway--b{animation-duration:11s;animation-delay:-2s}
@keyframes tpSway{from{transform:rotate(-1.4deg)}to{transform:rotate(1.4deg)}}

/* The two-step form: Continue, then Back and Create my account. */
/* Clients live in this browser; saved plans live on the account. This is the way back. */
.tp-restore{display:flex;align-items:center;gap:18px;flex-wrap:wrap;margin:18px 0 0;padding:16px 18px;background:#f7faf9;border:1px solid var(--tp-line);border-radius:12px}
.tp-restore div{flex:1 1 320px}
.tp-restore b{display:block;font-size:14.5px;color:var(--tp-text)}
.tp-restore p{margin:3px 0 0;font-size:13px;line-height:1.55;color:var(--tp-muted)}
.tp-restore .tp-btn{flex:none}
.tp-restore__msg{flex:1 1 100%;margin:0;font-size:13px;color:var(--tp-leaf);min-height:1.2em}
.tp-restore__msg:empty{display:none}
.tp-form__note.is-err{color:#a3271a}
.tp-saved__note{margin:12px 0 0;font-size:12.5px;line-height:1.6;color:var(--tp-muted)}

/* The subscription enquiry. Closed until someone asks to talk, so the pricing page stays a
   page about prices; opened, it is a short form that asks what actually settles a contract. */
.tp-enq{width:min(820px,100%);margin:30px auto 0;background:#fff;border:1px solid var(--tp-line);border-radius:12px;padding:28px 30px;
  box-shadow:0 18px 40px -30px rgba(13,61,53,.5);scroll-margin-top:24px}
.tp-enq[hidden]{display:none}
.tp-enq__head h1,.tp-enq__head h2{font-size:clamp(21px,2.2vw,27px);font-weight:700;letter-spacing:-.02em;margin:10px 0 8px}
.tp-enq__head p{margin:0 0 14px;font-size:14.5px;line-height:1.65;color:var(--tp-muted);max-width:62ch}
.tp-enq__warn{margin:0 0 20px;padding:10px 14px;background:#fdf4ec;border-left:3px solid var(--tp-gold);border-radius:0 8px 8px 0;color:var(--tp-text);font-size:14px}
.tp-enq__form{display:grid;gap:16px}
.tp-enq__row{display:grid;gap:16px;grid-template-columns:1fr 1fr}
@media (max-width:640px){.tp-enq{padding:22px 18px}.tp-enq__row{grid-template-columns:1fr}}
.tp-enq--open{margin:0;border:0;padding:0;box-shadow:none;width:auto}
.tp-enq__form label{display:grid;gap:6px;font-size:13px;font-weight:600;color:var(--tp-text)}
.tp-enq__form label small{font-weight:400;font-size:12px;color:var(--tp-muted);margin-top:-3px}
.tp-talk__page .tp-auth__after{margin-top:22px}
.tp-enq__form input,.tp-enq__form select,.tp-enq__form textarea{width:100%;font:inherit;font-size:15px;padding:11px 13px;
  border:1px solid #cbd5d1;border-radius:8px;background:#fff;color:var(--tp-text)}
.tp-enq__form textarea{resize:vertical;line-height:1.55}
/* Selects carry long clinical wording, so the chevron is drawn rather than left to the
   platform, and the text stops well clear of it instead of running underneath. */
.tp-enq__form select{-webkit-appearance:none;appearance:none;padding:11px 48px 11px 13px;line-height:1.4;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'%3E%3Cpath d='M1 1.5 7 7.5l6-6' fill='none' stroke='%230d3d35' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 17px center;background-size:14px 9px;
  border-left:1px solid #cbd5d1}
.tp-enq__form select:hover{border-color:#a9bdb7}
.tp-enq__form select::-ms-expand{display:none}

/* The follow-up questions the chosen reason asks for. They arrive as a set, marked off from
   the contact details below so it is clear which answers belong to the matter in hand. */
.tp-enq__branch{display:grid;gap:16px;margin:2px 0 4px;padding:18px 18px 20px;border-radius:10px;
  background:#f6faf8;border:1px solid var(--tp-line);border-left:3px solid var(--tp-forest)}
.tp-enq__branch[hidden]{display:none}
.tp-enq__branch.is-in{animation:tpBranchIn .34s cubic-bezier(.2,.7,.2,1) both}
@keyframes tpBranchIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
@media (min-width:700px){
  .tp-enq__branch{grid-template-columns:1fr 1fr}
  .tp-enq__branch>label:only-child,.tp-enq__branch>label:nth-child(odd):last-child{grid-column:1/-1}
  /* A hint line under one label must not push its field below its neighbour's. */
  .tp-enq__branch>label{align-content:end}
}
@media (prefers-reduced-motion:reduce){.tp-enq__branch.is-in{animation:none}}
.tp-enq__form input:focus,.tp-enq__form select:focus,.tp-enq__form textarea:focus{outline:0;border-color:var(--tp-forest);box-shadow:0 0 0 4px rgba(13,61,53,.12)}
.tp-enq__acts{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
.tp-enq__acts .tp-auth__btn{width:auto;justify-self:start}
.tp-enq__msg{margin:0;font-size:13.5px;line-height:1.55;color:var(--tp-leaf);min-height:1.2em}
.tp-enq__msg:empty{display:none}
.tp-enq__msg.is-err{color:#a3271a}
.tp-enq__done{margin:0;font-size:15.5px;line-height:1.7;color:var(--tp-text)}
.tp-enq__done b{display:block;color:var(--tp-forest);margin-bottom:4px}

/* The questions, grouped, on the pricing view and on their own page behind Help. */
.tp-faq__group{width:min(820px,100%);margin:26px auto 10px;font-size:12px;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:var(--tp-leaf);display:flex;align-items:center;gap:12px}
.tp-faq__group::before{content:"";flex:none;width:22px;height:2px;border-radius:2px;background:linear-gradient(90deg,var(--tp-gold),#e07a5f)}
.tp-faq__group:first-of-type{margin-top:10px}
.tp-auth__card .tp-faq__group{width:auto;margin-left:0;margin-right:0}
.tp-faq__page{display:grid;gap:0}
.tp-faq__page h1{font-size:clamp(24px,2.6vw,31px);font-weight:700;letter-spacing:-.02em;margin:0 0 10px}
.tp-faq__page .tp-auth__intro{margin-bottom:6px}
.tp-faq__page .tp-pricing__faq{width:auto;margin:0}
.tp-faq__page .tp-auth__after{margin-top:26px}

/* The other way in, kept beside Help under the card rather than inside it. */
.tp-auth__aside{margin:22px 0 0;font-size:13.5px;line-height:1.6;color:var(--tp-muted);text-align:center}
.tp-auth__aside a{color:var(--tp-forest);font-weight:600;text-decoration:underline;text-underline-offset:3px}
.tp-auth__aside a:hover{color:var(--tp-leaf)}
.tp-auth--split > .tp-auth__aside{text-align:left}
.tp-auth--split > .tp-auth__links--foot{margin-top:10px}

/* The routes out of an account screen, given room to read rather than run together as one
   line of small grey text. The same treatment on the centred card and the split one. */
.tp-auth__card .tp-auth__after{margin:20px 0 0;padding-top:18px;border-top:1px solid #e4ebe8;font-size:14.5px;line-height:1.8;color:var(--tp-muted)}
.tp-auth__card .tp-auth__after a{color:var(--tp-forest);font-weight:600;text-decoration:underline;text-underline-offset:3px}
.tp-auth__card .tp-auth__after a:hover{color:var(--tp-leaf)}
.tp-step{display:grid;gap:19px}
.tp-step[hidden]{display:none}
.tp-auth__acts{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:2px}
.tp-auth--split .tp-auth__card .tp-auth__form > .tp-auth__acts{animation-delay:calc(120ms + var(--i,0) * 45ms)}
.tp-auth--split .tp-auth__acts .tp-auth__btn{height:48px;border-radius:999px;font-size:15px;padding:0 30px;width:auto;justify-self:start;min-width:0}
.tp-auth--split .tp-auth__acts .tp-auth__btn--ghost{background:#fff;color:var(--tp-forest);border:1px solid #cbd5d1;padding:0 22px}
.tp-auth--split .tp-auth__acts .tp-auth__btn--ghost:hover{border-color:var(--tp-forest)}
@media (max-width:600px){
  .tp-auth__acts{flex-direction:column-reverse;align-items:stretch}
  .tp-auth--split .tp-auth__acts .tp-auth__btn{width:100%}
}

/* The panel. */
/* A pale panel, the illustration filling it, and the card sitting low over it. */
.tp-reg__side{position:relative;overflow:hidden;background:#eef3f0;color:var(--tp-text);display:flex;flex-direction:column;justify-content:flex-end;padding:0}
.tp-reg__glow{position:absolute;border-radius:50%;filter:blur(64px);pointer-events:none}
.tp-reg__glow--a{width:340px;height:340px;background:#a8d8c4;top:-60px;right:-70px;opacity:.5;animation:tpRegDriftA 18s ease-in-out infinite alternate}
.tp-reg__glow--b{width:300px;height:300px;background:#f3cf7f;bottom:-80px;left:-60px;opacity:.4;animation:tpRegDriftB 22s ease-in-out infinite alternate}
@keyframes tpRegDriftA{to{transform:translate3d(-40px,60px,0) scale(1.15)}}
@keyframes tpRegDriftB{to{transform:translate3d(50px,-50px,0) scale(1.1)}}
.tp-reg__deck{position:relative;z-index:1;display:grid;min-height:252px;margin:0 clamp(26px,3.6vw,52px) 16px}
/* The card does not cross-fade: the one leaving lifts away, the one arriving rises into
   its place, and its tag, line and bullets follow one after another. */
.tp-reg__day{grid-area:1/1;margin:0;background:#fff;border:0;border-radius:24px;padding:26px 28px;box-shadow:0 22px 50px -26px rgba(13,61,53,.4);display:grid;gap:12px;align-content:start;pointer-events:none;
  opacity:0;transform:translateY(26px) scale(.985);transition:opacity .45s ease,transform .65s cubic-bezier(.2,.7,.2,1)}
.tp-reg__day.is-on{opacity:1;transform:none}
.tp-reg__day.is-out{opacity:0;transform:translateY(-26px) scale(.99);transition:opacity .35s ease,transform .5s cubic-bezier(.4,0,.7,.2)}
.tp-reg__daytag,.tp-reg__day figcaption,.tp-reg__day li{opacity:0;transform:translateY(9px);transition:opacity .4s ease,transform .5s cubic-bezier(.2,.7,.2,1)}
.tp-reg__day.is-on .tp-reg__daytag,.tp-reg__day.is-on figcaption,.tp-reg__day.is-on li{opacity:1;transform:none}
.tp-reg__day.is-on .tp-reg__daytag{transition-delay:.12s}
.tp-reg__day.is-on figcaption{transition-delay:.20s}
.tp-reg__day.is-on li:nth-child(1){transition-delay:.30s}
.tp-reg__day.is-on li:nth-child(2){transition-delay:.38s}
.tp-reg__day.is-on li:nth-child(3){transition-delay:.46s}
@media (prefers-reduced-motion:reduce){
  .tp-reg__day,.tp-reg__day.is-out,.tp-reg__daytag,.tp-reg__day figcaption,.tp-reg__day li{transition:none;transform:none}
  .tp-reg__day.is-out{opacity:0}
}
.tp-reg__daytag{justify-self:start;font-size:10.5px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:#2f5d33;background:#e9f2ec;border-radius:999px;padding:5px 12px}
.tp-reg__day figcaption{font-size:19px;line-height:1.35;font-weight:600;color:var(--tp-text);letter-spacing:-.01em}
.tp-reg__day ul{margin:0;padding:0;list-style:none;display:grid;gap:9px}
.tp-reg__day li{position:relative;padding-left:20px;font-size:14px;line-height:1.5;color:var(--tp-muted)}
.tp-reg__day li::before{content:"";position:absolute;left:0;top:7px;width:7px;height:7px;border-radius:50%;background:var(--tp-leaf)}
.tp-reg__dots{position:relative;z-index:1;display:flex;gap:7px;margin:0 clamp(26px,3.6vw,52px) clamp(34px,6vh,76px);padding:0}
.tp-reg__dots i{width:7px;height:7px;border-radius:999px;background:rgba(13,61,53,.2);transition:width .45s cubic-bezier(.2,.7,.2,1),background .45s ease}
.tp-reg__dots i.is-on{width:24px;background:var(--tp-leaf)}
.tp-reg__sidefoot{position:relative;z-index:1;margin:0;font-size:12.5px;line-height:1.55;color:#9fbdb2;max-width:36ch}
@media (prefers-reduced-motion:reduce){
  .tp-reg__glow,.tp-reg__progress i.is-on,.tp-reg__card .tp-auth__form > *{animation:none}
  .tp-reg__day{transition:none}
}

/* The Clients screen used to run: a paragraph, a form asking for the person's sex, a
   second form about the clinician's own contact details, and only then the list of
   clients. The list comes first now, and each of the three jobs on this screen is a
   titled section so it is clear which one you are in. */
.tp-clients__lead{margin:0 0 6px;font-size:15px;line-height:1.6;color:var(--tp-muted);max-width:74ch}
.tp-clients__block{margin-top:26px;padding-top:22px;border-top:1px solid var(--tp-line)}
.tp-clients__block:first-of-type{margin-top:18px;padding-top:0;border-top:0}
.tp-clients__block>h3{font-size:16.5px;font-weight:700;letter-spacing:-.01em;color:var(--tp-forest);margin:0 0 6px}
.tp-clients__block>p{margin:0 0 16px;font-size:14px;line-height:1.6;color:var(--tp-muted);max-width:74ch}
.tp-clients__block .tp-table{margin-top:0}
.tp-clients__block.tp-restore{display:flex;flex-wrap:wrap;align-items:center;gap:14px}
.tp-clients__needreg{margin:0 0 16px;padding:11px 14px;border-radius:9px;background:#fdf4ec;
  border-left:3px solid var(--tp-gold);color:var(--tp-text);font-size:14px;line-height:1.6;max-width:74ch}
.tp-clients__needreg b{color:var(--tp-forest)}

/* ---------------------------------------------------------------------------
   v22: the workspace chrome on a phone
   This block sits at the foot of the sheet on purpose. Several of its rules exist to
   override rules written further up, and in this file position, not specificity, is
   what decides that.
   ------------------------------------------------------------------------- */

/* The wordmark is built the way the site's brand is built: the name, then the second
   word beneath it in spaced small caps. It also reads on one line's worth of width
   instead of two, which is what let the header settle into a single row. */
.tp-logo{gap:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;font-size:14px;line-height:1.05}
.tp-logo span{display:block;width:auto;height:auto;background:none;border-radius:0;color:var(--tp-forest);
  font-size:14px;letter-spacing:.06em;line-height:1.05;text-transform:uppercase}
.tp-logo span small{display:block;font-weight:500;letter-spacing:.18em;font-size:9.5px;opacity:.75;
  text-transform:uppercase;color:inherit;margin-top:3px}
@media (max-width:600px){.tp-logo span{font-size:13px}.tp-logo span small{font-size:9px;letter-spacing:.16em}}
/* One word at every width now, so nothing has to be dropped to make the row fit. */
@media (max-width:460px){.tp-packbtn{padding:0 11px;gap:6px}}

/* Filters and the search are one line. The button sits in the library bar beside the
   search box, and the facets it opens drop over the list as a panel instead of pushing
   the whole column down. Clear and Save go inside that panel, where the filters they act
   on actually are, rather than floating on a row of their own. */
.tp-packbtn__label{display:inline}
/* The play mark that stands in for a procedure's film. White ground, a green ring that
   breathes outwards, and the triangle nudged right of centre so it sits optically true. */
.tp-scene--place{display:grid;place-items:center;width:100%;height:100%;background:#fff}
.tp-play{width:clamp(40px,26%,58px);aspect-ratio:1;border-radius:50%;display:grid;place-items:center;
  background:#fff;border:2px solid var(--tp-leaf);color:var(--tp-forest);
  box-shadow:0 0 0 0 rgba(63,157,109,.5);animation:tpPlayPulse 2.4s ease-out infinite}
.tp-play svg{width:46%;height:46%;fill:currentColor;margin-left:8%}
@keyframes tpPlayPulse{
  0%{box-shadow:0 0 0 0 rgba(63,157,109,.5);border-color:var(--tp-leaf)}
  60%{box-shadow:0 0 0 13px rgba(63,157,109,0);border-color:rgba(63,157,109,.55)}
  100%{box-shadow:0 0 0 0 rgba(63,157,109,0);border-color:var(--tp-leaf)}
}
.tp-card__scene,.tp-thumb--scene{background:#fff}
/* A tile carrying a film: its first frame, with a quiet play triangle that steps back
   once the film is running under the pointer. */
.tp-scene--tile{width:100%;height:100%;object-fit:cover;display:block;background:#fff}
.tp-tileplay{position:absolute;right:8px;bottom:8px;width:28px;height:28px;border-radius:50%;
  background:rgba(255,255,255,.92);border:1px solid var(--tp-line);display:grid;place-items:center;
  color:var(--tp-forest);pointer-events:none;transition:opacity .25s,transform .25s}
.tp-tileplay svg{width:13px;height:13px;fill:currentColor;margin-left:2px}
.tp-card__scene:hover .tp-tileplay,.tp-thumb--scene:hover .tp-tileplay{opacity:0;transform:scale(.8)}
.tp-card__scene:hover .tp-play,.tp-thumb--scene:hover .tp-play{border-color:var(--tp-forest);transform:scale(1.06)}
.tp-play{transition:transform .25s,border-color .25s}
@media (prefers-reduced-motion:reduce){.tp-play{animation:none}}

/* Favourites, on the bar beside the search rather than buried as a radio in the filter
   rail. The count counts up rather than jumping and the star kicks once, so starring a
   procedure on the far side of the screen is still felt here. */
.tp-favbtn{appearance:none;display:inline-flex;align-items:center;gap:7px;flex:0 0 auto;
  min-height:42px;padding:0 13px;border:1px solid var(--tp-line);border-radius:10px;background:#fff;
  font:600 14px var(--tp-font);color:var(--tp-muted);cursor:pointer;transition:border-color .2s,color .2s,background .2s}
.tp-favbtn svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linejoin:round}
.tp-favbtn b{min-width:22px;height:22px;padding:0 6px;border-radius:999px;background:var(--tp-bg);
  color:var(--tp-muted);font-size:12.5px;display:inline-grid;place-items:center;transition:background .2s,color .2s}
.tp-favbtn:hover{border-color:var(--tp-forest);color:var(--tp-forest)}
.tp-favbtn.has-any svg{fill:var(--tp-gold);stroke:var(--tp-gold)}
.tp-favbtn.has-any b{background:#fdf4ec;color:#8a5a0b}
.tp-favbtn.is-on{background:var(--tp-forest);border-color:var(--tp-forest);color:#fff}
.tp-favbtn.is-on b{background:rgba(255,255,255,.2);color:#fff}
.tp-favbtn.is-on svg{fill:var(--tp-gold);stroke:var(--tp-gold)}
.tp-favbtn.is-bumped{animation:tpFavBump .62s cubic-bezier(.2,.7,.2,1)}
.tp-favbtn.is-bumped svg{animation:tpFavStar .62s cubic-bezier(.2,.7,.2,1)}
.tp-favbtn.is-dropped{animation:tpFavDrop .42s ease}
@keyframes tpFavBump{
  0%{transform:none;box-shadow:0 0 0 0 rgba(217,164,65,.5)}
  35%{transform:translateY(-3px);box-shadow:0 0 0 7px rgba(217,164,65,.14)}
  100%{transform:none;box-shadow:0 0 0 0 rgba(217,164,65,0)}
}
@keyframes tpFavStar{0%{transform:none}30%{transform:scale(1.45) rotate(-12deg)}60%{transform:scale(.94) rotate(4deg)}100%{transform:none}}
@keyframes tpFavDrop{0%{transform:none}40%{transform:translateY(2px);opacity:.7}100%{transform:none}}
@media (prefers-reduced-motion:reduce){.tp-favbtn.is-bumped,.tp-favbtn.is-bumped svg,.tp-favbtn.is-dropped{animation:none}}
/* On the tab row it takes that row's shape rather than the search bar's. */
.tp-sections .tp-favbtn{min-height:0;align-self:center;margin-left:6px;padding:0 12px;height:34px;border-radius:999px}
.tp-sections .tp-favbtn b{height:20px;min-width:20px}
@media (max-width:600px){.tp-favbtn span{display:none}.tp-favbtn{padding:0 11px}.tp-sections .tp-favbtn{margin-left:2px}}

/* Nothing to list: one mark, one question, one way on. The contact details and the
   restore block wait until there is a client, or until the setup prompt asks for them. */
.tp-none{display:grid;justify-items:center;gap:14px;padding:46px 20px 52px;text-align:center}
.tp-none[hidden]{display:none}
.tp-none__mark{width:96px;height:96px;border-radius:50%;display:grid;place-items:center;
  background:#eef5f1;border:1px solid #d7e7de;color:var(--tp-forest)}
.tp-none__mark svg{width:42px;height:42px;fill:none;stroke:currentColor;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round}
.tp-none b{font-size:19px;font-weight:700;letter-spacing:-.01em;color:var(--tp-text)}
.tp-none p{margin:-8px 0 2px;font-size:15px;color:var(--tp-muted)}
.tp-view[data-view="clients"].is-empty .tp-clients__lead,
.tp-view[data-view="clients"].is-empty .tp-clients__block>h3,
.tp-view[data-view="clients"].is-empty .tp-contact,
.tp-view[data-view="clients"].is-empty .tp-restore{display:none}
.tp-view[data-view="clients"].is-empty.show-setup .tp-contact{display:block}
.tp-view[data-view="clients"].is-empty.show-setup .tp-contact>h3{display:block}

/* Asked on the way in, not on the way out. */
.tp-setup{display:flex;flex-wrap:wrap;align-items:center;gap:12px 16px;margin:0;padding:12px 22px;
  background:#fdf4ec;border-bottom:1px solid #f0dcc4;font-size:14px;line-height:1.55;color:var(--tp-text)}
.tp-setup>div{flex:1 1 320px;min-width:0}
.tp-setup b{color:var(--tp-forest)}
.tp-setup .tp-btn{padding:9px 15px;font-size:13.5px}
@media (max-width:600px){.tp-setup{padding:11px 14px;font-size:13.5px}}

/* Who the plan went to, asked once, at the moment it goes. */
.tp-gate__to{display:grid;gap:12px;margin:4px 0 2px}
@media (min-width:620px){.tp-gate__to{grid-template-columns:1.4fr 1fr}}
.tp-gate__to label{display:grid;gap:6px;font-size:13px;font-weight:600;color:var(--tp-text)}
.tp-gate__to input,.tp-gate__to select{width:100%;font:inherit;font-size:14.5px;padding:10px 12px;
  border:1px solid #cbd5d1;border-radius:9px;background:#fff;color:var(--tp-text)}
.tp-gate__to input:focus,.tp-gate__to select:focus{outline:0;border-color:var(--tp-forest);box-shadow:0 0 0 3px rgba(13,61,53,.12)}

/* Status in the client list. */
.tp-state{display:inline-flex;align-items:center;gap:6px;padding:3px 10px;border-radius:999px;
  font-size:11.5px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;
  background:var(--tp-bg);color:var(--tp-muted);border:1px solid var(--tp-line)}
.tp-state--on{background:#e8f1ec;color:var(--tp-forest);border-color:#cfe3d7}
.tp-state--on::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--tp-green)}

/* One decision per person, where the decision is made. */
.tp-edit__wbopts{display:grid;gap:8px}
@media (min-width:620px){.tp-edit__wbopts{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}}
.tp-wbopt{display:flex;align-items:center;gap:9px;padding:10px 12px;border:1px solid var(--tp-line);
  border-radius:9px;background:#fff;font-size:13.5px;cursor:pointer;transition:border-color .2s,background .2s}
.tp-wbopt:hover{border-color:var(--tp-leaf)}
.tp-wbopt.is-on,.tp-wbopt:has(input:checked){border-color:var(--tp-forest);background:#eef5f1;font-weight:600}

/* The verified method, folded away until someone wants to change it. */
.tp-edit__method{border:1px solid var(--tp-line);border-radius:10px;background:#fbfcfb;margin:4px 0}
.tp-edit__method>summary{cursor:pointer;padding:12px 14px;font-weight:600;font-size:14px;color:var(--tp-forest);
  display:flex;align-items:center;justify-content:space-between;gap:12px;list-style:none}
.tp-edit__method>summary::-webkit-details-marker{display:none}
.tp-edit__method>summary span{font-weight:500;font-size:12.5px;color:var(--tp-muted)}
.tp-edit__method>summary::after{content:"";width:8px;height:8px;flex:none;border-right:2px solid currentColor;
  border-bottom:2px solid currentColor;transform:rotate(45deg);margin-left:auto;transition:transform .2s}
.tp-edit__method[open]>summary::after{transform:rotate(-135deg)}
.tp-edit__method>section{padding:0 14px 14px}
.tp-edit__method>section:first-of-type{padding-top:4px}

/* Find a client, from the bar above the library. */
.tp-sub{align-items:center}
.tp-find{position:relative;flex:0 1 320px;min-width:0}
.tp-find__box{display:flex;align-items:center;gap:8px;padding:0 11px;height:36px;background:#fff;
  border:1px solid var(--tp-line);border-radius:9px}
.tp-find__box svg{width:15px;height:15px;flex:none;fill:none;stroke:var(--tp-muted);stroke-width:1.8;stroke-linecap:round}
.tp-find__box input{border:0;background:none;font:inherit;font-size:13.5px;color:var(--tp-text);width:100%;min-width:0;padding:0}
.tp-find__box input:focus{outline:0}
.tp-find__box:focus-within{border-color:var(--tp-forest);box-shadow:0 0 0 3px rgba(13,61,53,.1)}
.tp-find__list{position:absolute;top:calc(100% + 6px);left:0;width:min(92vw,380px);z-index:40;margin:0;padding:6px;
  list-style:none;background:#fff;border:1px solid var(--tp-line);border-radius:12px;
  box-shadow:0 26px 52px -28px rgba(13,61,53,.55);max-height:320px;overflow:auto}
.tp-find__list[hidden]{display:none}
.tp-find__list button{display:grid;gap:2px;width:100%;text-align:left;appearance:none;border:0;background:none;
  padding:9px 10px;border-radius:8px;cursor:pointer;font:inherit}
.tp-find__list button b{font-size:14px;color:var(--tp-forest)}
.tp-find__list button span{font-size:12.5px;color:var(--tp-muted)}
.tp-find__list button:hover{background:var(--tp-bg)}
.tp-find__list button.is-on{background:#eef5f1}
.tp-find__none{padding:10px 11px;font-size:13px;line-height:1.55;color:var(--tp-muted)}
.tp-sub__now{display:flex;align-items:center;gap:10px;min-width:0}
.tp-sub__now b{color:var(--tp-forest)}
@media (max-width:980px){.tp-find{flex:1 1 100%}.tp-sub__now{flex:1 1 100%}}

/* The opened procedure: the film across the top, on white, and under it the photographs
   in a row that starts at the left edge and runs along. */
.tp-detail{position:relative}
.tp-detail__track{display:flex;gap:14px;overflow-x:auto;scroll-snap-type:x mandatory;
  scrollbar-width:thin;-webkit-overflow-scrolling:touch;padding-bottom:4px}
/* Two across, so the film is never the whole of the gallery and the next photograph is
   half in view. On a phone one fills the width and the next peeks past the edge. */
.tp-detail__slide{flex:0 0 calc(50% - 7px);scroll-snap-align:start;margin:0;aspect-ratio:16/9;
  background:#fff;border:1px solid var(--tp-line);border-radius:12px;overflow:hidden;display:grid;place-items:center}
.tp-detail__slide img{width:100%;height:100%;object-fit:cover;display:block}
.tp-detail__media{width:100%;height:100%;object-fit:contain;border:0;display:block;background:#000}
.tp-detail:not(.has-more) .tp-detail__slide{flex:0 0 100%}

@media (max-width:600px){.tp-detail__slide{flex:0 0 86%}}
/* The arrows sit over the strip, out of the way of the pictures. */
.tp-detail__nav{position:absolute;top:50%;transform:translateY(-50%);z-index:2;width:38px;height:38px;
  border-radius:50%;border:1px solid var(--tp-line);background:rgba(255,255,255,.96);color:var(--tp-forest);
  display:grid;place-items:center;cursor:pointer;box-shadow:0 6px 18px -8px rgba(13,61,53,.5);
  transition:background .2s,border-color .2s,transform .2s}
.tp-detail__nav svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.tp-detail__nav:hover{background:#fff;border-color:var(--tp-forest);transform:translateY(-50%) scale(1.06)}
.tp-detail__nav--prev{left:8px}
.tp-detail__nav--next{right:8px}

/* The head reserved a 120px column for a thumbnail that is no longer drawn, so the title
   and the summary sat indented from the gallery above and the method below. */
.tp-doc__head>span:empty{display:none}
.tp-doc__head:has(>span:empty){display:block}
/* The modal's media slot was a fixed 16:7 letterbox; the gallery sets its own height. */
.tp-modal__scene{aspect-ratio:auto;overflow:visible;border-radius:0}

/* The cover of a plan that has not been issued yet. */
.tp-pack__pending{margin:-4px 0 14px;font-size:13.5px;line-height:1.6;color:var(--tp-muted)}
@media (max-width:980px){
  .tp-libbar{gap:8px;flex-wrap:wrap}
  /* The button was built to fill the rail it used to live in; beside the search it is
     only as wide as its own word. */
  .tp-libbar .tp-side__toggle{display:inline-flex;width:auto;flex:0 0 auto;margin:0;min-height:42px;padding:0 13px;gap:8px}
  .tp-libbar .tp-side__toggle i{margin-left:0}
  .tp-libbar .tp-search{flex:1 1 150px;min-width:0}
  .tp-libbar .tp-search input{height:42px}
  .tp-work{position:relative}
  .tp-side{position:absolute;top:54px;left:0;width:min(92vw,360px);z-index:30;display:grid;gap:10px;
    background:#fff;border:1px solid var(--tp-line);border-radius:12px;padding:14px;
    box-shadow:0 26px 52px -28px rgba(13,61,53,.55);max-height:min(72vh,540px);overflow:auto}
  .tp-side:not(.is-open){display:none}
  .tp-side.is-open .tp-side__scroll{display:grid;gap:10px}
  .tp-filterhead{display:flex;justify-content:flex-end;gap:10px;padding:0 0 10px;margin:0;border-bottom:1px solid var(--tp-line)}
  .tp-filterhead svg,.tp-filterhead b{display:none}
}

/* Which client is being added to is the one thing that must never leave the screen: every
   tick in the library goes to it. On a phone it was not merely scrolling away, it was
   hidden outright, so it now holds under the tab row and moves up with it. */
@media (max-width:980px){
  .tp-sub{position:sticky;top:102px;z-index:18;background:#fbfcfb;padding:5px 14px;font-size:12.5px;
    transition:top .3s cubic-bezier(.2,.7,.2,1)}
  .tp.is-down .tp-sub{top:56px}
  /* Pinned, the strip has to earn its height: the 40px touch minimum on the link was
     making a 55px bar out of one line of text. Padding gives a 51x30 target instead. */
  .tp-sub .tp-linkbtn{min-height:0;padding:4px 3px;display:inline}
}
@media (prefers-reduced-motion:reduce){.tp-sub{transition:none}}

/* Sort and the view switch were a loose label beside a plain select, next to two boxes
   carrying unicode glyphs that each font draws differently. One bordered control with the
   word inside it, and a proper switch with drawn icons and a readable label. */
.tp-sort{display:inline-flex;align-items:stretch;gap:0;border:1px solid var(--tp-line);border-radius:9px;background:#fff;overflow:hidden}
.tp-sort span{display:flex;align-items:center;padding:0 10px;background:#f2f6f4;border-right:1px solid var(--tp-line);
  font-size:11.5px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--tp-muted)}
.tp-sort select{border:0;border-radius:0;background:#fff;font:inherit;font-size:13.5px;color:var(--tp-text);
  padding:0 32px 0 10px;height:36px;cursor:pointer;-webkit-appearance:none;appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.2 6 6.2l5-5' fill='none' stroke='%235a6f68' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 11px center}
.tp-sort select:focus{outline:2px solid var(--tp-gold);outline-offset:-2px}
.tp-viewtoggle{display:inline-flex;border:1px solid var(--tp-line);border-radius:9px;overflow:hidden;background:#f2f6f4;padding:3px;gap:3px}
.tp-viewtoggle button{appearance:none;border:0;background:none;width:auto;height:30px;min-height:30px;padding:0 10px;border-radius:6px;
  display:inline-flex;align-items:center;gap:6px;color:var(--tp-muted);cursor:pointer;transition:background .2s,color .2s}
.tp-viewtoggle button svg{width:15px;height:15px;fill:currentColor;flex:none}
.tp-viewtoggle button em{font-style:normal;font-size:12.5px;font-weight:600;letter-spacing:.01em}
.tp-viewtoggle button:hover{color:var(--tp-forest)}
.tp-viewtoggle button.is-on{background:#fff;color:var(--tp-forest);box-shadow:0 1px 2px rgba(13,61,53,.16)}
/* On a phone the labels go and the two controls are set to the same height, which the
   40px touch minimum on the toggle buttons was otherwise breaking by six pixels. */
@media (max-width:600px){
  .tp-viewtoggle button em{display:none}
  .tp-viewtoggle{padding:3px}
  .tp-viewtoggle button{padding:0 11px;min-width:42px;min-height:36px;height:36px;justify-content:center}
  .tp-sort select{height:42px}
  .tp-sort span{padding:0 9px}
}

/* The row head on a phone: three controls of the same size in a cluster, the title beside
   them with its badge on the same line, and everything that follows lined up under the
   title rather than starting again at the far left. */
@media (max-width:980px){
  .tp-row__head{grid-template-columns:auto auto auto minmax(0,1fr);gap:7px 9px;align-items:center;padding:9px 11px}
  .tp-row__head button{width:30px;height:30px}
  .tp-row__check{width:38px;height:30px}
  .tp-row__title{grid-column:4}
  .tp-row__clients,.tp-row__extra{grid-column:4/-1}
}

/* ---------------------------------------------------------------------------
   v21: the library list, laid out so a procedure reads as one line of text
   ------------------------------------------------------------------------- */

/* Seven of the eight columns took a fixed width and the procedure title took whatever was
   left, so on a 1150px screen the title had about sixty pixels and "Using a walking frame
   to walk safely" came out a word to a line. Every column now states the width it actually
   needs, and where the row cannot hold them all, client IDs and additional information drop
   to a line of their own inside the row instead of crushing the title. */
.tp-row__title{display:flex;align-items:center;gap:8px;flex-wrap:wrap;line-height:1.35;min-width:0}
.tp-row__title .tp-badge{flex:none}
/* Nothing in a cell is hyphenated or split mid-word. */
.tp-list__head span,.tp-row__title,.tp-row__meta,.tp-row__extra{overflow-wrap:normal;word-break:normal;hyphens:none}
.tp-row__meta{line-height:1.35}

@media (min-width:1280px){
  .tp-list__head,.tp-row__head{
    grid-template-columns:56px 30px 30px minmax(240px,2fr) minmax(124px,148px) 58px minmax(128px,1fr) minmax(148px,1.1fr)}
}
/* Between 981 and 1280 the row cannot hold eight columns without starving the title, so the
   last two move under it, indented to the title's own left edge so the row still reads as a
   block rather than a spill. */
@media (min-width:981px) and (max-width:1279px){
  .tp-list__head,.tp-row__head{grid-template-columns:56px 30px 30px minmax(220px,1fr) minmax(120px,150px) 58px}
  .tp-list__head span:nth-child(7),.tp-list__head span:nth-child(8){display:none}
  /* Both sit on one second line, starting at the title's left edge, so the row stays a
     block of two lines rather than a stack of four. */
  .tp-row__clients{grid-column:4/5}
  .tp-row__extra{grid-column:5/-1}
  .tp-row__head{row-gap:6px}
}

/* The additional-information control is a field the width of its column, but the rule that
   makes the row's info and favourite icons 26px squares with no border was catching it too,
   so on every screen it came out as a 26px box with "+ Add information" clipped to two
   characters. Restated here, a step more specific than the icon rule. */
.tp-row__head .tp-extra{display:block;width:100%;height:auto;padding:6px 9px;
  border:1px dashed var(--tp-line);border-radius:8px;background:#fff;
  font-size:12.5px;color:var(--tp-leaf);text-align:left}
.tp-row__head .tp-extra.has-text{border-style:solid;border-color:var(--tp-gold);background:#fff9ec;color:var(--tp-text)}
.tp-row__head .tp-extra:hover{background:#fff;border-color:var(--tp-forest);color:var(--tp-leaf)}

/* The first step in the row strip. Sixty-four characters of clinical instruction were being
   poured into an 82px square and cut off wherever the box ended, mid-word, with the rest
   hidden: "Check both / surfa". It gets a card of its own width now, and the sentence stops
   at the end of a line with an ellipsis instead of at the edge of the box. An equipment
   name without a photograph uses the same square as the photographs, and is clamped too. */
.tp-thumb--step b{display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}
.tp-thumb--first{width:210px;display:flex;flex-direction:column;gap:3px;padding:9px 11px;text-align:left;place-items:normal;align-content:normal}
.tp-thumb--first b{-webkit-line-clamp:1;margin:0;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--tp-forest)}
.tp-thumb--first > span{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
  font-size:12px;line-height:1.35;color:var(--tp-muted)}
@media (max-width:600px){.tp-thumb--first{width:190px}}

/* ---------------------------------------------------------------------------
   v23. Two small things, both about not saying more than is true.

   1. The strip above the library used to announce "New plan · nothing chosen
      yet" beside a link to a screen the tab row already reaches. Both are gone.
      What is left is a quiet pill that appears only once a client exists.
   2. The empty Clients screen. One mark, one question, one way on. The hand
      taps by itself and the tap sends two rings out, so the screen reads as an
      invitation rather than a dead end.
   Keep this block last in the sheet.
   ------------------------------------------------------------------------- */
.tp-sub__now{display:inline-flex;align-items:center;gap:7px;padding:5px 12px;border-radius:999px;
  background:#eef5f1;border:1px solid #d7e7de;font-size:13px;font-weight:600;letter-spacing:.01em;
  color:var(--tp-forest);white-space:nowrap;animation:tpNowIn .35s cubic-bezier(.2,.7,.2,1) both}
.tp-sub__now[hidden]{display:none}
.tp-sub__now::before{content:"";width:7px;height:7px;flex:none;border-radius:50%;background:var(--tp-green)}
@keyframes tpNowIn{from{opacity:0;transform:translateY(-4px)}}

.tp-none{display:grid;justify-items:center;gap:0;padding:60px 20px 64px;text-align:center}
.tp-none__mark{position:relative;width:104px;height:104px;margin:0 0 24px;border-radius:50%;
  display:grid;place-items:center;background:#fff;border:1px solid #dcebe2;color:var(--tp-forest);
  box-shadow:0 14px 30px -18px rgba(13,61,53,.45);animation:tpNoneIn .6s cubic-bezier(.2,.7,.2,1) both}
@keyframes tpNoneIn{from{opacity:0;transform:scale(.9)}}
/* The rings the tap sends out. Two of them, a beat apart, from the one tap. */
.tp-none__mark i{position:absolute;inset:-1px;border-radius:50%;border:1px solid var(--tp-leaf);opacity:0;
  animation:tpNoneRipple 3.4s cubic-bezier(.22,.7,.3,1) infinite}
.tp-none__mark i:nth-of-type(2){animation-delay:.28s}
@keyframes tpNoneRipple{0%{transform:scale(1);opacity:.38}24%{opacity:.16}44%,100%{transform:scale(1.5);opacity:0}}
.tp-none__mark svg{position:relative;width:40px;height:40px;fill:none;stroke:currentColor;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round;animation:tpNoneTap 3.4s cubic-bezier(.3,.85,.35,1) infinite}
@keyframes tpNoneTap{0%,22%,100%{transform:translateY(0)}7%{transform:translateY(5px)}}
.tp-none b{font-size:21px;font-weight:700;letter-spacing:-.02em;color:var(--tp-text);
  animation:tpNoneUp .55s cubic-bezier(.2,.7,.2,1) .1s both}
.tp-none p{margin:7px 0 22px;font-size:15px;color:var(--tp-muted);
  animation:tpNoneUp .55s cubic-bezier(.2,.7,.2,1) .18s both}
.tp-none .tp-btn{min-height:46px;padding:0 24px;font-size:15px;
  animation:tpNoneUp .55s cubic-bezier(.2,.7,.2,1) .26s both}
@keyframes tpNoneUp{from{opacity:0;transform:translateY(8px)}}
@media (max-width:600px){.tp-none{padding:44px 16px 48px}.tp-none__mark{width:92px;height:92px;margin-bottom:20px}
  .tp-none__mark svg{width:36px;height:36px}.tp-none b{font-size:19px}}
@media (prefers-reduced-motion:reduce){
  .tp-sub__now,.tp-none__mark,.tp-none__mark i,.tp-none__mark svg,.tp-none b,.tp-none p,.tp-none .tp-btn{animation:none}
  .tp-none__mark i{opacity:.26}.tp-none__mark i:nth-of-type(2){display:none}
}

/* ---------------------------------------------------------------------------
   v24. Searching the Clients list. The finder in the bar above jumps to a
   client and shows you their plan; this one stays on this screen and narrows
   the list, because what you came here for is the row, with its plan code and
   its actions still attached. The heading moved inside a row of its own, so
   the empty-screen rule that used to hide it by tag now hides that row.
   ------------------------------------------------------------------------- */
.tp-clients__head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:10px 16px;margin:0 0 14px}
.tp-clients__head h3{margin:0}
.tp-clients__find{flex:0 1 300px;min-width:0}
.tp-clients__count{margin:-4px 0 12px;font-size:13px;color:var(--tp-muted)}
.tp-clients__count[hidden]{display:none}
.tp-table__none td{padding:20px 12px;font-size:14px;line-height:1.6;color:var(--tp-muted)}
.tp-view[data-view="clients"].is-empty .tp-clients__head,
.tp-view[data-view="clients"].is-empty .tp-clients__count{display:none}
@media (max-width:600px){.tp-clients__find{flex:1 1 100%}}

/* ---------------------------------------------------------------------------
   v25. Three things.

   1. Select, favourite, edit, in that order, in the list as well as on the
      cards, and drawn with the same icons in both. The ⓘ that used to lead the
      row has gone: the procedure name opens it, as it does on a card.
   2. The edit window. One procedure, built from the verified template every
      time it opens with this client's changes laid over it.
   3. The empty Clients screen: a clock, because what it is describing is a
      plan that has not been written yet. It is the full width of the panel and
      takes the panel's own border and radius, so it sits in the page as a
      block rather than floating in the middle of it.
   ------------------------------------------------------------------------- */
.tp-row__icon{appearance:none;border:0;background:none;width:28px;height:28px;border-radius:8px;
  display:grid;place-items:center;color:var(--tp-forest);cursor:pointer;padding:0}
.tp-row__icon svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}
.tp-row__icon:hover{background:#f0f5f2}
.tp-row__icon.is-on svg path{fill:var(--tp-gold);stroke:var(--tp-gold)}
.tp-row__icon:focus-visible{outline:2px solid var(--tp-forest);outline-offset:2px}

.tp-modal__edit{display:block}
/* The close cross sits in this corner, so the bar stops short of it. */
.tp-modal__editbar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:8px 16px;margin:0 0 14px;padding:0 44px 12px 0;border-bottom:1px solid var(--tp-line)}
.tp-modal__editnote{font-size:13px;color:var(--tp-muted)}
/* Opaque, not a fade: a clinician reading the last field should not be reading it
   through the button that saves it. */
.tp-modal__edit .tp-pack__bar{position:sticky;bottom:0;z-index:3;margin:18px -4px -4px;
  padding:14px 4px;background:#fff;border-top:1px solid var(--tp-line);justify-content:flex-end}

.tp-none{width:100%;max-width:none;box-sizing:border-box;padding:54px 24px 58px;
  background:linear-gradient(180deg,#fbfdfc,#f4f8f6);border:1px solid var(--tp-line);border-radius:14px}
.tp-none__mark{background:#fff;border-color:#dcebe2}
/* The ring that keeps time with the hands: one slow breath per minute sweep. */
.tp-none__mark i{position:absolute;inset:-1px;border-radius:50%;border:1px solid var(--tp-leaf);
  opacity:.3;animation:tpNoneBreathe 4s ease-in-out infinite}
@keyframes tpNoneBreathe{0%,100%{transform:scale(1);opacity:.3}50%{transform:scale(1.11);opacity:.08}}
.tp-none__mark svg{width:46px;height:46px;stroke:currentColor;fill:none;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round;animation:none}
.tp-none__face{stroke-width:1.4;opacity:.9}
.tp-none__pip{fill:currentColor;stroke:none}
/* Waiting. The minute hand goes round in two seconds, the hour hand keeps pace
   with it at a twelfth of the speed, so the face reads as time passing. */
.tp-none__hour,.tp-none__min{transform-origin:12px 12px;transform-box:view-box;stroke-width:1.7}
.tp-none__min{animation:tpClock 2s linear infinite}
.tp-none__hour{animation:tpClock 24s linear infinite}
@keyframes tpClock{to{transform:rotate(360deg)}}
@media (max-width:600px){.tp-none{padding:42px 18px 46px}.tp-none__mark svg{width:40px;height:40px}}

/* ---------------------------------------------------------------------------
   v26. The confirmation the browser cannot switch off. Chrome lets a visitor
   silence window.confirm() for a page, and a silenced confirm returns false,
   so Delete did nothing and explained nothing. This one is in the page.
   ------------------------------------------------------------------------- */
.tp-ask{position:fixed;inset:0;z-index:80;display:grid;place-items:center;padding:20px;
  background:rgba(11,31,25,.5);backdrop-filter:blur(2px);
  animation:tpAskIn .16s ease-out both}
.tp-ask[hidden]{display:none}
@keyframes tpAskIn{from{opacity:0}}
.tp-ask__card{width:min(460px,100%);box-sizing:border-box;padding:26px 26px 20px;background:#fff;
  border-radius:14px;border:1px solid var(--tp-line);box-shadow:0 30px 70px -24px rgba(0,0,0,.5);
  animation:tpAskUp .2s cubic-bezier(.2,.7,.2,1) both}
@keyframes tpAskUp{from{opacity:0;transform:translateY(10px) scale(.98)}}
.tp-ask__count{display:block;font-size:11.5px;font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  color:var(--tp-muted)}
.tp-ask__count:empty{display:none}
.tp-ask__card h2{margin:6px 0 0;font-size:19px;font-weight:700;letter-spacing:-.015em;color:var(--tp-text)}
.tp-ask__card p{margin:10px 0 0;font-size:14.5px;line-height:1.6;color:var(--tp-muted)}
.tp-ask__card p:empty{display:none}
.tp-ask__bar{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:10px;margin-top:22px}
.tp-ask__bar .tp-btn{min-height:42px}
.tp-ask__bar [hidden]{display:none}
/* Solid red only inside this dialog, where the button is the last step of something
   irreversible. In the toolbar "Clear plan" stays the quiet outlined red it was, so it
   does not compete with Save for the eye. */
.tp-ask__bar .tp-btn--del{background:var(--tp-red);border-color:var(--tp-red);color:#fff}
.tp-ask__bar .tp-btn--del:hover{background:#c8443d;border-color:#c8443d}
@media (prefers-reduced-motion:reduce){.tp-ask,.tp-ask__card{animation:none}}

/* ---------------------------------------------------------------------------
   v27. The empty Clients screen, drawn rather than illustrated. A sheet draws
   itself, three lines are written and then unwritten, and the mark that starts
   a new plan waits in the corner: a plan that has not been written yet, and an
   invitation to write one. Replaces the clock, which only said "waiting".
   ------------------------------------------------------------------------- */
.tp-none__mark svg{width:52px;height:52px;fill:none;stroke:currentColor;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round;overflow:visible;animation:none}
/* The sheet. Drawn once on arrival, then it stays. */
.tp-none__page{stroke-dasharray:102;stroke-dashoffset:102;opacity:.85;
  animation:tpSheet 1.1s cubic-bezier(.35,0,.2,1) .2s forwards}
@keyframes tpSheet{to{stroke-dashoffset:0}}
/* The writing. Each line runs on, holds while the plan reads as written, then
   runs back off, so the sheet is empty again and the loop means something. */
.tp-none__ln{stroke-dasharray:13;stroke-dashoffset:13;stroke-width:2.1;
  animation:tpWrite 5.6s cubic-bezier(.4,0,.25,1) infinite}
.tp-none__ln--1{animation-delay:1.1s}
.tp-none__ln--2{animation-delay:1.55s}
.tp-none__ln--3{animation-delay:2s;stroke-dasharray:9;stroke-dashoffset:9}
@keyframes tpWrite{0%{stroke-dashoffset:13}14%,64%{stroke-dashoffset:0}84%,100%{stroke-dashoffset:13}}
.tp-none__ln--3{animation-name:tpWrite3}
@keyframes tpWrite3{0%{stroke-dashoffset:9}14%,64%{stroke-dashoffset:0}84%,100%{stroke-dashoffset:9}}
/* The one thing to press, in the site's gold, sitting over the corner of the sheet. */
.tp-none__new circle{fill:#fff;stroke:var(--tp-gold);stroke-width:2}
.tp-none__new path{stroke:var(--tp-gold);stroke-width:2.2}
.tp-none__new{transform-origin:34px 34px;transform-box:view-box;
  animation:tpNewIn .5s cubic-bezier(.2,1.5,.4,1) 1.2s both,tpNewBeat 5.6s ease-in-out 1.7s infinite}
@keyframes tpNewIn{from{opacity:0;transform:scale(.4)}}
@keyframes tpNewBeat{0%,88%,100%{transform:scale(1)}92%{transform:scale(1.12)}}
@media (max-width:600px){.tp-none__mark svg{width:46px;height:46px}}
@media (prefers-reduced-motion:reduce){
  .tp-none__page,.tp-none__ln,.tp-none__new{animation:none}
  .tp-none__page{stroke-dashoffset:0}
  .tp-none__ln{stroke-dashoffset:0}
}

/* ---------------------------------------------------------------------------
   v28. The plan's toolbar stays one row. It wrapped to two lines on a laptop
   and broke into a two-column grid on a phone, which moved Save somewhere
   different depending on the window. One row at every width: below about
   860px it scrolls sideways instead of rearranging itself, so the order the
   clinician learned is the order it keeps.
   ------------------------------------------------------------------------- */
.tp-pack__bar--top{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;
  -webkit-overflow-scrolling:touch;margin:0 -22px;padding:8px 22px}
.tp-pack__bar--top::-webkit-scrollbar{display:none}
.tp-pack__bar--top>*{flex:none}
.tp-pack__bar--top .tp-btn{white-space:nowrap}
.tp-pack__spacer{flex:1 1 auto;min-width:8px}
/* The grid that used to take over on a phone is off; the row shortens instead. */
@media (max-width:600px){
  .tp-pack__bar--top{display:flex;grid-template-columns:none;gap:6px;margin:0 -14px;padding:8px 14px}
  .tp-pack__spacer{display:block}
  .tp-pack__modes{grid-column:auto;display:inline-flex}
  .tp-pack__modes button{flex:none}
}

/* ---------------------------------------------------------------------------
   v29. Fitting the row rather than scrolling it. Six controls cannot keep
   their full names from a 360px phone to a wide monitor, and a row that runs
   off the edge hides the one button the screen exists for. So each control
   carries a mark, a full label and a short one, and the width chooses: full
   names while they fit, short names below 1040px, and below 560px the three
   secondary controls are their mark alone while Save keeps a word. The
   accessible name is the full one at every width.
   ------------------------------------------------------------------------- */
/* Height comes from the rule, not from the padding, so taking the padding away at the
   narrow end cannot flatten a button to the height of its own text. */
.tp-pack__bar--top .tp-btn{display:inline-flex;align-items:center;justify-content:center;
  gap:8px;white-space:nowrap;min-height:40px;box-sizing:border-box}
.tp-pack__bar--top .tp-btn svg{width:16px;height:16px;flex:none;fill:none;stroke:currentColor;
  stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.tp-btn__s{display:none}
.tp-pack__spacer{min-width:0}

@media (max-width:1040px){
  .tp-pack__bar--top .tp-btn__l{display:none}
  .tp-pack__bar--top .tp-btn__s{display:inline}
  .tp-pack__bar--top{gap:8px}
}
@media (max-width:560px){
  .tp-pack__bar--top{gap:6px}
  .tp-pack__bar--top [data-pack-back] .tp-btn__s,
  .tp-pack__bar--top [data-pack-clear] .tp-btn__s,
  .tp-pack__bar--top [data-pack-print] .tp-btn__s{display:none}
  /* A mark on its own still has to be a 44px target. */
  .tp-pack__bar--top [data-pack-back],
  .tp-pack__bar--top [data-pack-clear],
  .tp-pack__bar--top [data-pack-print]{width:44px;height:40px;padding:0;justify-content:center}
  .tp-pack__bar--top [data-pack-back] svg,
  .tp-pack__bar--top [data-pack-clear] svg,
  .tp-pack__bar--top [data-pack-print] svg{width:18px;height:18px}
  .tp-pack__modes button{padding:9px 11px;font-size:12.5px}
  /* Save keeps its word rather than its mark: it is the one control here that must
     never be guessed at, and the word is shorter than the mark plus the word. */
  .tp-pack__bar--top [data-pack-save]{padding:0 13px}
  .tp-pack__bar--top [data-pack-save] svg{display:none}
}
.tp-md__s{display:none}
/* Small phones, down to 320. Everything gives up a few more pixels rather than the row
   giving up: the marks come in from 44 to 40, which is still a comfortable target, the
   toggle tightens, and Preview becomes View. Nothing is hidden and nothing wraps. */
/* ---------------------------------------------------------------------------
   v30. One row, four tabs, one component.

   Procedures, Quick-start packs and Equipment were text with an underline;
   Favourites was a bordered pill of a different height with a pale count
   badge on a pale ground. Four ways into the library that looked like two
   kinds of thing, and the count was the least legible text on the page.

   They are now the same tile: same height, same shape, same weight of type,
   and the one you are on is filled forest green. Favourites keeps its star,
   because that is the mark you press to fill it, and says Empty rather than
   showing a nought.
   ------------------------------------------------------------------------- */
.tp-sections{gap:6px;padding:7px 22px 0;overflow-x:auto;scrollbar-width:none}
.tp-sections::-webkit-scrollbar{display:none}
.tp-sections>button{flex:none}
.tp-sections button:not(.tp-newbtn){display:inline-flex;align-items:center;gap:8px;
  min-height:38px;height:38px;margin:0 0 7px;padding:0 14px;border:0;border-radius:8px;
  background:none;font:600 14px var(--tp-font);color:var(--tp-muted);white-space:nowrap}
.tp-sections button:not(.tp-newbtn):hover{background:#eef5f1;color:var(--tp-forest)}
.tp-sections button:not(.tp-newbtn).is-on,
.tp-sections button:not(.tp-newbtn).is-on:hover{background:var(--tp-forest);color:#fff}
.tp-sections button:not(.tp-newbtn):focus-visible{outline:2px solid var(--tp-forest);outline-offset:2px}

.tp-sections .tp-favbtn{border:0;background:none;border-radius:8px}
/* The two actions sit together at the far end: make a procedure, or go and edit the
   plan. Custom procedure takes the gap, so both are pushed right as a pair. */
.tp-sections .tp-newbtn{margin-left:auto}
/* button.tp-packbtn, not .tp-packbtn: the tab rule above is
   .tp-sections button:not(.tp-newbtn), which outranks a plain class and had stripped
   the fill off the one button in this row that is supposed to have it. */
.tp-sections button.tp-packbtn{flex:none;height:38px;min-height:38px;margin:0 0 7px;padding:0 13px;
  border:0;border-radius:8px;background:var(--tp-forest);color:#fff;font-size:13.5px;gap:7px;
  white-space:nowrap;align-self:center}
.tp-sections button.tp-packbtn:hover{background:var(--tp-leaf);color:#fff}
.tp-sections button.tp-packbtn svg{width:16px;height:16px}
.tp-sections button.tp-packbtn b{min-width:20px;height:20px;font-size:12px;
  background:#fff;color:var(--tp-forest)}
.tp-sections button.tp-packbtn.is-ready b{background:var(--tp-gold);color:#17302a}
/* Custom procedure came to 36 against everything else's 38. */
.tp-sections button.tp-newbtn{height:38px;min-height:38px;margin:0 0 7px;align-self:center;
  border-radius:8px;font-size:13.5px}
@media (max-width:600px){.tp-sections .tp-packbtn{padding:0 11px;font-size:13px}}

/* ---------------------------------------------------------------------------
   v34. The asterisk beside the word, not under it.

   These labels are grids, and a grid gives every child its own row, so the
   text was one row, the star was the next and the box was the third: a form
   of fifteen lines pretending to be five. They lay out as a wrapping line
   instead, with the field told to take a whole line of its own, so the star
   sits against the word it belongs to and nothing else moves.
   ------------------------------------------------------------------------- */
.tp-gate__form label,.tp-gate__to label,[data-contact-form] label{
  display:flex;flex-wrap:wrap;align-items:baseline;gap:0 5px}
.tp-gate__form label>input,
.tp-gate__to label>input,.tp-gate__to label>select,
[data-contact-form] label>input,[data-contact-form] label>select{flex:1 1 100%;margin-top:5px}
/* The star earns its own colour: it is a requirement, not decoration. */
.tp-gate__form label>b,.tp-gate__to label>b,[data-contact-form] label>b{
  color:var(--tp-red);font-weight:700;line-height:1}

/* ---------------------------------------------------------------------------
   v35. One arrow, with room around it.

   The dropdowns had three different arrows: a custom chevron sitting 11px in
   on the sort and category controls, and the browser's own on the gate's
   selects, pressed hard against the right edge with the text running up
   behind it. They all take the same mark now, the same size, 14px in, with
   the text stopped well before it.
   ------------------------------------------------------------------------- */
.tp-sort select,
.tp-gate__to select,
[data-contact-form] select,
.tp-form select,
.tp-edit__grid select{
  -webkit-appearance:none;appearance:none;
  padding-right:40px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'%3E%3Cpath d='M1.2 1.6 7 7.4l5.8-5.8' fill='none' stroke='%235a6f68' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 14px center;
  background-size:12px 8px}
/* ---------------------------------------------------------------------------
   v36. Who the plan is going to, asked once.

   It was a blank box at one end of the dialog and a "Kind of service"
   dropdown at the other, so the same answer was given twice in two different
   ways and neither one said the other was related. One box now: who they
   are, then their name, divided down the middle. Other opens a line to write
   in, and what is written is what the record keeps.
   ------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
   v37. Prompts read as prompts.

   The examples in the plan's boxes were set in the same weight as the text a
   clinician types, so an empty plan looked like a filled one and you had to
   read a line to find out whether anybody had written it. They are lighter
   now, and they go on being lighter while the box has focus, because a
   prompt is a suggestion and not a value. Every one of these boxes has a
   label above it, so nothing is carried by the prompt alone.
   ------------------------------------------------------------------------- */
body.tp-body input::placeholder,
body.tp-body textarea::placeholder{color:#a3b0aa;opacity:1;font-style:normal}
body.tp-body input::-webkit-input-placeholder,
body.tp-body textarea::-webkit-input-placeholder{color:#a3b0aa}
body.tp-body input:focus::placeholder,
body.tp-body textarea:focus::placeholder{color:#b4c0ba}

/* ---------------------------------------------------------------------------
   v38. The Clients table, read as a table.

   Nine columns of the same grey at the same weight, with the reference no
   more prominent than the word "After issuing", so nothing led the eye and
   every row had to be read in full. The reference is the thing you look for,
   so it is set as such; the headings step back; the numbers line up; the row
   under the cursor lifts; and the current client is marked rather than being
   announced by a button that had stopped being a button.
   ------------------------------------------------------------------------- */
.tp-clients__block .tp-table{width:100%;border-collapse:separate;border-spacing:0;
  border:1px solid var(--tp-line);border-radius:12px;overflow:hidden;background:#fff}
.tp-clients__block .tp-table thead th{padding:11px 14px;background:#f6f9f7;
  border-bottom:1px solid var(--tp-line);text-align:left;white-space:nowrap;
  font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--tp-muted)}
.tp-clients__block .tp-table td{padding:13px 14px;border-bottom:1px solid #eef2f0;
  font-size:13.5px;line-height:1.45;color:var(--tp-text);vertical-align:middle}
.tp-clients__block .tp-table tbody tr:last-child td{border-bottom:0}
.tp-clients__block .tp-table tbody tr{transition:background .15s}
.tp-clients__block .tp-table tbody tr:hover{background:#fafcfb}
/* The current client, marked by the row rather than by a button that says so. */
.tp-clients__block .tp-table tbody tr.is-on{background:#f2f8f5;box-shadow:inset 3px 0 0 var(--tp-forest)}
.tp-clients__block .tp-table tbody tr.is-on:hover{background:#eef5f1}
/* The reference leads. */
.tp-clients__block .tp-table td:first-child b{font-size:14px;font-weight:700;letter-spacing:-.01em;
  color:var(--tp-forest);font-variant-numeric:tabular-nums}
.tp-clients__block .tp-table td[data-l="Plans"]{font-variant-numeric:tabular-nums;text-align:center}
.tp-clients__block .tp-table th:nth-child(3){text-align:center}
.tp-clients__block .tp-table small{display:block;margin-top:2px;font-size:11.5px;color:var(--tp-muted)}
.tp-clients__block .tp-table .tp-code{font-size:12.5px;letter-spacing:.04em}
.tp-clients__block .tp-table__act{white-space:nowrap;text-align:right}
.tp-clients__block .tp-table__act .tp-btn--small{min-height:32px;padding:0 13px;font-size:12.5px;margin-right:8px}
.tp-clients__block .tp-table__act .tp-btn--small.is-on{background:var(--tp-forest)}
.tp-clients__block .tp-table__act .tp-linkbtn{font-size:12.5px}
/* One row per client at every width. Folding the table into cards on a phone repeated
   nine headings down the screen for every client and turned a list into a stack of
   forms; it scrolls sideways instead, which keeps a row a row. */
.tp-clients__scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:thin;
  border-radius:12px}
/* ---------------------------------------------------------------------------
   The list fits the screen. No sideways scroll at any width.

   It was laid out to its content and the strip scrolled, so on anything short
   of a wide monitor the last columns, including the actions, were off the
   edge. The table is a fixed layout at full width now: every column has a
   share, every cell is one line, and anything too long for its share ends in
   an ellipsis rather than pushing the table wider. Below the widths where a
   column stops being readable it steps out of the way entirely, least
   important first, so what is left is always legible and always in view.
   ------------------------------------------------------------------------- */
.tp-clients__scroll{overflow:visible}
.tp-clients__block .tp-table{width:100%;table-layout:auto}
.tp-clients__block .tp-table th,
.tp-clients__block .tp-table td{white-space:nowrap;overflow:visible;text-overflow:clip}
/* The only column whose content has no natural limit. */
.tp-clients__block .tp-table td:nth-child(7){max-width:240px;overflow:hidden;text-overflow:ellipsis}
/* The actions must never be the column that gets squeezed: they are the point of the row. */
.tp-list-table th:last-child,.tp-clients__block .tp-table__act{width:152px}
.tp-clients__block .tp-table small{display:block;margin:1px 0 0;overflow:hidden;text-overflow:ellipsis}
.tp-list-table th:nth-child(1){width:44px}
.tp-list-table th:nth-child(5){width:74px}
/* Below 900px a row stops being readable as a row: nine values across a phone is a
   squint whichever columns are dropped, and dropping any of them hides something a
   clinician came to see. Each client becomes a card instead, with every field labelled
   and nothing left out. A row on a desktop, a card on a phone, the same facts in both. */
@media (max-width:1180px){
  .tp-list-table thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%)}
  .tp-clients__block .tp-table,
  .tp-clients__block .tp-table tbody,
  .tp-clients__block .tp-table tr,
  .tp-clients__block .tp-table td{display:block;width:auto}
  .tp-clients__block .tp-table{border:0;background:none;border-radius:0}
  .tp-clients__block .tp-table tbody tr{position:relative;margin:0 0 12px;padding:8px 0 4px;
    border:1px solid var(--tp-line);border-radius:12px;background:#fff;box-shadow:none}
  /* A border, not an inset shadow: on a row whose cells are blocks the shadow paints in
     the gaps between them and reads as a dashed line down the card. */
  .tp-clients__block .tp-table tbody tr.is-on{box-shadow:none;border-left:3px solid var(--tp-forest);
    padding-left:0}
  .tp-clients__block .tp-table tbody tr.is-on td.tp-col-check{left:11px}
  .tp-clients__block .tp-table tbody tr:last-child{margin-bottom:0}
  .tp-clients__block .tp-table td{border-bottom:0;padding:5px 14px;white-space:normal;
    display:flex;align-items:baseline;justify-content:space-between;gap:16px}
  /* The label the desktop keeps in its heading row travels with the value. */
  .tp-clients__block .tp-table td[data-l]::before{content:attr(data-l);flex:none;
    font-size:11px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--tp-muted)}
  /* The reference is the card's title, not another labelled line. */
  .tp-clients__block .tp-table td:nth-child(2){padding:2px 14px 8px 44px;border-bottom:1px solid #eef2f0;margin-bottom:6px}
  .tp-clients__block .tp-table td:nth-child(2) b{font-size:15.5px}
  /* The tick sits in the card's corner, where a card is selected from. */
  .tp-clients__block .tp-table td.tp-col-check{position:absolute;top:10px;left:14px;padding:0;width:auto}
  .tp-clients__block .tp-table small{display:inline;margin:0 0 0 6px;text-align:right}
  .tp-clients__block .tp-table td:nth-child(7){max-width:none;text-align:right}
  .tp-clients__block .tp-table__act{justify-content:flex-end;gap:10px;padding:10px 14px 6px;
    margin-top:4px;border-top:1px solid #eef2f0;width:auto}
  .tp-clients__block .tp-table .tp-table__none td{justify-content:flex-start}
  .tp-clients__block .tp-table .tp-table__none td::before{content:none}
}
@media (max-width:600px){
  .tp-clients__block .tp-table td{padding-left:12px;padding-right:12px}
  .tp-clients__block .tp-table td:nth-child(2){padding-left:42px}
}

/* The Clients heading and its explanation as one full-width band: the title in its own
   column, the sentence beside it holding a readable measure rather than running the
   whole width of a monitor, which is a line no one finishes. */
.tp-clients__intro{display:grid;grid-template-columns:minmax(180px,260px) minmax(0,1fr);
  gap:8px 40px;align-items:baseline;width:100%;padding-bottom:16px;margin-bottom:4px;
  border-bottom:1px solid var(--tp-line)}
.tp-clients__intro h2{margin:0}
.tp-clients__intro .tp-clients__lead{max-width:80ch;margin:0}
@media (max-width:900px){
  .tp-clients__intro{grid-template-columns:1fr;gap:6px;padding-bottom:14px}
  .tp-clients__intro .tp-clients__lead{max-width:none}
}

/* Each procedure says where it sits in the plan, so "the third one" means something to
   the person holding it. The section heading no longer counts to one. */
.tp-pack__count{margin:0 0 6px;font-size:11.5px;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:var(--tp-muted)}
@media print{.tp-pack__count{color:#555}}

/* ---------------------------------------------------------------------------
   v39. The Clients list as a list table: tick some, sort by a column, act on
   the ticked. The pattern WordPress uses for everything it manages, because
   forty clients is the same job as forty of anything else.
   ------------------------------------------------------------------------- */
.tp-bulk{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin:0 0 12px}
.tp-bulk[hidden]{display:none}
.tp-bulk__pick select{min-width:170px}
.tp-bulk__count{margin:0;font-size:12.5px;font-weight:600;color:var(--tp-forest)}
.tp-bulk__count:empty{display:none}
/* The search sits at the far end of the same row, so the list has one strip of
   controls rather than two stacked bands saying different things. */
.tp-bulk .tp-clients__find{margin-left:auto;flex:0 1 260px}
@media (max-width:700px){.tp-bulk .tp-clients__find{margin-left:0;flex:1 1 100%}}

.tp-col-check{width:40px;padding-right:0!important}
.tp-col-num{text-align:center}
.tp-check{display:inline-grid;place-items:center;width:20px;height:20px;cursor:pointer;position:relative}
.tp-check input{position:absolute;inset:0;opacity:0;margin:0;cursor:pointer}
.tp-check span{width:17px;height:17px;border:1.5px solid #c2cfc9;border-radius:5px;background:#fff;
  transition:background .12s,border-color .12s}
.tp-check input:checked+span{background:var(--tp-forest);border-color:var(--tp-forest);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='9' viewBox='0 0 12 9'%3E%3Cpath d='M1 4.4 4.3 7.7 11 1' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:center}
.tp-check input:indeterminate+span{background:var(--tp-forest);border-color:var(--tp-forest);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='2' viewBox='0 0 10 2'%3E%3Cpath d='M1 1h8' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:center}
.tp-check input:focus-visible+span{outline:2px solid var(--tp-forest);outline-offset:2px}

/* Sortable headings: the whole heading is the control, and the arrow only shows on the
   column actually doing the sorting, as it does in every list table people know. */
.tp-list-table th.tp-col-sort{padding:0}
.tp-list-table th.tp-col-sort button{appearance:none;border:0;background:none;width:100%;
  display:flex;align-items:center;gap:6px;padding:11px 14px;cursor:pointer;
  font:700 11px var(--tp-font);letter-spacing:.08em;text-transform:uppercase;color:var(--tp-muted)}
.tp-list-table th.tp-col-sort button:hover{color:var(--tp-forest);background:#eef5f1}
.tp-list-table th.tp-col-sort i{width:0;height:0;border-left:4px solid transparent;
  border-right:4px solid transparent;border-bottom:5px solid currentColor;opacity:0;transition:opacity .12s}
.tp-list-table th.tp-col-sort button:hover i{opacity:.35}
.tp-list-table th.is-sorted button{color:var(--tp-forest)}
.tp-list-table th.is-sorted i{opacity:1}
.tp-list-table th.is-desc i{transform:rotate(180deg)}
@media (max-width:900px){.tp-list-table th.tp-col-sort button{padding:9px 12px}}
@media (max-width:1180px){
  .tp-clients__block .tp-table td{padding:11px 12px;font-size:13px}
  .tp-clients__block .tp-table thead th{padding:9px 12px}
  .tp-clients__scroll{margin-right:-14px;padding-right:14px}
}

.tp-gate__wide{grid-column:1/-1}

/* The environment follows the recipient, and is seen to do it.
   The wrapper is a flex item of the label, so it has to claim the whole line the way a
   bare field does, or the label and the field end up side by side. */
.tp-gate__to label>.tp-env{flex:1 1 100%;margin-top:5px}
.tp-gate__to label>.tp-env__say{flex:1 1 100%}
.tp-env{position:relative;display:block}
.tp-env select{width:100%}
.tp-env select{transition:opacity .2s,border-color .2s}
.tp-env.is-loading select{opacity:.45;pointer-events:none}
.tp-env.is-set select{border-color:var(--tp-green);box-shadow:0 0 0 3px rgba(63,157,109,.18)}
.tp-env__spin{position:absolute;top:50%;right:38px;width:15px;height:15px;margin-top:-7px;
  border:2px solid rgba(13,61,53,.18);border-top-color:var(--tp-forest);border-radius:50%;
  opacity:0;pointer-events:none;transition:opacity .15s}
.tp-env.is-loading .tp-env__spin{opacity:1;animation:tpEnvSpin .7s linear infinite}
@keyframes tpEnvSpin{to{transform:rotate(360deg)}}
.tp-env__say{display:block;margin-top:5px;font-size:12px;font-weight:600;line-height:1.45;
  color:var(--tp-muted);letter-spacing:0;text-transform:none}
.tp-env__say:empty{display:none}
@media (prefers-reduced-motion:reduce){.tp-env.is-loading .tp-env__spin{animation:none}}

/* Focus moves the mark's colour with the border, so the two read as one control. */
.tp-sort select:focus,
.tp-gate__to select:focus,
[data-contact-form] select:focus,
.tp-form select:focus,
.tp-edit__grid select:focus{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'%3E%3Cpath d='M1.2 1.6 7 7.4l5.8-5.8' fill='none' stroke='%230d3d35' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")}
.tp-sections .tp-favbtn svg{width:15px;height:15px;flex:none;fill:none;stroke:currentColor;
  stroke-width:1.8;stroke-linejoin:round}
/* The count reads as a count: dark on a light ground, not grey on grey. */
.tp-sections .tp-favbtn b{height:auto;min-width:0;padding:2px 8px;border-radius:6px;
  background:#e7ece9;color:var(--tp-text);font:700 12px var(--tp-font);letter-spacing:.01em}
.tp-sections .tp-favbtn.has-any svg{fill:var(--tp-gold);stroke:var(--tp-gold)}
.tp-sections .tp-favbtn.has-any b{background:#fbeccd;color:#6d4708}
.tp-sections .tp-favbtn.is-on b,
.tp-sections .tp-favbtn.is-on.has-any b{background:rgba(255,255,255,.22);color:#fff}
.tp-sections .tp-favbtn.is-on svg,
.tp-sections .tp-favbtn.is-on.has-any svg{fill:#f3cf7f;stroke:#f3cf7f}
/* Nothing to count, nothing said: the chip disappears rather than reading Empty on a
   button that is a way in, not a status. */
.tp-sections .tp-favbtn b:empty{display:none}

/* Where the procedures would have been: the star, then the word. */
.tp-empty--fav{display:grid;justify-items:center;gap:12px;padding:60px 20px 64px;text-align:center}
.tp-empty--fav .tp-empty__star{display:grid;place-items:center;width:64px;height:64px;border-radius:50%;
  background:#fdf7ec;border:1px solid #f0dcc4}
.tp-empty--fav .tp-empty__star svg{width:28px;height:28px;fill:var(--tp-gold);stroke:var(--tp-gold);
  stroke-width:1.5;stroke-linejoin:round}
.tp-empty--fav b{font-size:19px;font-weight:700;letter-spacing:-.01em;color:var(--tp-text)}

/* ---------------------------------------------------------------------------
   v31. The equipment library, organised.

   It was one flat grid of cards, each repeating its own category above the
   name of the device, so "HOISTS" was printed eleven times down a column of
   hoists in the same size as the thing it labelled. The two links at the foot
   sat at opposite ends of a row too narrow to hold them, so they wrapped onto
   two lines on some cards and one on others, and because the cards were
   different heights no two rows of links lined up.

   The category is said once, over the group it names. The card is a stack
   that ends in its actions, so the actions sit on the same line across a row
   whatever the name above them does. The links read as a pair.
   ------------------------------------------------------------------------- */
/* The two controls over the library: type to narrow, or pick a category. */
.tp-eqbar{display:flex;flex-wrap:wrap;align-items:center;gap:10px 14px;margin-top:16px;
  padding-bottom:14px;border-bottom:1px solid var(--tp-line)}
.tp-eqbar__find{flex:0 1 260px;min-width:0}
.tp-eqbar__cat{flex:0 0 auto}
.tp-eqbar__msg{flex:1 1 auto;margin:0;font-size:12.5px;color:var(--tp-muted)}
.tp-eqbar__msg:empty{display:none}
.tp-equip__item[hidden],.tp-equip__group[hidden]{display:none}
/* A device no procedure names: said plainly, not offered as a button that opens nothing. */
.tp-equip__none{font:600 12.5px var(--tp-font);color:var(--tp-muted)}
@media (max-width:600px){.tp-eqbar__find{flex:1 1 100%}.tp-eqbar__cat{flex:1 1 100%}.tp-eqbar__msg{flex:1 1 100%}}

.tp-equip__group{margin-top:26px}
.tp-equip__group:first-of-type{margin-top:18px}
.tp-equip__group>h3{display:flex;align-items:center;gap:9px;margin:0 0 2px;font-size:12.5px;
  font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--tp-forest)}
/* The count belongs beside the word it counts, so the rule that fills the line is
   pushed past it rather than the other way about. */
.tp-equip__group>h3::after{content:"";order:2;flex:1;height:1px;background:var(--tp-line)}
.tp-equip__group>h3 b{order:1;font-size:11.5px;font-weight:700;letter-spacing:0;
  padding:1px 7px;border-radius:999px;background:#eef5f1;color:var(--tp-forest)}

/* Smaller tiles: more of the library on a screen, and a device is recognised by its
   shape long before its name is read. */
.tp-equip{grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:12px;margin-top:12px}
.tp-equip__item{display:flex;flex-direction:column;gap:7px;padding:10px;border-radius:11px}
/* The whole picture, never a crop.
   The box is square because almost every photograph here is, and the image was being
   cut off at the top and bottom: a grid item will not shrink below its own intrinsic
   size unless its minimum is set to nought, so height:100% was quietly ignored and a
   300px photograph sat in a 218px box with the rest hidden. */
.tp-equip__img{aspect-ratio:1/1;border-radius:9px;background:#f7faf8;border:1px solid #edf2ef;
  padding:7px;box-sizing:border-box;overflow:hidden}
.tp-equip__img img{width:100%;height:100%;min-width:0;min-height:0;padding:0;
  object-fit:contain;display:block}
.tp-equip__item h4{margin:0;font-size:14px;font-weight:700;letter-spacing:-.01em;
  line-height:1.32;color:var(--tp-text)}
.tp-equip__models{margin:0;font-size:11.5px;line-height:1.45;color:var(--tp-muted)}
/* Pinned to the foot, so a two-line name above does not push this card's links out of
   step with the card beside it. */
.tp-equip__actions{margin-top:auto;display:flex;flex-wrap:wrap;gap:3px 12px;align-items:center;
  justify-content:flex-start;padding-top:9px;border-top:1px solid var(--tp-line)}
.tp-equip__link{appearance:none;border:0;background:none;padding:0;font:600 11.5px var(--tp-font);
  color:var(--tp-leaf);cursor:pointer;text-decoration:none;white-space:nowrap}
.tp-equip__link:hover{color:var(--tp-forest);text-decoration:underline}
.tp-equip__link:focus-visible{outline:2px solid var(--tp-forest);outline-offset:2px;border-radius:4px}
.tp-equip__link--out{color:var(--tp-muted)}
.tp-equip__none{font-size:11.5px}

/* ---------------------------------------------------------------------------
   v32. The plan editor's three decisions, told apart by looking at them.

   Discard throws the whole plan away and is filled red, on the near side of
   the gap, with Print and Save on the far side, so it is never beside the
   button that keeps the work. Each procedure ends in its own pair: keep what
   has been written here, or take this one out. A filled button and an
   outlined red one, because they are not the same kind of act.
   ------------------------------------------------------------------------- */
.tp-btn--danger{background:var(--tp-red);border:1px solid var(--tp-red);color:#fff}
.tp-btn--danger:hover{background:#c8443d;border-color:#c8443d;color:#fff}
.tp-pack__bar--top .tp-btn--danger svg{stroke:currentColor}
.tp-btn--outdanger{background:#fff;border:1px solid #e8cdc8;color:#a3271a}
.tp-btn--outdanger:hover{background:#fdf3f1;border-color:#d9b3ad;color:#7d1d13}
.tp-btn--small{min-height:36px;padding:0 14px;font-size:13px;border-radius:9px;
  display:inline-flex;align-items:center;justify-content:center}

.tp-edit__foot{display:flex;flex-wrap:wrap;align-items:center;gap:10px 12px;margin-top:20px;
  padding-top:16px;border-top:1px solid var(--tp-line)}
.tp-edit__foot [data-edit-drop]{margin-left:auto}
.tp-edit__said{font-size:12.5px;font-weight:600;color:var(--tp-green)}
.tp-edit__said:empty{display:none}
@media (max-width:600px){
  .tp-edit__foot{gap:8px}
  .tp-edit__foot .tp-btn--small{flex:1 1 auto}
  .tp-edit__foot [data-edit-drop]{margin-left:0}
}
@media print{.tp-edit__foot{display:none}}

/* ---------------------------------------------------------------------------
   v33. One height for the whole toolbar.

   Measured, it was three heights: the outlined buttons came to 45px because
   their border sat outside a 40px minimum, Save came to 43 because it has no
   border, and the Edit/Preview pair was 38. Every control is 42 now, border
   or no border, because a transparent border keeps the box the same size as
   one that shows.
   ------------------------------------------------------------------------- */
.tp-pack__bar--top>*{box-sizing:border-box}
.tp-pack__bar--top .tp-btn{height:42px;min-height:42px;padding:0 16px;font-size:14px;
  border:1px solid transparent;border-radius:10px;line-height:1}
.tp-pack__bar--top .tp-btn--ghost{border-color:var(--tp-line)}
.tp-pack__bar--top .tp-btn--danger{border-color:var(--tp-red)}
.tp-pack__bar--top .tp-pack__modes{height:42px;border-radius:10px;align-items:stretch}
.tp-pack__bar--top .tp-pack__modes button{height:100%;padding:0 16px;font-size:13.5px;line-height:1}
@media (max-width:560px){
  .tp-pack__bar--top [data-pack-back],
  .tp-pack__bar--top [data-pack-clear],
  .tp-pack__bar--top [data-pack-print]{width:44px;height:42px;padding:0}
  .tp-pack__bar--top .tp-pack__modes button{padding:0 11px;font-size:12.5px}
  .tp-pack__bar--top [data-pack-save]{padding:0 13px}
}
@media (max-width:380px){
  .tp-pack__bar--top [data-pack-back],
  .tp-pack__bar--top [data-pack-clear],
  .tp-pack__bar--top [data-pack-print]{width:40px}
  .tp-pack__bar--top .tp-pack__modes button{padding:0 8px;font-size:11.5px}
  .tp-pack__bar--top [data-pack-save]{padding:0 10px;font-size:13.5px}
}
@media (max-width:600px){
  .tp-equip{grid-template-columns:repeat(auto-fill,minmax(144px,1fr));gap:10px}
  .tp-equip__item{padding:9px;gap:6px}
  .tp-equip__item h4{font-size:13.5px}
}

/* The label stays at every width. A lone star and a number was the unreadable part. */
@media (max-width:600px){
  .tp-sections{padding:7px 14px 0;gap:4px}
  .tp-sections .tp-favbtn span{display:inline}
  .tp-sections button:not(.tp-newbtn){padding:0 11px;font-size:13.5px}
  .tp-sections .tp-favbtn{margin-left:0}
}

/* Version and last-changed date on the plan a care team reads, and the way out of a
   plan that is no longer the right one. Both print. */
.tp-pack__ver{margin:6px 0 0;padding:9px 12px;border-radius:10px;background:#fdf4ec;
  border:1px solid #f0dcc4;font-size:13.5px;line-height:1.55;color:var(--tp-text)}
.tp-pack__danger{margin:18px 0 0;padding-top:14px;border-top:1px solid var(--tp-line);
  font-size:13.5px;color:var(--tp-muted)}
.tp-linkbtn--del{color:var(--tp-red)}
@media print{.tp-pack__ver{background:none;border:1px solid #999}.tp-pack__danger{display:none}}

@media (max-width:380px){
  .tp-pack__bar--top{gap:4px;margin:0 -10px;padding:8px 10px}
  .tp-pack__modes button{padding:9px 8px;font-size:11.5px}
  .tp-md__l{display:none}
  .tp-md__s{display:inline}
  .tp-pack__bar--top [data-pack-back],
  .tp-pack__bar--top [data-pack-clear],
  .tp-pack__bar--top [data-pack-print]{width:40px}
  .tp-pack__bar--top [data-pack-save]{padding:0 10px;font-size:13.5px}
}
@media (prefers-reduced-motion:reduce){
  .tp-none__mark i,.tp-none__hour,.tp-none__min{animation:none}
  .tp-none__mark i{opacity:.26}
}

/* ---------------------------------------------------------------------------
   v40: who the plan is for, and a filter rail you can read down
   ------------------------------------------------------------------------- */

/* The pill carried a green dot, which said a client was chosen and nothing more. A person
   stands there now, drawn from the last letter of the reference. */
.tp-sub__now::before{content:none}
.tp-sub__who{width:15px;height:15px;flex:none;fill:none;stroke:currentColor;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round}

/* ---------------------------------------------------------------------------
   v43: the head on the pill
   ------------------------------------------------------------------------- */

/* Bigger than the fifteen pixels it started at, because there is a face in it now and the
   hair is what tells one head from another. It draws itself in when a client is chosen,
   stroke by stroke, and then turns a few degrees each way on a seven second cycle: enough
   that the pill is alive, not so much that anyone reading the reference beside it is
   distracted. pathLength normalises every path to one unit, so the strokes all draw at the
   same rate whatever their real length. */
.tp-sub__who{width:18px;height:18px;stroke-width:1.3;overflow:visible}
.tp-who__g{transform-box:view-box;transform-origin:12px 21px;
  animation:tpWhoTurn 7s cubic-bezier(.45,0,.55,1) infinite}
@keyframes tpWhoTurn{0%,100%{transform:rotate(-3.4deg)}50%{transform:rotate(3.4deg)}}
.tp-sub__who path{stroke-dasharray:1;stroke-dashoffset:1;
  animation:tpWhoDraw .8s cubic-bezier(.2,.7,.2,1) forwards}
.tp-sub__who path:nth-child(2){animation-delay:.09s}
.tp-sub__who path:nth-child(3){animation-delay:.17s}
.tp-sub__who path:nth-child(4){animation-delay:.25s}
@keyframes tpWhoDraw{to{stroke-dashoffset:0}}
@media (prefers-reduced-motion:reduce){
  .tp-who__g{animation:none}
  .tp-sub__who path{animation:none;stroke-dashoffset:0}
}

/* Every filter group looked like the one above it: a hairline, a small grey word, then more
   rows of the same size, so the names of the groups were the hardest thing on the rail to
   find. Physitrack's rail reads easily because the name sits out on the rail's own tint and
   the options sit in a white card beneath it: the eye counts cards instead of hunting for
   headings. The same arrangement here, in our own colours. */
.tp-side{gap:13px}
.tp-filter{border-top:0;padding:0;margin:0;gap:6px}
.tp-filter__title{padding:0 2px;font:700 11.5px var(--tp-font);letter-spacing:.07em;
  text-transform:uppercase;color:#456e5f}
.tp-filter__title::after{content:none}
.tp-filter__title b{margin-left:7px;font-size:11.5px;font-weight:700;letter-spacing:.02em;
  color:var(--tp-forest)}
.tp-filter__opts{background:#fff;border:1px solid #e2eae6;border-radius:9px;padding:4px;gap:1px}
.tp-filter--long .tp-filter__opts{max-height:236px;padding-right:2px}
@media (max-width:600px){.tp-filter--long .tp-filter__opts{max-height:172px}}

/* ---------------------------------------------------------------------------
   v41: air around the group names
   ------------------------------------------------------------------------- */

/* The arrangement was right and the spacing was not. Ten pixels between one group and the
   next left the name of a group closer to the card above it than to its own options, so it
   read as the last line of the wrong block, and the rows inside were tighter than a
   fingertip. Twenty pixels between groups, ten between a name and what it names, and rows
   a finger tall. The narrow-screen rules carry their own gap, so they are told again. */
.tp-side{padding:14px 13px}
.tp-side__scroll{gap:20px}
.tp-side.is-open .tp-side__scroll{gap:20px}
.tp-filters{display:grid;gap:20px}
.tp-filter{gap:10px;padding:0;margin:0}
.tp-filter__title{padding:0 4px;font-size:11px;letter-spacing:.09em}
.tp-filter__opts{padding:8px;gap:2px;border-radius:10px}
.tp-filter__opts label{padding:6px 9px;min-height:32px;border-radius:7px}
.tp-filterhead{padding-bottom:12px}

/* ---------------------------------------------------------------------------
   v42: the filter stays where it was opened
   ------------------------------------------------------------------------- */

/* Below 981 the line carrying Filters and the search sat in the flow and the panel was
   glued to the page beneath it. Open the filter, scroll, and both left the top of the
   screen: the only way back to the control just used was to scroll all the way up again.
   The line is held under whatever is already pinned, at an offset measured from those
   elements rather than guessed at, and the open panel is held against the window with the
   list dimmed behind it. */
@media (max-width:980px){
  /* Edge to edge, like the tab row and the client strip above it and the panel below it.
     The box runs out to both edges of the window and the padding brings the controls back
     to the column, so Filters and the search still line up with the cards while the band
     behind them is unbroken. Without it the bar was the one inset thing in a stack of
     full-width ones, with a strip of dimmed library showing down either side. */
  .tp-mainbar{position:sticky;top:var(--tp-stick,145px);z-index:16;background:var(--tp-bg);
    margin:0 calc(50% - 50vw) 14px;padding:8px calc(50vw - 50%) 6px;
    border-bottom:1px solid var(--tp-line)}
  /* Away from the top the count and sort line folds away and what is left is the line
     worth keeping: Filters, and the search. It opens out again at the top. */
  .tp.is-down .tp-mainbar .tp-toolbar{display:none}
  .tp.is-down .tp-mainbar .tp-libbar{margin-bottom:0}

  /* The rail as the desktop has it, held against the window: the same bordered card at the
     same width, hung from the foot of the bar that opened it. Edge to edge was tried and
     it stopped being the rail: it became a sheet, and the filter on a tablet should be the
     filter a clinician already knows from the desktop. */
  .tp-side.is-open{position:fixed;top:var(--tp-sidey,203px);left:0;right:auto;
    width:min(92vw,360px);max-height:calc(100vh - var(--tp-sidey,203px) - 18px);
    overflow:auto;z-index:17;box-shadow:0 26px 60px -24px rgba(11,31,25,.5);
    border-left:0;border-top-left-radius:0;border-bottom-left-radius:0;padding-left:16px}
  /* The list behind it is dimmed and the chrome above it is not, because the button that
     opened the panel is also the button that closes it and has to stay lit. Tapping the
     dimmed list closes it too. */
  /* It starts at the top of the panel, not at the top of the window. Covering the whole
     window put a grey wash over the strip between the tab row and the bar, which is page
     background and nothing to do with the list, and made the bar look thicker and darker
     the moment the filter opened. Above the panel nothing changes. */
  .tp-side.is-open ~ .tp-main::before{content:"";position:fixed;left:0;right:0;bottom:0;
    top:var(--tp-sidey,203px);z-index:15;
    background:rgba(11,31,25,.3);animation:tpDim .2s ease both}
}
@keyframes tpDim{from{opacity:0}to{opacity:1}}
/* On a short window in landscape a pinned bar costs more than it gives. */
@media (max-width:980px) and (max-height:560px){.tp-mainbar{position:static}}
@media (prefers-reduced-motion:reduce){.tp-side.is-open ~ .tp-main::before{animation:none}}

/* A panel held over the list is a panel, and a panel says what it is. The heading was
   hidden on narrow screens back when this was a box tucked under a button. */
@media (max-width:980px){
  .tp-filterhead{justify-content:flex-start;padding-top:2px}
  .tp-filterhead svg{display:block}
  .tp-filterhead b{display:inline-block}
}

/* The panel was a 360px column sitting in a 724px space on a tablet, which read as a
   dropdown that had lost its way. It runs to both edges of the window now. Inside it, the
   groups are the groups the rail has always had: one to a row, one option to a line, in
   their own bordered cards. The width was tried on the options themselves and it was
   worse, not better: three short columns turned a list you read down into a grid you have
   to scan. */
@media (max-width:980px){
  .tp-side.is-open .tp-side__scroll{display:grid;grid-template-columns:1fr;gap:20px;column-gap:0}
  .tp-side.is-open .tp-filters{display:grid;gap:20px}
}

/* No seam above the bar. Sticky elements stacked by measurement will always be a fraction
   of a pixel out somewhere, and on a page that has been scrolled before the script has
   read anything they can be ten pixels out, which showed as a slot of moving library
   between the client strip and the bar. The bar carries its own background upwards over
   that slot. It sits inside the bar's own layer, so the strip, the tab row and the header
   still pass over the top of it; the only thing it covers is the list. */
.tp-mainbar::before{content:"";position:absolute;left:0;right:0;bottom:100%;height:18px;
  background:var(--tp-bg);pointer-events:none}

/* The client strip was told to move up to 56px once the page went down, from back when the
   tab row slid away on the way down. The tab row stays now, so the strip was being pulled
   up behind it and losing its top edge: the reference read as a clipped line. It holds
   under the tab row, wherever that row happens to end. */
@media (max-width:980px){
  .tp-sub,.tp.is-down .tp-sub{top:var(--tp-stick2,109px)}
  /* Its top used to be animated, from when it slid between two pinned positions as the tab
     row came and went. It has one position now, and a transition on the top of a sticky
     element means it arrives late: scrolling down, the strip lags behind the point it
     should have stuck at and a band of moving library shows above it for a third of a
     second before it catches up. Nothing left to animate, so nothing animates. */
  .tp-sub{transition:none}
}

/* ---------------------------------------------------------------------------
   v44: the send gate says what is wrong where it is wrong
   ------------------------------------------------------------------------- */

/* A list at the foot naming six things left the clinician counting boxes to work out which
   ones. Each box carries its own line in red under itself, the box is outlined so it can be
   found without reading, and the line at the foot is a count. */
.tp-gate__say{display:block;margin:5px 0 0;font-size:12.5px;font-weight:600;line-height:1.35;
  color:#b3261e}
.tp-gate__say:empty{display:none}
.tp-gate__grid label.is-bad input,
.tp-gate__to label.is-bad input,
.tp-gate__to label.is-bad select{border-color:#b3261e;background:#fffaf9}
.tp-gate__grid label.is-bad input:focus,
.tp-gate__to label.is-bad input:focus,
.tp-gate__to label.is-bad select:focus{border-color:#b3261e;box-shadow:0 0 0 3px rgba(179,38,30,.16)}
.tp-gate__grid label.is-bad>b,.tp-gate__to label.is-bad>b{color:#b3261e}

/* ---------------------------------------------------------------------------
   v45: editing a procedure reads as a short list of decisions
   ------------------------------------------------------------------------- */

/* It was a single column of small-caps headings parted by hairlines: nothing said how many
   things there were to fill in, where one ended and the next began, or which of them was
   the one that mattered. Each decision is a numbered card now, its number in the margin,
   its brief under its title, its boxes inside its own panel. */
/* The theme's own list styling runs after this file, so the markers have to be turned off
   on the items as well as the list, or the browser numbers each card a second time in the
   margin beside the numbered badge. */
.tp-fs{list-style:none;margin:18px 0 0;padding:0;display:grid;gap:16px}
.tp-fs>li{list-style:none;margin:0;padding-left:0}
.tp-fs>li::marker{content:""}

.tp-fs__step{border:1px solid var(--tp-line);border-radius:14px;background:#fff;
  padding:16px 18px 18px;box-shadow:0 1px 0 rgba(11,31,25,.03)}
.tp-fs__head{display:grid;grid-template-columns:28px minmax(0,1fr);gap:12px;align-items:start;
  margin:0 0 12px}
.tp-fs__n{display:flex;align-items:center;justify-content:center;width:28px;height:28px;
  border-radius:50%;background:var(--tp-forest);color:#fff;font-size:13px;font-weight:700;
  font-variant-numeric:tabular-nums;flex:none}
.tp-fs__title h3{margin:3px 0 0;font-size:14.5px;font-weight:700;letter-spacing:-.01em;
  text-transform:none;color:var(--tp-text);line-height:1.3}
.tp-fs__hint{margin:5px 0 0;font-size:12.5px;line-height:1.5;color:var(--tp-muted)}
.tp-fs__body{padding-left:40px}
@media (max-width:600px){
  .tp-fs__step{padding:14px 14px 16px}
  .tp-fs__body{padding-left:0}
}

/* The weight-bearing choice is the one thing on this form a care team reads as an
   instruction, so it is the one card that looks like a choice rather than a box. */
.tp-fs__step--wb{background:#fbfdfc;border-color:#d7e7de}
.tp-fs__step--wb .tp-edit__wbopts{gap:10px}
.tp-fs__step--sling{background:#fbfcfb}

/* Inside the method card the fold carries the whole thing, so it loses the second border
   it used to draw inside the card's own. */
.tp-fs__step--method .tp-edit__method{margin:0;background:#fbfcfb}
.tp-fs__step--method .tp-edit__method>summary{font-size:13.5px}

/* The template's own section headings, inside the fold, stay small caps: they label what is
   in the box rather than naming a decision. */
.tp-edit__method h3{font-size:12px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--tp-leaf);font-weight:700}

.tp-doc--edit .tp-doc__head{margin-bottom:4px}
.tp-doc--edit .tp-doc__guidance{margin-top:16px;border:1px solid var(--tp-line);border-radius:14px;
  background:#fbfcfb;padding:14px 18px}

/* The sticky foot sat on top of the last box. The document ends above it now. */
.tp-modal__edit .tp-doc--edit{padding-bottom:6px}
.tp-edit__foot{margin-top:18px}

/* The edit window's buttons on one row: taking the procedure out at the far left, keeping
   it at the right, the gap between them saying they are not the same kind of act. */
.tp-pack__bar--edit{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.tp-pack__bar-spacer{flex:1 1 auto;min-width:0}
.tp-modal__edit .tp-edit__foot{display:none}
@media (max-width:520px){
  .tp-pack__bar--edit{gap:8px}
  .tp-pack__bar-spacer{flex-basis:100%;height:0}
}

/* Changing who the ticks are going to, beside the name of who they are going to now. */
.tp-sub{display:flex;align-items:center;gap:12px}
.tp-sub__change{appearance:none;border:1px solid #d7e7de;background:#fff;margin-left:auto;
  font:inherit;font-size:12.5px;font-weight:600;color:var(--tp-forest);
  padding:5px 12px;border-radius:999px;cursor:pointer;white-space:nowrap;flex:none}
.tp-sub__change:hover{border-color:var(--tp-forest);background:#eef5f1}

/* ---------------------------------------------------------------------------
   v46: plainer still, for staff who do not spend their day in software
   ------------------------------------------------------------------------- */

/* The numbered cards were an improvement on the hairlines and still too much furniture:
   a box inside a box inside a window, and a badge to read before the heading. What is left
   is the least that still separates one question from the next. A plain question in
   ordinary sentence case, a line of help under it, then the boxes, with a rule and a lot of
   air between sections. The controls are large enough to hit without aiming, and everything
   is one column, because a grid is one more thing to work out. */
/* The theme's own list styling runs after this file, so the indent an ol carries by
   default has to be taken off here, where this block is last and wins. */
.tp-fs{display:block;margin:4px 0 0;padding:0}
.tp-fs__step{background:none;border:0;border-radius:0;box-shadow:none;
  margin:0;padding:26px 0 4px;border-top:1px solid var(--tp-line)}
.tp-fs__step:first-child{border-top:0;padding-top:14px}
.tp-fs__n{display:none}
.tp-fs__step>h3{margin:0;font-size:17px;font-weight:700;letter-spacing:-.01em;
  text-transform:none;color:var(--tp-text);line-height:1.3}
.tp-fs__hint{margin:7px 0 0;font-size:13.5px;line-height:1.55;color:var(--tp-muted);max-width:64ch}
.tp-fs__body{padding-left:0;margin-top:14px}
.tp-fs__step--wb,.tp-fs__step--sling{background:none;border-top:1px solid var(--tp-line)}

/* Boxes you can hit without aiming, and type you can read across a desk. */
.tp-doc--edit textarea,.tp-edit__grid input,.tp-edit__grid select{font-size:15.5px;
  padding:12px 14px;border-radius:10px}
.tp-doc--edit textarea{min-height:96px;line-height:1.55}
.tp-edit__grid input,.tp-edit__grid select{min-height:50px}
.tp-edit__grid{grid-template-columns:1fr;gap:16px}
.tp-edit__grid label{font-size:14px;font-weight:600;color:var(--tp-text);gap:7px}

/* One choice to a line, each the width of the form: three short columns made the reader
   hunt for the third. */
.tp-edit__wbopts,.tp-fs__step--wb .tp-edit__wbopts{display:grid;grid-template-columns:1fr;gap:10px}
.tp-wbopt{padding:14px 16px;font-size:15px;border-radius:10px;min-height:54px}
.tp-wbopt input{width:20px;height:20px}

/* The fold reads as the button it is. */
.tp-fs__step--method .tp-edit__method{background:#fff;border-radius:10px}
.tp-fs__step--method .tp-edit__method>summary{font-size:15px;padding:14px 16px;min-height:52px}

/* The heading above the form, said once and plainly. */
.tp-doc--edit .tp-eyebrow{font-size:12.5px;letter-spacing:.06em}
.tp-doc--edit .tp-doc__summary{font-size:14.5px;line-height:1.55}

/* The bar at the foot of the edit window stopped twenty-six pixels short of the bottom,
   which is the card's own bottom padding, and the form scrolled through the gap underneath
   it. A negative bottom margin does not move a sticky element, so the padding goes instead:
   where the card holds an edit window it has none at the foot, the bar reaches the card's
   edges, and its own padding puts the buttons back on the line the content sits on. The
   bottom corners follow the card's. */
.tp-modal__card:has(.tp-modal__edit){padding-bottom:0}
.tp-modal__edit .tp-pack__bar{margin:18px -28px 0;padding:16px 28px 20px;
  border-bottom-left-radius:16px;border-bottom-right-radius:16px}
@media (max-width:600px){
  .tp-modal__card{padding:20px 18px}
  .tp-modal__edit .tp-pack__bar{margin:16px -18px 0;padding:14px 18px 18px}
}

/* "One point per line. Remove what does not apply" was printed under all six method
   sections, so a third of the fold was the same sentence repeated. Said once, at the top,
   where it is read before any of them. */
.tp-edit__once{margin:0 0 16px;font-size:13.5px;line-height:1.55;color:var(--tp-muted)}

/* Everything on this form reads from the same left edge, in one measure, with the same
   space between a label and its box. Left aligned rather than justified: justified text
   opens rivers of white down a narrow column and is harder to read for exactly the people
   this form is for. */
.tp-doc--edit,.tp-doc--edit p,.tp-doc--edit h2,.tp-doc--edit h3,
.tp-doc--edit label,.tp-doc--edit textarea,.tp-doc--edit input{text-align:left}
.tp-doc--edit .tp-doc__summary,.tp-fs__hint,.tp-edit__once{max-width:66ch}
.tp-edit__method>section{padding:0 16px 18px}
.tp-edit__method>section>h3{margin:0 0 8px}
.tp-edit__once{padding:0 16px}

/* The pill was stretching to fill the strip, which pushed the control beside it onto a line
   of its own. It keeps the width of the name it carries. */
.tp-sub{flex-wrap:nowrap}
.tp-sub__now{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis}

/* The one control on the client strip, in its two states, and they are deliberately not
   the same weight. Removing the client undoes a choice already made, so it is quiet: plain
   underlined words in red, sitting right beside the reference it acts on, where what it
   refers to is not in doubt. Choosing a client is the next thing to do when there is
   nobody, so that one stays a filled green button. Neither is pushed to the far end of the
   strip: a control that acts on something belongs next to it, not across the room. */
.tp-sub{gap:14px}
/* The strip put its two ends apart, from when it carried one thing at each end. The
   workspace strip carries a reference and the control that acts on it, so they sit
   together. The saved-plan viewer's strip still has two ends and keeps its own rule. */
.tp-sub[data-sub]{justify-content:flex-start}
.tp-sub__none{font-size:12.5px;color:var(--tp-muted)}
.tp-sub__change{margin-left:0}
.tp-sub__change--off{border:0;background:none;border-radius:4px;padding:6px 4px;
  font-size:12.5px;font-weight:600;color:#b3261e;
  text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px}
.tp-sub__change--off:hover{background:none;color:#8c1d18;text-decoration-thickness:2px}
.tp-sub__change--off:focus-visible{outline:2px solid #b3261e;outline-offset:2px}
.tp-sub__change--go{border-color:var(--tp-forest);background:var(--tp-forest);color:#fff}
.tp-sub__change--go:hover{border-color:var(--tp-leaf);background:var(--tp-leaf);color:#fff}

/* ---------------------------------------------------------------------------
   v47: the cover reads like the plans under it
   ------------------------------------------------------------------------- */

/* The cover's boxes were set in one size and the plans below them in another, so the top of
   the editor looked like a different form from the rest of it. One set of sizes for both:
   the same label, the same measure, the same box, the same space underneath. */
.tp-edit__notes{gap:7px;margin-top:18px;font-size:14px;font-weight:600;color:var(--tp-text)}
.tp-edit__notes textarea,.tp-edit__notes input{font-size:15.5px;padding:12px 14px;
  border-radius:10px;line-height:1.55}
.tp-edit__notes textarea{min-height:96px}
.tp-edit__notes input{min-height:50px}
.tp-pack__cover--edit .tp-edit__hint{margin:18px 0 0;font-size:13.5px;line-height:1.55;
  color:var(--tp-muted);max-width:66ch}
.tp-pack__cover--edit dl{margin-bottom:4px}

/* ---------------------------------------------------------------------------
   v48: a client reads in three lines, not nine
   ------------------------------------------------------------------------- */

/* On a narrow screen every client became nine labelled lines, four of which said only that
   nothing had happened yet: no code, not sent, access after issuing. A draft client now
   shows what it has and stays quiet about what it has not, and what is left runs two to a
   line. Three lines and the buttons, down from nine. */
@media (max-width:900px){
  .tp-clients__block .tp-table td.is-empty{display:none}
  .tp-clients__block .tp-table tbody tr{display:grid;grid-template-columns:1fr 1fr;
    padding:8px 0 6px;margin-bottom:10px;column-gap:14px}
  .tp-clients__block .tp-table td{padding:4px 14px;font-size:13.5px}
  .tp-clients__block .tp-table td[data-l]::before{font-size:10.5px;letter-spacing:.06em}
  /* The reference is the card's title and the buttons are its foot, so both take the width. */
  .tp-clients__block .tp-table td:nth-child(1),
  .tp-clients__block .tp-table td:nth-child(2),
  .tp-clients__block .tp-table td.tp-table__act{grid-column:1/-1}
  .tp-clients__block .tp-table td:nth-child(2){padding:2px 14px 7px 44px;margin-bottom:4px}
  .tp-clients__block .tp-table__act{padding:8px 14px 4px;margin-top:2px}
  /* A plan code is a thing you copy, so it keeps a line to itself. Seventh now: the
     carers column went in beside the count of procedures. */
  .tp-clients__block .tp-table td:nth-child(7){grid-column:1/-1}
}

/* Carers sits beside the count of procedures and reads as a number, so it is set like one:
   right aligned on a wide screen, lining figures so a column of them compares at a glance. */
.tp-clients__block .tp-table td:nth-child(6){font-variant-numeric:tabular-nums}
@media (min-width:901px){
  .tp-clients__block .tp-table td:nth-child(5),
  .tp-clients__block .tp-table td:nth-child(6),
  .tp-list-table th.tp-col-num{text-align:right}
  .tp-list-table th.tp-col-num button{justify-content:flex-end;width:100%}
}

/* Sort sits with the other two things you do to this list, and is built like the bulk
   action beside it so the row reads as one set of controls. */
.tp-bulk__sort{display:flex;align-items:center;gap:0;border:1px solid var(--tp-line);
  border-radius:8px;background:#fff;overflow:hidden;flex:none}
.tp-bulk__sort>span{padding:0 10px;font-size:11px;font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;color:var(--tp-muted);border-right:1px solid var(--tp-line);
  align-self:stretch;display:flex;align-items:center;white-space:nowrap}
.tp-bulk__sort select{appearance:none;border:0;background:transparent;font:inherit;
  font-size:13.5px;color:var(--tp-text);padding:9px 30px 9px 10px;min-height:38px;cursor:pointer;
  background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%2317302a' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 10px center;background-size:11px}
.tp-bulk__sort select:focus-visible{outline:2px solid var(--tp-gold);outline-offset:-2px}
@media (max-width:600px){
  .tp-bulk__sort{flex:1 1 100%}
  .tp-bulk__sort select{width:100%}
}

/* Searching, acting on a selection and sorting are the three things you do to this list and
   they share its one row. The search gives up width first, then the word Sort goes, since
   the wording in the box already says what it is; the select keeps its label for a reader. */
.tp-clients__find{flex:1 1 200px;min-width:0}

/* Sort is the last thing in the row and stays there: the search takes whatever width is
   going, so Sort is pushed to the far right and holds its own size. Its name is always
   shown, because a heading that disappears on a narrow screen is a heading you cannot
   rely on. */
/* One row, three places. Sort opens it, the bulk action and its Apply sit in the middle,
   the search closes it at the right edge. The two automatic margins split whatever width
   is left over equally, which is what puts the middle pair in the middle rather than
   wherever the widths happen to leave them. It stays one row until a phone, where one row
   is not possible and the search takes a line of its own. */
.tp-bulk{flex-wrap:nowrap}
.tp-bulk__sort{margin-left:0;flex:none}
.tp-bulk__pick{margin-left:auto;flex:none}
.tp-clients__find{margin-left:auto;flex:0 1 300px;min-width:150px}
@media (max-width:600px){
  .tp-bulk{flex-wrap:wrap}
  .tp-bulk__sort,.tp-bulk__pick{margin-left:0;flex:none}
  .tp-clients__find{margin-left:0;flex:1 1 100%}
}

/* The count only speaks when something is ticked. Empty, it was still an item in the row
   and still took its gap, which pushed the middle pair off centre. */
.tp-bulk__count:empty{display:none}

/* ---------------------------------------------------------------------------
   v49: the clients row as three columns
   ------------------------------------------------------------------------- */

/* Held apart by automatic margins the row could only centre its middle when the two ends
   were the same width, and it could overflow its card, which is how the search came to sit
   outside it. Three grid columns instead: an equal share at each end and the middle taking
   what it needs. The middle is exactly centred because the columns either side of it are
   equal by construction, and nothing can overflow, because a fraction of the row cannot be
   wider than the row.

   The search is the control people use, so it is the one given room: it fills its whole
   column and stands taller than the two that only ever hold a short answer. Sort and Bulk
   action are drawn down to the size of what they say. */
.tp-bulk{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:14px}
.tp-bulk__mid{display:flex;align-items:center;gap:8px;min-width:0}
.tp-bulk__sort{justify-self:start;max-width:100%}
.tp-clients__find{justify-self:stretch;width:100%;min-width:0;margin:0;flex:none}

.tp-bulk__sort,.tp-bulk__pick{min-height:34px}
.tp-bulk__sort>span,.tp-bulk__pick>span{padding:0 9px;font-size:10.5px;letter-spacing:.06em}
.tp-bulk__sort select,.tp-bulk__pick select{font-size:13px;min-height:32px;padding:6px 28px 6px 9px}
.tp-bulk__pick select{min-width:0}
.tp-bulk [data-bulk-apply]{min-height:34px;padding:0 14px;font-size:13px}

.tp-clients__find{min-height:42px}
.tp-clients__find input{font-size:14.5px}

@media (max-width:820px){
  /* Two rows rather than four cramped columns: the two short answers keep the top line,
     the search takes the one under it and all of the width. */
  .tp-bulk{grid-template-columns:auto 1fr;row-gap:10px}
  .tp-bulk__sort{justify-self:start}
  .tp-bulk__mid{justify-self:end}
  .tp-clients__find{grid-column:1/-1}
}
@media (max-width:520px){
  .tp-bulk{grid-template-columns:1fr}
  .tp-bulk__mid{justify-self:stretch}
  .tp-bulk__pick{flex:1 1 auto;min-width:0}
}

/* ---------------------------------------------------------------------------
   v50: the way into the plan, and the filter on a phone
   ------------------------------------------------------------------------- */

/* Edit plan is the one button in the row that takes you to the work rather than to another
   list, so it is the one that carries weight. Red, because a plan being built is the thing
   with consequences attached, and first in the row the moment there is a plan to edit. */
/* The rule that fills this button is .tp-sections button.tp-packbtn, which outranks a
   plain class, so these have to match it to be heard at all. */
.tp-sections button.tp-packbtn{background:#b3261e;color:#fff}
.tp-sections button.tp-packbtn:hover{background:#8c1d18;color:#fff}
.tp-sections button.tp-packbtn b,
.tp-sections button.tp-packbtn.is-ready b{background:#fff;color:#b3261e}
.tp-sections.has-plan button.tp-packbtn{order:-1;margin-right:4px}
/* The button sets its own display, which beats the browser's rule for hidden, so it has
   to be told again here or hiding it does nothing. */
.tp-sections button.tp-packbtn[hidden],button.tp-packbtn[hidden]{display:none}

/* Three things you can do to a plan from the list, so the column holding them needs room
   for three. */
.tp-list-table th:last-child,.tp-clients__block .tp-table__act{width:auto;min-width:240px}
.tp-clients__block .tp-table__act{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  justify-content:flex-end}
@media (max-width:900px){
  .tp-clients__block .tp-table__act{justify-content:flex-start;min-width:0}
}

/* The chevron on Filters turns when it is open, so the button says which way it goes. The
   arrow is two borders turned 45 degrees, so open is 225 and not 180: 180 alone points it
   back up the diagonal it came from. The rule that used to do this looked for .is-open on
   an ancestor of the button, and the button is not inside the panel, so it never fired. */
.tp-side__toggle[aria-expanded="true"] i{transform:rotate(225deg)}

/* Category, manufacturer and the search share the equipment bar's one row, and give up
   width in that order as it narrows: the two questions pair off, then the search takes a
   line of its own. */
/* Category, manufacturer and the search stay on one line at every width. The two questions
   hold their own size, the search gives up whatever is needed, and the labels drop away
   before anything wraps, because a control that has moved to a second line is a control
   the eye has to go looking for. */
.tp-eqbar{flex-wrap:nowrap;align-items:center}
.tp-eqbar__cat,.tp-eqbar__make{flex:0 1 auto;min-width:0}
.tp-eqbar__cat select,.tp-eqbar__make select{min-width:0}
.tp-eqbar__find{flex:1 1 90px;min-width:0}
@media (max-width:820px){
  .tp-eqbar__cat>span,.tp-eqbar__make>span{display:none}
  .tp-eqbar__cat select,.tp-eqbar__make select{padding-left:10px}
}

/* ---------------------------------------------------------------------------
   v51: the panels take the whole width of a small screen
   ------------------------------------------------------------------------- */

/* On a phone the page's twelve pixel gutter was costing a card room on both edges and
   buying a rounded corner nobody needs at that size. The panel runs to both edges instead
   and keeps a comfortable gutter of its own inside: the margin is worked out from the
   width it is given rather than written as a number, so it stays right if that gutter
   ever changes. */
/* Every width, not just the small ones: the page gutter was costing every panel room on
   both edges and buying a rounded corner that earns nothing. The margin is worked out from
   the width the panel is given rather than written as a number, so it stays right if that
   gutter ever changes. */
.tp-view>.tp-panel{margin-left:calc(50% - 50vw);margin-right:calc(50% - 50vw);
  padding-left:clamp(16px,4vw,34px);padding-right:clamp(16px,4vw,34px);
  border-left:0;border-right:0;border-radius:0}

/* ---------------------------------------------------------------------------
   v52: one gutter, at the edge of the content, on every screen
   ------------------------------------------------------------------------- */

/* The page carried a gutter of its own and then every card inside it carried another, so
   content sat two insets in from the glass and the panels had to be pulled back out with
   negative margins to undo it. The gutter belongs to the content now: the views and the
   plan editor run edge to edge, and each thing inside them sets the space it needs, once.
   It grows with the screen rather than stepping between two fixed numbers. */
.tp{--tp-gut:clamp(16px,4vw,34px)}
.tp-view,.tp-pack{padding-left:0;padding-right:0}
.tp-view>.tp-panel{margin-left:0;margin-right:0;
  padding-left:var(--tp-gut);padding-right:var(--tp-gut)}
.tp-locked{max-width:none}

/* ---------------------------------------------------------------------------
   v53: one gutter, the same on both sides, everywhere
   ------------------------------------------------------------------------- */

/* Running to the glass was tried and it is not the right answer: content that touches the
   edge of the screen reads as though it has been cropped, and on a phone a card flush to
   the bezel is a card you tap the edge of by accident. There is one gutter now, set once,
   the same on the left as on the right, and everything sits inside it: the views, the plan
   editor, the panels and the bar that spans behind them. It grows with the screen, from
   16px on a phone to 32 on a wide window, which is the range these layouts normally use.

   The bar keeps a background that reaches both edges, because that is what a bar is, but
   what is printed on it starts on the same line as the cards underneath. */
.tp{--tp-gut:clamp(16px,3.5vw,32px)}
.tp-view,.tp-pack{padding-left:var(--tp-gut);padding-right:var(--tp-gut)}
.tp-view>.tp-panel{margin-left:0;margin-right:0;
  padding-left:clamp(16px,2.4vw,26px);padding-right:clamp(16px,2.4vw,26px);
  border-left:1px solid var(--tp-line);border-right:1px solid var(--tp-line);border-radius:14px}
.tp-work,.tp-pack>*{margin-left:0;margin-right:0}
.tp-pack>.tp-pack__cover,.tp-pack>.tp-pack__plan{border-left:1px solid var(--tp-line);
  border-right:1px solid var(--tp-line);border-radius:14px}
@media (max-width:980px){
  .tp-mainbar{margin-left:calc(0px - var(--tp-gut));margin-right:calc(0px - var(--tp-gut));
    padding-left:var(--tp-gut);padding-right:var(--tp-gut)}
}

.tp-side__done{display:none}
@media (max-width:600px){
  /* On a phone the panel takes the width it is given and reaches the foot of the window,
     so it reads as the sheet it is rather than a box that happened to land there. */
  /* A column with three parts: the head, the list that scrolls, and the way out. Sticky
     inside a scrolling grid put Done wherever the scroll happened to be; a flex column
     holds it at the foot because the middle part is the only thing that can grow. */
  .tp-side.is-open{left:0;right:0;width:auto;height:calc(100vh - var(--tp-sidey,203px));
    max-height:none;border-radius:0;border-left:0;border-right:0;border-bottom:0;
    display:flex;flex-direction:column;overflow:hidden;padding:12px 16px 0}
  .tp-side.is-open .tp-filterhead{flex:none}
  .tp-side.is-open .tp-side__scroll{flex:1 1 auto;min-height:0;overflow-y:auto;
    -webkit-overflow-scrolling:touch;padding-bottom:12px}
  .tp-side.is-open .tp-side__done{flex:none;display:block;margin:0 -16px;
    padding:15px 16px calc(15px + env(safe-area-inset-bottom));width:calc(100% + 32px);
    border:0;border-top:1px solid #e2eae6;background:#fff;font:inherit;font-size:15px;
    font-weight:700;color:var(--tp-forest);cursor:pointer;text-align:center}
  .tp-side.is-open .tp-side__done:hover{background:#eef5f1}
}

/* The same row on a wide screen, half a line shorter. */
.tp-clients__block .tp-table td{padding-top:9px;padding-bottom:9px}
.tp-clients__block .tp-table small{line-height:1.35}

/* ---------------------------------------------------------------------------
   v55: the pricing page lines up with itself
   ------------------------------------------------------------------------- */

/* The three buttons sat on three different lines, because each card stacked its own
   parts and the feature lists are different lengths. Subgrid puts all three cards on
   one set of rows, so the prices, the leads, the lists, the buttons and the small print
   each sit on the same line across the row. It is the only way to align them without
   padding the copy out to match. */
.tp-price__list{align-content:start}
@supports (grid-template-rows:subgrid){
  .tp-pricing__grid{grid-template-rows:auto auto auto 1fr auto auto}
  .tp-price{display:grid;grid-row:span 6;grid-template-rows:subgrid;row-gap:14px}
  .tp-price>.tp-auth__btn{margin-top:6px}
  .tp-price>.tp-auth__small{margin:0;min-height:0}
  /* Two cards on a row and the third across the foot: twelve rows, not six. */
  @media (max-width:1180px){
    .tp-pricing__grid{grid-template-rows:auto auto auto 1fr auto auto auto auto auto 1fr auto auto}
  }
  /* Stacked, so there is nothing to line up with. */
  @media (max-width:820px){
    .tp-pricing__grid{grid-template-rows:none}
    .tp-price{display:flex;flex-direction:column;grid-row:auto;grid-template-rows:none}
  }
}

/* The questions were inset 110px from the cards above them on both sides, which reads as
   a mistake rather than as a reading measure. They take the width of the section; the
   answers keep their own measure, which is what actually protects the line length. */
.tp-pricing .tp-pricing__faqhead,.tp-pricing .tp-faq__group,.tp-pricing .tp-pricing__faq{
  width:100%;margin-left:0;margin-right:0}

/* One heading over the whole set. It was drawn as an eyebrow, the same size, colour and
   rule as THE PLATFORM and THE PLANS under it, so the five groups read as five sections
   instead of as parts of one FAQ. */
.tp-pricing__faqhead{display:block;font-size:clamp(22px,2.2vw,27px);font-weight:700;
  letter-spacing:-.01em;text-transform:none;color:var(--tp-text);
  margin:44px 0 4px;padding-top:26px;border-top:1px solid var(--tp-line)}
.tp-pricing__faqhead::before{display:none}

/* ---------------------------------------------------------------------------
   v56: the answers read like answers
   ------------------------------------------------------------------------- */

/* The answer ran straight on from the question in the same block, a size smaller than
   anything else on the page and with no line between the two. A rule under the question
   while it is open, the body size the rest of the page uses, and a measure that holds at
   a readable length however wide the card gets. */
.tp-pricing__faq summary{padding:18px 22px;font-size:16.5px}
.tp-pricing__faq details[open] summary{border-bottom:1px solid var(--tp-line)}
.tp-pricing__faq details[open] summary{color:var(--tp-forest)}
.tp-pricing__faq p{padding:17px 22px 21px;font-size:15.5px;line-height:1.75;max-width:68ch}

/* ---------------------------------------------------------------------------
   v57: one lockup, on every page
   ------------------------------------------------------------------------- */

/* Signing in, signing up, opening a plan with a code and setting a password drew their
   own mark: a larger badge beside "Optimised Handling" on one line in sentence case at
   23px, where every other page carries the same badge with OPTIMISED over HANDLING at
   14px. It is the header lockup now, at the header's size and in the header's case, so
   the site does not introduce itself twice in two different voices. */
.tp-auth__logo{flex-direction:row;align-items:center;justify-content:center;
  gap:11px;text-align:left;font-size:14px;letter-spacing:.06em;
  text-transform:uppercase;line-height:1.05;margin:0 0 22px}
.tp-auth__logo img{width:30px;height:auto}
.tp-auth__logo span{display:block;width:auto;height:auto}
@media (max-width:600px){ .tp-auth__logo{font-size:14px;margin-bottom:16px} }
/* The split screen runs everything down the left, so the mark starts at the left too. */
@media (min-width:981px){
  .tp-auth--split > .tp-auth__logo{justify-content:flex-start;gap:11px;font-size:14px}
}

/* ---------------------------------------------------------------------------
   v58: the client row fits its panel
   ------------------------------------------------------------------------- */

/* The row ran off the side of the panel. The block above put white-space:nowrap on every
   cell and took the sideways scroll off the strip, but left the table on
   table-layout:auto, so the table's width became the sum of eleven cells that refuse to
   wrap: 1318px inside an 848px panel on a 960px window, 445px of it past the edge, with
   the whole page scrolling sideways to reach the actions. That block's own comment
   describes a fixed layout with a share per column and an ellipsis for anything too
   long. This is that layout.

   A fixed table is the width of its box and never a pixel more, whatever is in it. The
   shares below add up to 100, so there is nothing left over to overflow with. */
@media (min-width:1181px){
  .tp-clients__block .tp-table{table-layout:fixed;width:100%}
  .tp-clients__block .tp-table th,
  .tp-clients__block .tp-table td{overflow:hidden;text-overflow:ellipsis;
    padding-left:10px;padding-right:10px}
  .tp-clients__block .tp-table th:nth-child(1){width:3.5%}
  .tp-clients__block .tp-table th:nth-child(2){width:11%}
  .tp-clients__block .tp-table th:nth-child(3){width:8.5%}
  .tp-clients__block .tp-table th:nth-child(4){width:9.5%}
  .tp-clients__block .tp-table th:nth-child(5){width:5.5%}
  .tp-clients__block .tp-table th:nth-child(6){width:6%}
  .tp-clients__block .tp-table th:nth-child(7){width:11.5%}
  .tp-clients__block .tp-table th:nth-child(8){width:10%}
  .tp-clients__block .tp-table th:nth-child(9){width:8%}
  .tp-clients__block .tp-table th:nth-child(10){width:7.5%}
  .tp-clients__block .tp-table th:nth-child(11){width:19%}
  /* The actions are the point of the row, so they are the column that keeps its width;
     between the card layout and a wide monitor they hold their line on a smaller type. */
  .tp-clients__block .tp-table__act{white-space:nowrap}
}
@media (min-width:1181px) and (max-width:1400px){
  .tp-clients__block .tp-table__act{gap:8px}
  .tp-clients__block .tp-table__act .tp-btn{padding-left:9px;padding-right:9px;font-size:12.5px}
  .tp-clients__block .tp-table__act .tp-linkbtn{font-size:12.5px}
}

/* ---------------------------------------------------------------------------
   v59: the actions line up, and nothing is cut off with no way to read it
   ------------------------------------------------------------------------- */

/* The three actions wrapped into a stack. The cell is a flex row with flex-wrap:wrap, so
   the moment the column was a few pixels short the buttons broke one under the other and
   the column stopped reading as a column. They stay on one line now. Each button also
   carried margin-right:8px on top of the row's 8px gap, which put 16px between them and
   8px of nothing after the last, so the right edge never lined up with the row above.
   The gap does the spacing; the margin is gone. */
.tp-clients__block .tp-table__act{display:flex;flex-wrap:nowrap;align-items:center;
  justify-content:flex-end;gap:10px;white-space:nowrap}
.tp-clients__block .tp-table__act .tp-btn--small{margin-right:0;flex:none}
.tp-clients__block .tp-table__act .tp-linkbtn{flex:none}

/* "Issued to" is the only column holding something a person typed, so it is the only one
   that cannot be sized from what it contains. It was cut off mid-word with nothing to
   click and no way to read the rest. It wraps instead: two or three short lines, all of
   it on the page. Every other column stays on one line, because every other column holds
   a value of known length. */
@media (min-width:1181px){
  .tp-clients__block .tp-table td[data-l="Issued to"]{white-space:normal;overflow:visible;
    text-overflow:clip;line-height:1.35}
  .tp-clients__block .tp-table td[data-l="Issued to"] small{white-space:normal}
  /* Room for it, taken from the columns whose width is a fixed number of characters. */
  .tp-clients__block .tp-table th:nth-child(2){width:10.5%}
  .tp-clients__block .tp-table th:nth-child(3){width:7.5%}
  .tp-clients__block .tp-table th:nth-child(4){width:8.5%}
  .tp-clients__block .tp-table th:nth-child(5){width:5%}
  .tp-clients__block .tp-table th:nth-child(6){width:5.5%}
  .tp-clients__block .tp-table th:nth-child(7){width:11%}
  .tp-clients__block .tp-table th:nth-child(8){width:14%}
  .tp-clients__block .tp-table th:nth-child(9){width:7.5%}
  .tp-clients__block .tp-table th:nth-child(10){width:7.5%}
  .tp-clients__block .tp-table th:nth-child(11){width:19.5%}
  /* A row is as tall as its longest cell now, so the rest sit against the top of it
     rather than floating in the middle of a cell they do not fill. */
  .tp-clients__block .tp-table td{vertical-align:top}
  .tp-clients__block .tp-table td.tp-table__act{vertical-align:middle}
}

/* ---------------------------------------------------------------------------
   v60: the mark is the size the page it sits on asks for
   ------------------------------------------------------------------------- */

/* One lockup, two jobs. In a header it sits in a row of navigation and stays out of the
   way; on a sign-in screen it is the only thing above the card and has to carry the page.
   Making the two identical put the header's 14px wordmark on a screen with nothing else
   on it, which read as a footnote rather than as a name. Same drawing, same proportions,
   same case: one size for a bar, a larger one for a page. */

/* In the bar, above the workspace and above a shared plan. */
.tp-top .tp-logo{gap:12px;font-size:15.5px}
.tp-top .tp-logo img{width:34px}
.tp-top .tp-logo span{font-size:15.5px}
.tp-top .tp-logo span small{font-size:10px;letter-spacing:.19em;margin-top:3px}
@media (max-width:600px){
  .tp-top .tp-logo{gap:10px;font-size:14px}
  .tp-top .tp-logo img{width:30px}
  .tp-top .tp-logo span{font-size:14px}
  .tp-top .tp-logo span small{font-size:9px;letter-spacing:.16em}
}

/* On its own page: signing in, signing up, opening a plan with a code, setting a
   password. The mark leads, and the card sits under it. */
.tp-auth__logo{gap:15px;font-size:22px;margin-bottom:30px}
.tp-auth__logo img{width:48px}
.tp-auth__logo span{font-size:22px;letter-spacing:.05em}
.tp-auth__logo span small{font-size:12px;letter-spacing:.2em;margin-top:5px}
@media (max-width:600px){
  .tp-auth__logo{gap:12px;font-size:18px;margin-bottom:22px}
  .tp-auth__logo img{width:40px}
  .tp-auth__logo span{font-size:18px}
  .tp-auth__logo span small{font-size:10.5px;letter-spacing:.18em;margin-top:4px}
}
@media (min-width:981px){
  .tp-auth--split > .tp-auth__logo{gap:15px;font-size:22px;margin-bottom:26px}
}

/* ---------------------------------------------------------------------------
   v62: the plan carries the way into itself
   ------------------------------------------------------------------------- */

/* A carer holding a printed plan should not have to type TP-57VR-722R into a phone on a
   landing. The square, the code and the three steps sit together on the plan, on the
   screen that issues the code and in the email, in the same words each time. */
.tp-open{display:grid;grid-template-columns:auto minmax(0,1fr);gap:20px;align-items:start;
  margin:18px 0 0;padding:18px 20px;border:1px solid var(--tp-line);border-radius:12px;
  background:#f7faf9;break-inside:avoid;page-break-inside:avoid}
.tp-open__qr{line-height:0}
.tp-open__qr svg,.tp-open__qr img{display:block;width:132px;height:132px;border-radius:8px;
  border:1px solid var(--tp-line);background:#fff}
.tp-open__body h3{margin:0 0 4px;font-size:15px;font-weight:700;color:var(--tp-forest);
  letter-spacing:-.01em}
.tp-open__code{margin:0 0 10px;font-size:13.5px;color:var(--tp-muted)}
.tp-open__code b{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:15px;
  letter-spacing:.06em;color:var(--tp-text)}
.tp-open__body ol{margin:0;padding:0;list-style:none;display:grid;gap:7px;
  counter-reset:tpopen;font-size:13.5px;line-height:1.55;color:var(--tp-text)}
.tp-open__body li{counter-increment:tpopen;padding-left:27px;position:relative}
.tp-open__body li::before{content:counter(tpopen);position:absolute;left:0;top:1px;
  width:19px;height:19px;border-radius:50%;background:var(--tp-forest);color:#fff;
  font-size:11px;font-weight:700;display:grid;place-items:center;line-height:1}
@media (max-width:620px){
  .tp-open{grid-template-columns:1fr;justify-items:center;text-align:center;gap:14px}
  .tp-open__body li{text-align:left}
}
/* On paper the square is the point of the block, so it keeps its ink. */
@media print{
  .tp-open{background:#fff;border:1px solid #bbb}
  .tp-open__qr svg,.tp-open__qr img{width:118px;height:118px;
    -webkit-print-color-adjust:exact;print-color-adjust:exact}
}

/* ---------------------------------------------------------------------------
   v63: the shared plan is a document, not a workspace
   ------------------------------------------------------------------------- */

/* The client strip belongs to the workspace, where it names the client every tick in the
   library is going to, and where its sticky offset is measured from a header with a tab
   row under it. The shared plan has neither. It inherited the offset anyway: pinned at
   109px under a header 56px tall, it floated in the middle of the page with a band of
   plan showing above it and the cover running underneath. On a wide screen it was never
   sticky at all, so the page already disagreed with itself.

   A carer opening a plan reads one document from the top. The client reference is its
   heading, three lines above. The strip sits in the flow, at every width. */
.tp--viewer .tp-sub{position:static;top:auto;z-index:auto;transition:none}

/* ---------------------------------------------------------------------------
   v64: a carer can print the plan
   ------------------------------------------------------------------------- */

/* There was no way to print a shared plan on a phone. The header nav is hidden below
   980px and opened by the hamburger, but the hamburger belongs to the workspace: the
   viewer has no such button, so the plan code, the print control and the sign-in link
   were all unreachable on the device most carers open a plan on. Above that width the
   control was there but drawn as a bare word in muted grey, which is not what an action
   looks like.

   The viewer keeps its header row at every width, and printing is a button. */
.tp--viewer .tp-nav{display:flex;position:static;flex-direction:row;align-items:center;
  justify-content:flex-end;flex-wrap:wrap;gap:10px;margin-left:auto;padding:0;flex:0 1 auto;
  background:none;border:0;box-shadow:none}
.tp--viewer .tp-nav a{padding:0;min-height:0;border:0;border-radius:0;font-size:13px;
  color:var(--tp-muted);text-decoration:underline;text-underline-offset:3px;background:none;
  text-transform:none;letter-spacing:0;font-weight:500}
.tp--viewer .tp-nav a:hover{color:var(--tp-forest)}
.tp--viewer .tp-nav__code{white-space:nowrap}

/* Printing is the one thing a carer does with a plan besides read it, so it is the one
   thing in the header that looks like it can be pressed. Scoped to the header: the bar
   at the foot carries the same data attribute, and an attribute selector one class
   deeper was quietly winning over the bar's own size and shape. */
.tp--viewer .tp-top [data-viewer-print]{display:inline-flex;align-items:center;gap:8px;
  min-height:40px;padding:0 17px;border-radius:999px;border:1px solid var(--tp-forest);
  background:var(--tp-forest);color:#fff;font:600 14px/1 var(--tp-font);
  white-space:nowrap;cursor:pointer;text-align:left;
  box-shadow:0 8px 20px -14px rgba(13,61,53,.9)}
.tp--viewer .tp-top [data-viewer-print]:hover{background:var(--tp-leaf);border-color:var(--tp-leaf)}
.tp--viewer .tp-top [data-viewer-print]:focus-visible{outline:3px solid var(--tp-gold);outline-offset:2px}
.tp--viewer .tp-top [data-viewer-print]::before{content:"";flex:none;width:16px;height:16px;
  background:currentColor;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9V3h12v6'/%3E%3Cpath d='M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2'/%3E%3Crect x='6' y='14' width='12' height='7'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9V3h12v6'/%3E%3Cpath d='M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2'/%3E%3Crect x='6' y='14' width='12' height='7'/%3E%3C/svg%3E") center/contain no-repeat}

/* On a phone the header holds the mark and the action. The plan code is the document's
   own heading and appears on it twice over, so it does not need a third airing up here. */
@media (max-width:760px){
  .tp--viewer .tp-nav__code{display:none}
  .tp--viewer .tp-nav{gap:8px}
  .tp--viewer .tp-top [data-viewer-print]{padding:0 14px;font-size:13.5px}
  /* The mark already links to the sign-in page, so the link beside it only pushed the
     header onto a second row for a route a carer never takes. */
  .tp--viewer .tp-nav a{display:none}
  .tp--viewer .tp-top{padding-top:10px;padding-bottom:10px;gap:10px}
}

/* ---------------------------------------------------------------------------
   v65: the print action follows the reader down the page
   ------------------------------------------------------------------------- */

/* Two labels, one button. "Print / save as PDF" is 217px of a 390px header, which is
   most of the row for something the reader has not asked for yet. On a phone the header
   says Print and the long label waits for a screen with room. Only one is ever in the
   accessibility tree, so the button is still announced once. */
.tp-print__short{display:none}
@media (max-width:760px){
  .tp-print__full{display:none}
  .tp-print__short{display:inline}
  .tp--viewer .tp-top [data-viewer-print]{padding:0 13px;gap:6px;min-height:36px;font-size:13px}
  .tp--viewer .tp-top [data-viewer-print]::before{width:15px;height:15px}
}

/* A carer reads to the end of the plan and then wants it on paper. On a phone that is a
   long scroll back to the header, so the action waits at the foot of the screen instead,
   where a thumb already is. It is the same button as the one in the header. */
.tp-printbar{display:none}
@media (max-width:760px){
  .tp-printbar{display:block;position:fixed;left:0;right:0;bottom:0;z-index:30;
    padding:10px 16px calc(10px + env(safe-area-inset-bottom));
    background:rgba(255,255,255,.94);backdrop-filter:saturate(140%) blur(10px);
    -webkit-backdrop-filter:saturate(140%) blur(10px);
    border-top:1px solid var(--tp-line);box-shadow:0 -10px 30px -22px rgba(11,31,25,.5)}
  .tp-printbar__btn{display:flex;align-items:center;justify-content:center;gap:9px;
    width:100%;min-height:48px;border-radius:999px;border:1px solid var(--tp-forest);
    background:var(--tp-forest);color:#fff;font:600 15px/1 var(--tp-font);cursor:pointer}
  .tp-printbar__btn:active{background:var(--tp-leaf);border-color:var(--tp-leaf)}
  .tp-printbar__btn:focus-visible{outline:3px solid var(--tp-gold);outline-offset:2px}
  .tp-printbar__btn::before{content:"";flex:none;width:17px;height:17px;background:currentColor;
    -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9V3h12v6'/%3E%3Cpath d='M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2'/%3E%3Crect x='6' y='14' width='12' height='7'/%3E%3C/svg%3E") center/contain no-repeat;
    mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9V3h12v6'/%3E%3Cpath d='M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2'/%3E%3Crect x='6' y='14' width='12' height='7'/%3E%3C/svg%3E") center/contain no-repeat}
  /* The bar floats over the page, so the page ends above it rather than behind it. */
  .tp--viewer{padding-bottom:calc(74px + env(safe-area-inset-bottom))}
}
/* Neither control belongs on the paper. */
@media print{.tp-printbar{display:none!important}}

/* ---------------------------------------------------------------------------
   v66: the plan on paper
   ------------------------------------------------------------------------- */

/* The shared plan renders each procedure as .tp-pack__numbered; the workspace preview
   renders .tp-pack__plan. Every print rule named only the second, so a carer printing
   the plan they were actually sent got no page breaks at all: procedures ran into one
   another and a heading landed wherever the text happened to reach, which is what a
   heading in the middle of a page is. Both names are handled here, and the rules below
   decide where paper is allowed to break rather than leaving it to chance. */
@media print{
  @page{size:A4;margin:14mm 13mm}

  /* One procedure to a page. The cover, with the code and the square, keeps its own. */
  .tp-pack__numbered,.tp-pack__plan{break-before:page;page-break-before:always;
    break-inside:auto;page-break-inside:auto;border:0;border-radius:0;padding:0 0 10px}
  .tp-pack__cover{break-inside:auto;page-break-inside:auto}

  /* A heading never ends a page, and never parts from the lines under it. */
  .tp-pack h1,.tp-pack h2,.tp-pack h3,.tp-pack h4,
  .tp-pack__section,.tp-pack__count,.tp-doc__head,.tp-open__body h3{
    break-after:avoid;page-break-after:avoid;break-inside:avoid;page-break-inside:avoid}

  /* A step, a check or a stop sign is one thought: it does not straddle two sheets. */
  .tp-pack li,.tp-pack tr,.tp-pack dt,.tp-pack dd{
    break-inside:avoid;page-break-inside:avoid}
  .tp-pack p,.tp-pack li{orphans:3;widows:3}

  /* Blocks that mean nothing split in half. */
  .tp-open,.tp-pack__contact,.tp-doc__control,.tp-doc__note,.tp-pack__ver,
  .tp-doc__chips,.tp-pack__cover dl{break-inside:avoid;page-break-inside:avoid}

  /* A table that has to split carries its headings onto the next sheet. */
  .tp-pack table{break-inside:auto;page-break-inside:auto}
  .tp-pack thead{display:table-header-group}
  .tp-pack tfoot{display:table-footer-group}

  .tp-pack img{max-width:100%;height:auto;break-inside:avoid;page-break-inside:avoid}
}

/* ---------------------------------------------------------------------------
   v61: the sign-up page is one column, and everything is in it
   ------------------------------------------------------------------------- */

/* The split screen runs its content down a single left column, and gives every child of
   it the same left margin. Two children took that margin back: .tp-auth__aside sets
   "margin:22px 0 0" and the lockup sets a margin shorthand of its own, and a shorthand
   resets all four sides. Both are single class selectors declared after the column rule,
   so both won, and both sat at x=0 against the window edge while the card and the footer
   started at 90. The column's margin is restored to them by name. */
@media (min-width:981px){
  .tp-auth--split > .tp-auth__logo,
  .tp-auth--split > .tp-auth__aside{margin-left:clamp(28px,7vw,96px);margin-right:28px}
}

/* Below the split the second panel is gone, so there is no column to sit beside: it is
   one centred stack, like every other screen that has no panel. It was left aligned with
   a different width per child, 520 for the lockup and the aside, 560 for the card, and
   its own measure for the footer, so nothing lined up with anything. One measure,
   centred. */
@media (max-width:980px){
  .tp-auth--split{justify-items:center}
  .tp-auth--split > *,
  .tp-auth--split > .tp-auth__card{width:min(540px,100%);margin-left:auto;margin-right:auto}
  .tp-auth--split > .tp-auth__logo{justify-content:center}
  .tp-auth--split > .tp-auth__aside{text-align:center}
  .tp-auth--split > .tp-auth__links--foot{justify-content:center}
  .tp-auth--split > .tp-auth__foot{text-align:center}
}
