/* Letterpress Studio: the drawn house style, and the only stylesheet every page
   loads. Warm ink-black stock with visible grain, surfaces that are pressed into
   the page rather than floated over it, one cut corner on everything that holds
   content, small-caps eyebrows over ruled heads, and a burnt-amber accent that
   is only ever allowed on controls, active state and focus - never on structure,
   because a reseller repaints it. */
@font-face{font-family:Fraunces;font-style:normal;font-weight:400 700;font-display:swap;
  src:url(/static/fonts/fraunces-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:Fraunces;font-style:normal;font-weight:400 700;font-display:swap;
  src:url(/static/fonts/fraunces-latin-ext.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400 600;font-display:swap;
  src:url(/static/fonts/plex-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400 600;font-display:swap;
  src:url(/static/fonts/plex-latin-ext.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}

:root{
  /* Ink and stock. Five surfaces, each one step of the same warm black, so a
     card on a card on a well still reads as paper and not as a stack of greys. */
  --bg:#141210;--card:#1f1b18;--raised:#26211d;--sunk:#100e0c;--edge:#0c0a09;
  --line:#332c26;--rule:#2a241f;--text:#f2ede6;--muted:#b9afa4;
  --accent:#d97d3d;--ink:#17120e;
  /* The accent washes - focus halo, drag tint, selection - mixed from the
     accent itself, so a reseller's colour repaints them too instead of leaving
     our amber behind on a teal tenant. Literal amber first for the few engines
     without colour-mix. */
  --halo:rgba(217,125,61,.16);--tint:rgba(217,125,61,.07);
  --sel:rgba(217,125,61,.28);
  --good:#6fae7c;--warn:#e0a73b;--bad:#d96363;
  /* Radius by component, and the bottom-left corner of a sheet is cut square:
     that one asymmetry is the house signature and appears on every surface. */
  --r-sm:3px;--r-md:7px;--r-lg:11px;--cut:2px;
  --sheet:var(--r-md) var(--r-md) var(--r-md) var(--cut);
  --sheet-lg:var(--r-lg) var(--r-lg) var(--r-lg) var(--cut);
  /* Depth is a pressed edge, not a drop shadow: a hairline of light on the top
     lip, a hairline of ink under the bottom one. */
  --press:inset 0 1px 0 rgba(255,255,255,.055),0 1px 0 rgba(0,0,0,.4);
  --press-hi:inset 0 1px 0 rgba(255,255,255,.085),0 2px 0 rgba(0,0,0,.45);
  --well:inset 0 1px 2px rgba(0,0,0,.5),inset 0 -1px 0 rgba(255,255,255,.03);
  --lift:0 10px 26px rgba(0,0,0,.42);
  --deep:0 22px 54px rgba(0,0,0,.55);
  /* Spacing on a 4px stave. Named by step so a card, a rail and a table gutter
     cannot drift apart by a quarter of a rem. */
  --s1:.25rem;--s2:.5rem;--s3:.75rem;--s4:1rem;--s5:1.5rem;--s6:2rem;
  --s7:3rem;--s8:4.5rem;
  --fast:140ms cubic-bezier(.4,0,.2,1);--slow:220ms cubic-bezier(.16,1,.3,1);
  --head:Fraunces,Georgia,serif;
  --body:'IBM Plex Sans',system-ui,-apple-system,Segoe UI,sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
  /* Paper. Turbulence at low opacity, fixed to the viewport so it reads as the
     stock the page is printed on rather than a texture that scrolls with it. */
  --grain:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='g'><feTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='160' height='160' filter='url(%23g)'/></svg>");
}
@supports (color:color-mix(in srgb,red,blue)){
  :root{--halo:color-mix(in srgb,var(--accent) 16%,transparent);
    --tint:color-mix(in srgb,var(--accent) 7%,transparent);
    --sel:color-mix(in srgb,var(--accent) 28%,transparent)}
}
*{box-sizing:border-box}
/* Anything the browser still draws itself - a select's dropped list, a date
   picker, a scrollbar on an old engine - is told which room it is in. */
html{-webkit-text-size-adjust:100%;color-scheme:dark;accent-color:var(--accent)}
body{margin:0;background:var(--bg);color:var(--text);
  font:16px/1.6 var(--body);font-feature-settings:"kern" 1,"liga" 1;
  text-rendering:optimizeLegibility}
body::before{content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
  background-image:var(--grain);background-size:160px 160px;opacity:.05}
header,main,footer,.shell{position:relative;z-index:1}
/* A modal sits in the top layer and the browser centres it on the viewport;
   giving every dialog position:relative put it back in the page, so one opened
   halfway down a long list appeared above the top of the window. */
dialog[open]{position:fixed;inset:0;margin:auto}
/* Display type is set tight and optically dark; body copy stays open. */
h1,h2,h3{font-family:var(--head);font-weight:600;letter-spacing:-.012em;
  color:var(--text)}
h4{font-family:var(--head);font-weight:600;color:var(--text)}
h1{font-size:clamp(1.5rem,1.2rem + 1.1vw,1.95rem);line-height:1.15;
  margin:0 0 var(--s4)}
h2{font-size:1.12rem;line-height:1.25;margin:0 0 var(--s3)}
h3{font-size:.98rem;margin:0 0 var(--s2)}
p{margin:0 0 var(--s3)}
a{color:var(--accent);text-decoration:none}
a:hover{text-decoration:underline;text-decoration-thickness:1px;
  text-underline-offset:2px}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;
  border-radius:var(--r-sm)}
::selection{background:var(--sel)}
b,strong{font-weight:600}
/* The platform scrollbar - a grey trough with two arrow buttons - was the last
   piece of chrome the app did not draw itself, and a sideways one across a
   table read as part of the page. Firefox takes the two colours; Chrome and
   Safari take the parts. */
*{scrollbar-width:thin;scrollbar-color:#4a4038 transparent}
::-webkit-scrollbar{width:11px;height:11px}
::-webkit-scrollbar-track{background:var(--sunk);
  box-shadow:inset 0 1px 2px rgba(0,0,0,.45)}
::-webkit-scrollbar-thumb{background:#4a4038;border:2px solid var(--sunk);
  border-radius:99px}
::-webkit-scrollbar-thumb:hover{background:#5f5348}
::-webkit-scrollbar-thumb:active{background:var(--accent)}
::-webkit-scrollbar-corner{background:var(--sunk)}
/* No arrow buttons: nothing else in the app asks to be clicked twelve times. */
::-webkit-scrollbar-button{display:none}
/* Anything that is a number a buyer compares lines up in its column. */
table,.price,.clock,.figure,code,kbd,.months li b{font-variant-numeric:tabular-nums}
.skip{position:absolute;left:-9999px;top:0;padding:.5rem .8rem;z-index:60;
  background:var(--raised);border:1px solid var(--line);color:var(--text)}
.skip:focus{left:.6rem;top:.6rem}

/* --- the eyebrow, the rule and the tick --------------------------------- */
/* Three marks do most of the hierarchy work on every page: a small-caps label
   above a heading, a hairline that fades instead of stopping dead, and a short
   accent tick that says "this is the live one". */
.eyebrow{font-family:var(--body);font-size:.68rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
  margin:0 0 var(--s2)}
.rule{border:0;height:1px;margin:var(--s5) 0;
  background:linear-gradient(90deg,rgba(255,255,255,.16),rgba(255,255,255,0))}
hr{border:0;height:1px;margin:var(--s4) 0;
  background:linear-gradient(90deg,rgba(255,255,255,.16),rgba(255,255,255,0))}

/* --- signed-in chrome: a drawn rail, not a bar of dropdowns ------------- */
.shell{display:grid;grid-template-columns:15.5rem minmax(0,1fr);
  min-height:100vh}
.rail{position:sticky;top:0;align-self:start;height:100vh;display:flex;
  flex-direction:column;gap:var(--s4);padding:var(--s4) var(--s3) var(--s3);
  background:var(--card) linear-gradient(180deg,rgba(255,255,255,.02),
  rgba(0,0,0,.18));border-right:1px solid var(--line);overflow:auto}
.rail .logo{padding:var(--s1) var(--s2) var(--s2);font-size:1.12rem;
  border-bottom:1px solid var(--rule)}
/* Twenty-five destinations at reading spacing stood 1,277px tall, so a laptop
   screen hid Settings and everything under it behind a scroll nobody saw: the
   rail is set at menu spacing instead, and the whole app fits the screen. */
.rail nav{display:flex;flex-direction:column;gap:var(--s2);flex:1}
.railgroup{display:flex;flex-direction:column}
.railgroup .eyebrow{margin:0 0 var(--s1);padding-left:var(--s2);font-size:.62rem;
  color:#8d8378}
.railgroup a{display:flex;align-items:center;gap:.55rem;padding:.2rem .55rem;
  line-height:1.3;
  border-radius:var(--sheet);color:var(--muted);font-size:.9rem;
  border:1px solid transparent;transition:color var(--fast),
  background var(--fast),border-color var(--fast)}
.railgroup a .ic{width:17px;height:17px;flex:none;opacity:.72}
.railgroup a:hover{background:var(--raised);color:var(--text);
  text-decoration:none}
.railgroup a.on{background:var(--raised);color:var(--text);
  border-color:var(--line);box-shadow:var(--press)}
.railgroup a.on .ic{opacity:1;color:var(--accent)}
.railgroup a.on::before{content:"";width:2px;height:.95rem;margin-left:-.55rem;
  margin-right:.3rem;border-radius:2px;background:var(--accent)}
.burger{display:none}
/* The board: one strip of account furniture, then the page. */
.board{display:flex;flex-direction:column;min-width:0}
.bench{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;
  padding:.6rem var(--s5);border-bottom:1px solid var(--line);
  background:linear-gradient(180deg,rgba(255,255,255,.022),rgba(0,0,0,.14))}
.bench .kbd{margin-left:0;width:15rem;justify-content:space-between;
  color:#8d8378}
.bench .kbd:hover{color:var(--text)}
.bench .meta{margin-left:auto;gap:var(--s3)}
.bench .quota{font-variant-numeric:tabular-nums;white-space:nowrap}
/* Signing out is not a peer of the plan and the allowance it sits beside: it is
   set smaller and put the far side of a hairline. */
.bench .meta>a.ghost{font-size:.85rem;padding-left:var(--s3);
  border-left:1px solid var(--line)}
.bench .meta>a.ghost:hover{color:var(--text);text-decoration:none}
.bench .crumbs{margin:0}

/* --- signed-out chrome --------------------------------------------------- */
.topbar{display:flex;align-items:center;gap:var(--s5);padding:.75rem var(--s5);
  border-bottom:1px solid var(--line);background:var(--card);flex-wrap:wrap}
.logo{display:flex;align-items:center;gap:var(--s2);font-family:var(--head);
  font-weight:600;color:var(--text);letter-spacing:-.015em}
.logo:hover{text-decoration:none}
.logo img{height:26px}
.topbar nav{display:flex;gap:.35rem;flex:1;flex-wrap:wrap;align-items:center}
.topbar nav a{color:var(--muted)}
.topbar nav a.on{color:var(--text);border-bottom:2px solid var(--accent)}
.kbd{background:var(--sunk);border:1px solid var(--line);color:var(--muted);
  border-radius:var(--sheet);padding:.3rem .6rem;font:inherit;font-size:.82rem;
  cursor:pointer;display:flex;align-items:center;gap:.3rem;
  box-shadow:var(--well);transition:color var(--fast),border-color var(--fast)}
.kbd:hover{border-color:var(--accent);color:var(--text)}
kbd{background:var(--raised);border:1px solid var(--line);
  border-radius:var(--r-sm);padding:0 .3rem;font:inherit;font-size:.72rem;
  box-shadow:0 1px 0 rgba(0,0,0,.4)}
#palette{width:min(34rem,92vw);padding:var(--s3);background:var(--card);
  color:var(--text);border:1px solid var(--line);border-radius:var(--sheet-lg);
  box-shadow:var(--deep)}
#palette::backdrop{background:rgba(10,8,7,.66)}
#palette input{width:100%;font-size:1rem;padding:.6rem .7rem}
#palette ul{list-style:none;margin:var(--s3) 0 var(--s1);padding:0;
  max-height:19rem;overflow:auto}
#palette li a{display:flex;justify-content:space-between;gap:var(--s4);
  padding:.45rem .6rem;border-radius:var(--r-sm);color:var(--text)}
#palette li a span{color:var(--muted);font-size:.82rem}
#palette li.on a,#palette li a:hover{background:var(--raised);
  text-decoration:none}
/* The house's own "are you sure": the platform confirm() box is grey, names the
   host above the question, and cannot be dressed. */
dialog.ask{width:min(24rem,92vw);padding:var(--s5);background:var(--card);
  color:var(--text);border:1px solid var(--line);border-radius:var(--sheet-lg);
  box-shadow:var(--deep)}
dialog.ask::backdrop{background:rgba(10,8,7,.66)}
dialog.ask p{margin:0 0 var(--s4)}
dialog.ask .row{justify-content:flex-end}
/* What a field says when the browser refuses it: the native bubble points at
   the control from outside the page and vanishes on the next click. */
.said{display:block;margin-top:.3rem;color:var(--bad);font-size:.78rem;
  letter-spacing:0}
[aria-invalid="true"]{border-color:var(--bad)}
.meta{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.pill{display:inline-flex;align-items:center;gap:.3rem;background:var(--accent);
  color:var(--ink);border-radius:99px 99px 99px 4px;padding:.14rem .62rem;
  font-size:.8rem;font-weight:600;box-shadow:var(--press)}
.pill:hover{text-decoration:none}
.pill.up{background:none;border:1px solid var(--accent);color:var(--text);
  box-shadow:none;font-weight:400}
.quota{color:var(--muted);font-size:.85rem}
.ghost{color:var(--muted)}

/* --- the page ----------------------------------------------------------- */
.wrap{max-width:1100px;margin:0 auto;padding:var(--s5);width:100%}
/* A 1,100px column in the middle of a wide screen left 300px of empty paper
   either side of the work, and the shop showed three voices where five fit: the
   signed-in page grows with the window instead, and the prose inside it keeps
   its own measure so nothing runs to a hundred characters a line. */
.board .wrap{max-width:1500px}
/* Pages that are one thing to read rather than a board of panels keep the
   narrower measure: a voice's facts across 1,500px is a table adrift. */
.board .wrap.read{max-width:1140px}
/* A table of nine short facts stretched across a page-wide card read as a
   fragment adrift in it: the card is the width of what it holds. */
.board .wrap.read>.card{max-width:46rem}
.board .wrap.read>.card.voicehead{max-width:none}
.board .card>p,.board .card>.muted,.board .card>.note,
.board .card>form>p,.board .card>ul,.board .card>ol{max-width:78ch}
.pagehead{margin:0 0 var(--s5)}
.pagehead h1{margin:0}
.pagehead .lede{margin:.35rem 0 0}
.titlerow{display:flex;align-items:baseline;gap:var(--s3);flex-wrap:wrap;
  justify-content:space-between}
.titlerow h1{margin-bottom:.2rem}
.lede{color:var(--muted);max-width:46rem}
.muted{color:var(--muted);font-size:.85rem}
.note{color:var(--muted);font-size:.82rem}
.err,.error,.bad{color:var(--bad);font-size:.9rem}
.ok{color:var(--good);font-size:.85rem}
[hidden]{display:none!important}

/* A card is a pressed sheet: cut corner, lit top lip, inked bottom edge, and a
   head that is ruled off from its body. */
.card{background:var(--card);border:1px solid var(--line);
  border-radius:var(--sheet);padding:var(--s5) var(--s5) var(--s4);
  margin-bottom:var(--s5);box-shadow:var(--press)}
.card>h2:first-child,.card>form>h2:first-child{position:relative;
  padding-bottom:var(--s2);margin-bottom:var(--s3);
  border-bottom:1px solid var(--rule)}
.card>h2:first-child::after{content:"";position:absolute;left:0;bottom:-1px;
  width:2.2rem;height:1px;background:var(--accent)}
.card.narrow{max-width:480px}
.card.quiet{background:none;box-shadow:none}
/* Nothing here, or nothing you may see: said once, centred, in a card the width
   of the sentence rather than a full-bleed panel with a line in the corner. */
.card.empty{text-align:center;padding:var(--s7) var(--s5);max-width:36rem;
  margin-inline:auto}
.card.empty h1,.card.empty h2{margin:0 0 var(--s2)}
.card.empty h2::after{display:none}
.card.empty .lede,.card.empty .muted{margin-left:auto;margin-right:auto;
  max-width:30rem}
.card.empty .row{justify-content:center;margin-top:var(--s5)}
/* Two forms of different lengths: the shorter one ends where its content ends
   rather than stretching into a panel of empty paper. */
.grid.two{display:grid;grid-template-columns:1fr 1fr;gap:var(--s5);
  align-items:start}
.grid.three{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s5)}
/* A grid child is min-width:auto by default, so one wide code block inside a
   card pushed the whole column past the viewport on a phone. */
.grid.two>*,.grid.three>*{min-width:0}
/* A short form beside a wide table: halves left the table too narrow to show
   its own controls, so the form keeps only the room a form needs. */
.grid.aside{display:grid;grid-template-columns:minmax(0,19rem) minmax(0,1fr);
  gap:var(--s5);align-items:start}
.grid.aside>*{min-width:0}
/* The work first, the guidance beside it: a second filled card of the same size
   read as a second half of the page. */
.grid.work{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,20rem);
  gap:var(--s6);align-items:start}
.grid.work>*{min-width:0}
/* A panel holding one sentence should not weigh the same as a panel holding a
   month of figures: it keeps the heading and loses the fill. */
.card.flat{background:none;box-shadow:none;border:0;border-radius:0;
  border-top:1px solid var(--rule);padding:var(--s4) 0 0}
.card.flat>h2{margin-top:0}
.card.sidenote{background:none;box-shadow:none;border:0;border-radius:0;
  border-left:1px solid var(--rule);padding:var(--s1) 0 var(--s1) var(--s5)}
.card.sidenote h2{font-family:var(--body);font-size:.8rem;font-weight:600;
  letter-spacing:.12em;text-transform:uppercase;color:var(--muted);
  border:0;padding:0;margin:0 0 var(--s3)}
.card.sidenote h2::after{display:none}
.card.sidenote p,.card.sidenote li{color:var(--muted);font-size:.86rem}
.card.sidenote ul{padding-left:1.1rem;margin:0 0 var(--s4)}
.card.sidenote li{margin-bottom:var(--s2)}
.card.sidenote .subhead{margin-top:var(--s4)}

/* --- controls ----------------------------------------------------------- */
label{display:block;margin-bottom:var(--s3);color:var(--muted);
  font-size:.78rem;letter-spacing:.03em}
label em{font-style:normal;text-transform:uppercase;font-size:.66rem;
  letter-spacing:.1em;color:var(--muted);margin-left:.3rem}
form.is-busy{opacity:.7}
button[disabled]{opacity:.55;cursor:progress}
/* A tick and a sentence, not a row of flex items: as a flex container every
   word-and-link in the sentence became its own column, so a label that
   mentioned /cleanup broke into three. The box hangs in the indent instead. */
label.check{display:block;position:relative;padding-left:1.45rem;
  font-size:.85rem;line-height:1.5;letter-spacing:0;color:var(--text)}
label.check>input[type=checkbox],label.check>input[type=radio]{
  position:absolute;left:0;top:.2rem;margin:0}
/* A label's caption belongs above its control. Left inline, a menu narrower
   than the room left on the line sat beside the word instead, so one page had
   labels above and labels beside. */
label>input:not([type=checkbox]):not([type=radio]),label>select,
label>textarea{display:block}
input,select,textarea{width:100%;margin-top:.3rem;padding:.55rem .7rem;
  background:var(--sunk);color:var(--text);border:1px solid var(--line);
  border-radius:var(--sheet);font:inherit;font-size:.95rem;
  box-shadow:var(--well);transition:border-color var(--fast),
  box-shadow var(--fast)}
input:hover,select:hover,textarea:hover{border-color:#4a4038}
input:focus,select:focus,textarea:focus{border-color:var(--accent);
  box-shadow:var(--well),0 0 0 3px var(--halo);outline:none}
input::placeholder,textarea::placeholder{color:#8d8378}
/* Chrome paints a remembered value pale blue and its own text on top, which
   turned a signed-in look into a browser dialogue: the sunk field is kept by
   filling it with a long inset shadow, the only thing autofill leaves alone. */
input:-webkit-autofill,input:-webkit-autofill:hover,
input:-webkit-autofill:focus{-webkit-text-fill-color:var(--text);
  -webkit-box-shadow:0 0 0 100px var(--sunk) inset,var(--well);
  caret-color:var(--text)}
/* A search field's platform clear button is a grey circled cross that appears
   only in webkit, at a size nothing else on the page uses. */
input[type=search]::-webkit-search-cancel-button{-webkit-appearance:none;
  width:.8rem;height:.8rem;cursor:pointer;
  background:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='11' height='11' viewBox='0 0 11 11' fill='none' stroke='%23b9afa4' stroke-width='1.6' stroke-linecap='round'><path d='M1.5 1.5l8 8M9.5 1.5l-8 8'/></svg>") center/contain no-repeat}
input[type=search]::-webkit-search-cancel-button:hover{opacity:.75}
/* And the date/time picker's own grey glyph. */
input::-webkit-calendar-picker-indicator{opacity:.75;cursor:pointer;
  filter:invert(72%) sepia(9%) saturate(340%) hue-rotate(348deg)}
/* A drawn chevron: the platform arrow is the giveaway that nobody dressed the
   form. One warm stroke, same angle as the icon set. */
select{appearance:none;-webkit-appearance:none;padding-right:2rem;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9' fill='none' stroke='%23b9afa4' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'><path d='M1.4 1.6 7 7.2l5.6-5.6'/></svg>");
  background-repeat:no-repeat;background-position:right .7rem center}
select:disabled{opacity:.6}
/* A drawn tick. accent-color still left the platform's own box and its blue
   halo, so a form read as half dressed. The input keeps every job it had. */
input[type=checkbox],input[type=radio]{appearance:none;-webkit-appearance:none;
  width:1.05rem;height:1.05rem;flex:none;margin-top:0;padding:0;
  background:var(--sunk);border:1px solid var(--line);
  border-radius:var(--r-sm) var(--r-sm) var(--r-sm) 1px;
  box-shadow:var(--well);cursor:pointer;
  transition:border-color var(--fast),background var(--fast)}
input[type=radio]{border-radius:99px}
input[type=checkbox]:hover,input[type=radio]:hover{border-color:#4a4038}
input[type=checkbox]:checked,input[type=radio]:checked{
  background:var(--accent);border-color:var(--accent);box-shadow:var(--press)}
input[type=checkbox]:checked{
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='10' viewBox='0 0 12 10' fill='none' stroke='%2317120e' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M1.3 5.2 4.4 8.3 10.7 1.6'/></svg>");
  background-repeat:no-repeat;background-position:center}
input[type=radio]:checked{background:var(--sunk);box-shadow:var(--well);
  background-image:radial-gradient(circle at center,var(--accent) 0 .27rem,
    transparent .28rem)}
input[type=checkbox]:focus-visible,input[type=radio]:focus-visible{
  outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--halo)}
input[type=checkbox]:disabled,input[type=radio]:disabled{opacity:.55;
  cursor:not-allowed}
input[type=file]{padding:.45rem .5rem;font-size:.85rem}
/* The drawn file picker. The native input keeps every job it had - click, drop,
   keyboard, the posted part - and lies transparent across the box, so this is a
   coat of paint rather than a replacement widget. With JS off, files.js never
   runs, no .filepick exists, and the plain input above is what shows. */
.filepick{position:relative;display:flex;align-items:center;gap:var(--s3);
  margin-top:.3rem;padding:.6rem .7rem;background:var(--sunk);
  border:1px dashed var(--line);border-radius:var(--sheet);
  box-shadow:var(--well);color:var(--muted);
  transition:border-color var(--fast),color var(--fast)}
.filepick input[type=file]{position:absolute;inset:0;width:100%;height:100%;
  margin:0;padding:0;opacity:0;cursor:pointer;box-shadow:none;border:0}
.filepick:hover,.filepick.over{border-color:var(--accent)}
.filepick.over{background:var(--tint)}
.filepick:focus-within{border-color:var(--accent);
  box-shadow:var(--well),0 0 0 3px var(--halo)}
.filepick.has{border-style:solid;color:var(--text)}
.fp-face{display:flex;align-items:center;gap:var(--s3);min-width:0;flex:1}
.fp-ic{display:grid;place-items:center;width:2rem;height:2rem;flex:none;
  background:var(--raised);border:1px solid var(--line);
  border-radius:var(--sheet);color:var(--muted);box-shadow:var(--press)}
.filepick.has .fp-ic{color:var(--accent)}
.fp-said{min-width:0;letter-spacing:0}
.fp-said b{display:block;font-size:.9rem;font-weight:500;color:var(--text);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* The accepted-types line is lowercased because it is written in the accept
   attribute's own words; a chosen file's size is not, or 118 KB reads as
   kilobits. */
.fp-hint{display:block;font-size:.74rem;color:var(--muted);
  text-transform:lowercase}
.filepick.has .fp-hint{text-transform:none}
.fp-clear{position:relative;z-index:1;display:grid;place-items:center;flex:none;
  width:1.7rem;height:1.7rem;background:var(--raised);
  border:1px solid var(--line);border-radius:var(--sheet);color:var(--muted);
  cursor:pointer;box-shadow:var(--press)}
.fp-clear:hover{color:var(--text);border-color:var(--accent)}
/* In a filter row the picker is one control among several and gets a couple of
   hundred pixels: the framed icon and the accepted-types line are the first
   things to go, and the name still elides. */
.row .filepick,.filters .filepick{padding:.42rem .5rem;gap:var(--s2)}
.row .filepick .fp-ic,.filters .filepick .fp-ic{display:none}
.row .filepick:not(.has) .fp-hint,
.filters .filepick:not(.has) .fp-hint{display:none}
/* A name, a colour or an email is a short answer, and a box a thousand pixels
   wide invites a paragraph: fields stop at a readable measure, and the ones
   meant to be long say so. */
input:not([type=checkbox],[type=radio],[type=file]),
select{max-width:32rem}
.grow input,.grow select,.compare input,td input,td select,
.fields input,.fields select,.voicepick input{max-width:none}
/* A field on a stave takes the column's width, but a speed of 1.0 in a
   350px box on a wide screen read as a mistake: a control in a field grid
   stops at the width of an answer while still starting on the column. */
.fields input,.fields select,.fields .stepper,.fields .filepick{max-width:24rem}
input[type=range]{padding:0;box-shadow:none;background:none;accent-color:var(--accent)}
textarea{resize:vertical;line-height:1.6}
/* The grey diagonal grip in a textarea's corner is the browser's; this one is
   two warm strokes at the icon set's angle. */
textarea::-webkit-resizer{background:
  linear-gradient(135deg,transparent 0 46%,#4a4038 46% 54%,transparent 54% 70%,
    #4a4038 70% 78%,transparent 78%)}
/* A drawn stepper. The native spinner is a pair of grey chevrons that only
   appear on hover and never matched anything; steppers.js puts real buttons
   beside the field, and with no script the field types as it always did. */
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.stepper input[type=number]{-moz-appearance:textfield;appearance:textfield}
.stepper{display:flex;align-items:stretch;gap:var(--s1);margin-top:.3rem}
.stepper input[type=number]{margin-top:0;min-width:0;flex:1}
.stepper button{display:grid;place-items:center;width:1.9rem;padding:0;
  flex:none;background:var(--raised);border:1px solid var(--line);
  border-radius:var(--sheet);color:var(--muted);font-size:1rem;line-height:1;
  cursor:pointer;box-shadow:var(--press)}
.stepper button:hover{color:var(--text);border-color:var(--accent)}
.stepper button:active{box-shadow:var(--well)}
/* Drawn where the browser's own tooltip would appear, and only while it is
   wanted: kept in the tree at rest it widened its host's scroll extent. */
[data-tip]{position:relative}
[data-tip]:hover::after,[data-tip]:focus-visible::after{content:attr(data-tip);
  position:absolute;bottom:calc(100% + 6px);left:50%;z-index:40;
  max-width:min(16rem,calc(100vw - 1.5rem));
  padding:.3rem .5rem;background:var(--raised);border:1px solid var(--line);
  border-radius:var(--sheet);box-shadow:var(--lift);color:var(--text);
  font-family:var(--body);font-size:.74rem;font-weight:400;letter-spacing:0;
  white-space:nowrap;pointer-events:none;animation:tipup var(--fast) both}
@keyframes tipup{from{opacity:0;transform:translate(-50%,3px)}
  to{opacity:1;transform:translate(-50%,0)}}
/* Near a window edge a centred tip hangs over it, so it hangs off the control's
   own edge instead - controls.js measures which side. */
[data-tip][data-tip-at=end]:hover::after,
[data-tip][data-tip-at=end]:focus-visible::after{left:auto;right:0;
  animation-name:tipupend}
[data-tip][data-tip-at=start]:hover::after,
[data-tip][data-tip-at=start]:focus-visible::after{left:0;
  animation-name:tipupend}
@keyframes tipupend{from{opacity:0;transform:translateY(3px)}
  to{opacity:1;transform:translateY(0)}}
@media(prefers-reduced-motion:reduce){
  [data-tip]:hover::after,[data-tip]:focus-visible::after{animation:none;
    transform:translateX(-50%)}
  [data-tip][data-tip-at]:hover::after,
  [data-tip][data-tip-at]:focus-visible::after{transform:none}
}
fieldset{border:1px solid var(--line);border-radius:var(--sheet);
  padding:var(--s3);margin:0 0 var(--s4)}
legend{color:var(--muted);font-size:.7rem;letter-spacing:.12em;
  text-transform:uppercase;padding:0 .35rem}
/* Fields on a stave. A flex row sized every control to its content, so a speed
   box, a format menu and a level box ended up three different widths on one
   line and read as three unrelated controls. In a field grid they share one
   column width and line up with the field above them. */
.fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(9.5rem,1fr));
  gap:var(--s2) var(--s4);align-items:start;margin-bottom:var(--s3)}
.fields>label{margin-bottom:0}
.fields.wide{grid-template-columns:repeat(auto-fit,minmax(15rem,1fr))}
/* A field's own small print: the sentence that used to be crammed onto the end
   of its label, one line below the control it belongs to. */
.hint{display:block;margin-top:.35rem;color:var(--muted);font-size:.78rem;
  letter-spacing:0;line-height:1.5}
label.check .hint{margin-top:.2rem}
/* Every fold gets the drawn sign, not the platform triangle - the two were
   sitting on the same page in the operations console. */
summary{cursor:pointer;list-style:none}
summary::-webkit-details-marker{display:none}
details>summary::before{content:"+";display:inline-block;width:1rem;
  color:var(--accent);font-weight:600}
details[open]>summary::before{content:"\2212"}
/* A note the reader only wants once: folded away rather than four lines of grey
   prose under every form. */
details.tip{margin:var(--s3) 0 0;border-top:1px solid var(--rule);
  padding-top:var(--s3)}
details.tip>summary{cursor:pointer;color:var(--muted);font-size:.82rem;
  letter-spacing:.02em;list-style:none}
details.tip>summary::-webkit-details-marker{display:none}
details.tip>summary::before{content:"+";display:inline-block;width:1rem;
  color:var(--accent);font-weight:600}
details.tip[open]>summary::before{content:"\2212"}
details.tip>summary:hover{color:var(--text)}
details.tip>p{margin:var(--s2) 0 0;color:var(--muted);font-size:.85rem}
details.tip+.row,details.tip+.fields{margin-top:var(--s4)}
/* A second job inside one card: a ruled small-caps head instead of a bare rule,
   so "and now the other thing" is legible rather than implied. */
.subhead{display:flex;align-items:baseline;gap:var(--s3);margin:var(--s5) 0 var(--s3);
  padding-top:var(--s3);border-top:1px solid var(--rule)}
.subhead h3{margin:0;font-size:.92rem}
/* The aside stays beside its heading rather than at the card's far edge. */
.subhead .note{margin:0}
.row{display:flex;gap:var(--s4);align-items:flex-end;flex-wrap:wrap}
.row.between{justify-content:space-between;align-items:center}
.row.tight{gap:var(--s2)}
.row .grow{flex:1 1 22rem}
/* A key on a deck: it has a lit lip, an inked base, and it moves when pressed.
   Nothing here is a flat rectangle that changes opacity. */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:.45rem;
  background:linear-gradient(180deg,rgba(255,255,255,.14),rgba(0,0,0,.06)),
  var(--accent);color:var(--ink);border:1px solid rgba(0,0,0,.28);
  border-radius:var(--sheet);padding:.5rem 1rem;font:inherit;font-size:.92rem;
  font-weight:600;cursor:pointer;box-shadow:var(--press-hi);
  transition:filter var(--fast),transform var(--fast),box-shadow var(--fast)}
.btn:hover{filter:brightness(1.06);text-decoration:none}
.btn:active{transform:translateY(1px);box-shadow:var(--press)}
.btn .ic{width:16px;height:16px}
.btn.ghost{background:linear-gradient(180deg,rgba(255,255,255,.045),
  rgba(0,0,0,.1));border-color:var(--line);color:var(--text)}
.btn.ghost:hover{border-color:var(--accent)}
.btn.small{padding:.28rem .6rem;font-size:.79rem;font-weight:500}
.btn.wide{width:100%}
.btn.danger{background:linear-gradient(180deg,rgba(255,255,255,.06),
  rgba(0,0,0,.12));border-color:#4a2f2f;color:var(--bad);box-shadow:var(--press)}
/* Fields carry their label's bottom margin, buttons and prose carry none, so a
   key that followed a field sat on its edge and the note under it touched the
   key. Side by side outside a gapped row they need the same air. */
label+.btn,label+button,.filepick+.btn,.filepick+button,
fieldset+.btn,fieldset+button,.row+.btn,.row+button,
.pl+.btn,.pl+button,audio+.btn,audio+button{margin-top:var(--s3)}
.btn+p,button+p,.btn+.note,button+.note,.btn+.muted,button+.muted{
  margin-top:var(--s3)}
.btn+.btn,.btn+button,button+.btn,button+button{margin-left:var(--s2)}
.row>.btn+.btn,.row>.btn+button,.row>button+.btn,.row>button+button,
.row-actions>.btn+.btn,.row-actions>button+button,.row-actions>.btn+button,
.row-actions>button+.btn,.chips>.btn+.btn,.chips>button+button{margin-left:0}
@supports selector(:has(*)){
  .row:has(>.btn),.row:has(>button){margin-top:var(--s3)}
  .row.between:has(>.btn),.row.between:has(>button),
  .filters .row:has(>button),h1+.row:has(>.btn){margin-top:0}
  .row:has(>.btn)+p,.row:has(>button)+p,
  .row:has(>.btn)+.note,.row:has(>button)+.note{margin-top:var(--s4)}
}
/* Contents for a long reference: a ruled row of destinations, not a second nav
   full of boxes. */
.toc{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s4);margin:0 0 var(--s5);
  padding:var(--s3) 0;border-top:1px solid var(--rule);
  border-bottom:1px solid var(--rule)}
.toc a{color:var(--muted);font-size:.8rem;letter-spacing:.02em}
.toc a:hover{color:var(--accent);text-decoration:none}
/* Five short facts about an account are one line of the page, not five ruled
   rows: the label above the value, read left to right like a docket. */
.kv{display:flex;flex-wrap:wrap;gap:var(--s3) var(--s6);list-style:none;
  margin:0 0 var(--s4);padding:0}
.kv li{min-width:0}
.kv>li>b{display:block;font:inherit;font-size:.68rem;font-weight:600;
  letter-spacing:.13em;text-transform:uppercase;color:var(--muted);
  margin-bottom:.15rem}
.kv>li>span{display:block;font-size:.9rem}
.kv>li>span b{font:inherit;font-weight:600}
.chips{display:flex;flex-wrap:wrap;gap:var(--s2);margin:0 0 var(--s4);padding:0}
.chip{background:var(--raised) linear-gradient(180deg,rgba(255,255,255,.04),
  rgba(0,0,0,.1));border:1px solid var(--line);border-radius:99px 99px 99px 5px;
  padding:.28rem .8rem;font:inherit;font-size:.8rem;color:var(--text);
  cursor:pointer;box-shadow:var(--press);
  transition:border-color var(--fast),color var(--fast)}
.chip:hover{border-color:#4a4038}
.chip.on{border-color:rgba(0,0,0,.3);background:var(--accent);color:var(--ink);
  font-weight:600}
.tags{display:flex;flex-wrap:wrap;gap:var(--s1);list-style:none;padding:0;
  margin:0}
.tags li{background:var(--sunk);border:1px solid var(--line);
  border-radius:99px 99px 99px 4px;padding:.06rem .5rem;font-size:.71rem;
  letter-spacing:.02em;color:var(--muted)}
/* The tier is a fact about the voice, not a call to action: an amber-outlined
   chip on two dozen cards at once made the grid flicker. */
.tags li.tier{border-color:#463c34;color:var(--text)}
.tags li.lock{border-color:var(--line);color:var(--muted)}
.tags li.q-best,.tags li.q-great{color:var(--good)}
/* Five outlined chips on each of twenty-four cards is a grid of chips: inside a
   voice card the same facts read as one dotted line. */
/* One line, always: reserving two for a word that sometimes wrapped left a
   ragged half-empty row under every card in the shop. */
.vcard .tags{display:block;gap:0;font-size:.73rem;margin:0 0 var(--s2);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vcard .tags li{display:inline;background:none;border:0;border-radius:0;
  padding:0;font-size:inherit}
.vcard .tags li+li::before{content:"\00b7";margin:0 .4rem;color:var(--line)}
.vcard .tags li.tier{color:var(--muted)}
.vcard .tags li.lock{color:var(--warn)}

/* --- data -------------------------------------------------------------- */
table{width:100%;border-collapse:collapse;margin:var(--s2) 0 var(--s4)}
/* A four-column table stretched across a 1,500px page put a key at one edge and
   its row's name at the other. On a wide page the table takes the width of what
   it holds, and only fills the card when it has enough columns to need it. */
@media(min-width:1180px){
  .board table{width:auto;min-width:min(100%,40rem)}
}
/* Long values (API keys, ids) scroll inside their own card rather than pushing
   the page sideways on a phone. */
/* A table wider than a phone scrolls sideways, and nothing said so: the edge
   shadow appears only on the side that still has rows to show, and rides the
   scroll itself, so no script is involved. */
.scroller{overflow-x:auto;-webkit-overflow-scrolling:touch;
  background:
    linear-gradient(to right,#1f1b18 40%,rgba(0,0,0,0)),
    linear-gradient(to left,#1f1b18 40%,rgba(0,0,0,0)) 100% 0,
    radial-gradient(farthest-side at 0 50%,rgba(0,0,0,.6),rgba(0,0,0,0)),
    radial-gradient(farthest-side at 100% 50%,rgba(0,0,0,.6),rgba(0,0,0,0))
      100% 0;
  background-repeat:no-repeat;
  background-size:2.4rem 100%,2.4rem 100%,1.15rem 100%,1.15rem 100%;
  background-attachment:local,local,scroll,scroll}
/* Only as wide as a table of a few columns actually needs, so a narrow one
   fits a phone instead of scrolling for nothing. */
.scroller table{min-width:21rem}
/* Three tiers, each with its drawn emblem: a row on a desk, stacking on a
   phone, and readable with no artwork at all on a white-label tenant. */
.tiers{list-style:none;margin:var(--s3) 0 var(--s5);padding:0;display:grid;
  gap:var(--s4);grid-template-columns:repeat(auto-fit,minmax(13rem,1fr))}
.tiers li{display:flex;flex-direction:column;gap:var(--s1)}
.tiers .emblem{width:3.4rem;height:3.4rem;margin-bottom:var(--s2);
  border-radius:99px;object-fit:cover}
.tiers b{font-family:var(--head);font-size:1.02rem;font-weight:600}
th{text-align:left;padding:.4rem .6rem;font-size:.66rem;font-weight:600;
  letter-spacing:.12em;text-transform:uppercase;color:var(--muted);
  border-bottom:1px solid var(--line);white-space:nowrap}
td{text-align:left;padding:.55rem .6rem;border-bottom:1px solid var(--rule);
  vertical-align:top;font-size:.9rem}
tbody tr:hover td{background:rgba(255,255,255,.018)}
td code{overflow-wrap:anywhere}
code{background:var(--sunk);border:1px solid var(--rule);padding:.05rem .35rem;
  border-radius:var(--r-sm);font-family:var(--mono);font-size:.8rem;
  color:var(--text)}
pre.code{background:var(--sunk);border:1px solid var(--line);
  border-radius:var(--sheet);padding:var(--s3);font-family:var(--mono);
  font-size:.8rem;overflow:auto;color:var(--muted);box-shadow:var(--well)}
pre.code{white-space:pre;tab-size:2}
code.secret{overflow-wrap:anywhere;font-size:.75rem}
ul.plain{list-style:none;padding:0;margin:0 0 var(--s2);font-size:.9rem}
ul.plain li{padding:.3rem 0;border-bottom:1px solid var(--rule)}
ul.plain li:last-child{border-bottom:none}
.steps{margin:0;padding-left:1.2rem}
.steps li{padding:.3rem 0}
.steps li[data-done=yes]>a{color:var(--muted);text-decoration:line-through}
.steps li[data-done=yes]::marker{color:var(--good)}
.steps em{font-style:normal;font-size:.68rem;text-transform:uppercase;
  letter-spacing:.1em;color:var(--muted);margin-left:.35rem}
.steps span{display:block;color:var(--muted);font-size:.82rem}
/* Four short first-run steps read as a tall grey column stacked one per line;
   in two they are a card the height of the work below them. */
.steps.two{display:grid;grid-template-columns:1fr 1fr;gap:0 var(--s6)}
@media(max-width:860px){.steps.two{grid-template-columns:1fr}}
.row-actions{display:flex;gap:var(--s1);align-items:center;flex-wrap:wrap}
.row-actions form{margin:0}
/* A control in a cell inherited width:100% of whatever the column happened to
   be, which squeezed a plan menu to "Fre..." and pushed its key onto the next
   line. In a cell they take their content's width and stay on one line; the
   card scrolls sideways if the sum no longer fits. */
td form,td .row{display:flex;gap:var(--s2);align-items:center;flex-wrap:nowrap;
  margin:0}
td input,td select,td textarea{width:auto;max-width:16rem;flex:none;
  min-width:0;margin-top:0}
/* A menu in a cell asks the column for room for its longest chosen label, so
   "Reseller / White-label" reads in full instead of "Reseller /". */
td select{min-width:max-content;padding-right:2.35rem}
td .btn,td button{flex:none;white-space:nowrap}
td .btn,td button,td .filepick{margin-top:0}
td .btn+.btn,td .btn+button,td button+.btn,td button+button{margin-left:0}
td .note,td .chip{display:block;margin-top:var(--s1)}
td .chip{display:inline-block;cursor:default;margin:.15rem .2rem 0 0}
.figure{font-family:var(--head);font-size:1.6rem;font-weight:600;
  line-height:1.1;display:block}
audio{width:100%;margin:var(--s3) 0}
video{width:100%;margin:var(--s3) 0;border:1px solid var(--line);
  border-radius:var(--sheet);background:var(--sunk)}

/* --- first run and "where you left off" -------------------------------- */
.card.start{border-left:2px solid var(--accent)}
.card.start h3{font-family:var(--head);font-size:.95rem;margin:0 0 var(--s2)}

/* --- the voice shop ----------------------------------------------------- */
.cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(255px,1fr));
  gap:var(--s4);margin:var(--s4) 0}
.cards.inline{grid-column:1/-1;margin:var(--s3) 0 0}
.vcard{background:var(--card);border:1px solid var(--line);
  border-radius:var(--sheet);padding:var(--s4);box-shadow:var(--press);
  transition:border-color var(--slow),transform var(--slow),
  box-shadow var(--slow)}
/* A row of five: one card whose tier chip wrapped to a second line left its
   neighbours' keys sitting at four different heights. The card is a column and
   its keys hang from the bottom, so a shelf of cards reads as a shelf. */
.vcard{display:flex;flex-direction:column}
.vcard .row{margin-top:auto}
.vcard:hover{border-color:#4a4038;transform:translateY(-1px);
  box-shadow:var(--lift)}
/* A two-line name used to push its card's tagline, tags and player a line lower
   than its neighbours': the header keeps room for two lines either way. */
.vcard header{display:flex;align-items:flex-start;gap:var(--s3);
  min-height:2.9rem}
.vcard .who{display:flex;flex-direction:column;flex:1;min-width:0}
.vcard .who b{font-family:var(--head);font-size:1.05rem;letter-spacing:-.01em}
.vcard .who .muted{font-size:.75rem}
.vcard .who b a.plain{color:inherit;text-decoration:none}
.vcard .who b a.plain:hover{text-decoration:underline}
.vcard .why{font-size:.78rem;color:var(--accent);margin:.1rem 0 .3rem}
.vcard .tagline{font-size:.85rem;margin:var(--s3) 0 var(--s1);min-height:1.2em}
.vcard audio{height:34px;margin:var(--s1) 0}
.vcard details{margin-top:var(--s2)}
.vcard summary{cursor:pointer;font-size:.8rem;color:var(--muted)}
/* The platform triangle is the other giveaway that nobody dressed the page: the
   same drawn plus as every other disclosure. */
.vcard details>summary,details.advanced>summary{list-style:none;
  cursor:pointer}
.vcard details>summary::-webkit-details-marker,
details.advanced>summary::-webkit-details-marker{display:none}
.vcard details>summary::before,details.advanced>summary::before{
  content:"+";display:inline-block;width:.9rem;color:var(--accent);
  font-weight:600}
.vcard details[open]>summary::before,
details.advanced[open]>summary::before{content:"\2212"}
/* A fold in the middle of a card is a line of its own, ruled off the fields
   above it so it does not read as another field. */
.card.find details.advanced,.card.filters details.advanced{
  margin:var(--s3) 0 0;border-top:1px solid var(--rule);padding-top:var(--s3)}
.card.find details.advanced>summary,
.card.filters details.advanced>summary{color:var(--muted);font-size:.85rem}
.card.find details.advanced>summary:hover,
.card.filters details.advanced>summary:hover{color:var(--text)}
.card.filters details.advanced .fields{margin-top:var(--s3)}
/* One key per card. "Similar" and "Compare" are second thoughts, so they are
   set as quiet text beside it rather than three keys of equal weight. */
.vcard .row .btn.ghost{background:none;border-color:transparent;
  box-shadow:none;color:var(--muted);padding:.3rem .35rem}
.vcard .row .btn.ghost:hover{color:var(--text);background:none;
  border-color:transparent;text-decoration:underline}
.avatar{display:grid;place-items:center;width:2.2rem;height:2.2rem;
  flex:0 0 auto;border-radius:99px 99px 99px 4px;background:var(--accent);
  color:var(--ink);font-weight:600;box-shadow:var(--press)}
.fav{background:none;border:0;color:var(--muted);font-size:1.2rem;
  cursor:pointer;padding:0;box-shadow:none}
.fav.on{color:var(--warn)}
.filters .row{align-items:flex-end}
.filters label{margin-bottom:0;flex:1 1 8rem}
.filters .filter-do{margin-top:var(--s4)}
@supports selector(:has(*)){
@media(min-width:1000px){
  /* Two short fields across a wide card stranded Search on a line of its own
     with two thirds of the card blank beside it: where the fields are the whole
     form, the key joins the end of their row. */
  .filters:not(:has(details)){display:flex;flex-wrap:wrap;align-items:flex-end;
    gap:var(--s3) var(--s4)}
  .filters:not(:has(details))>.fields{flex:1 1 26rem;margin-bottom:0}
  .filters:not(:has(details))>.filter-do{margin:0}
}
}
/* Facets fill the line they are given rather than leaving a ragged short row
   under a fixed four-column grid. */
.filters .fields{grid-template-columns:repeat(auto-fit,minmax(12rem,1fr));
  gap:var(--s3) var(--s4)}
/* The key belongs beside the field it submits: left to grow, the label took the
   whole card and stranded Search against the far edge. */
.card.find>form.row{align-items:flex-start}
.card.find>form.row .grow{flex:0 1 34rem}
.card.find>form.row .btn{margin-top:1.55rem}
/* Three questions in a narrow card: two per row leaves each menu wide enough
   for its longest answer instead of trimming "product demo". */
.finder .fields{grid-template-columns:repeat(auto-fit,minmax(11rem,1fr))}
@media(max-width:860px){.filters .fields{grid-template-columns:repeat(2,minmax(0,1fr))}}
/* Three ways to find a voice in one card: the sentence search leads, and the
   two narrower routes sit under one rule as a pair of columns. */
.find-more .pair{display:grid;grid-template-columns:1fr 1fr;gap:var(--s5);
  margin-top:var(--s4)}
.find-more h3{margin:0 0 var(--s3);font-family:var(--body);font-size:.85rem;
  font-weight:600;letter-spacing:.01em;color:var(--muted)}
.find-more form{margin:0}
.find-more .pair>div+div{border-left:1px solid var(--rule);
  padding-left:var(--s5)}
.listhead{margin:0 0 var(--s3)}
.listhead p{margin:0}
@media(max-width:860px){
  .find-more .pair{grid-template-columns:1fr;gap:var(--s4)}
  .find-more .pair>div+div{border-left:0;border-top:1px solid var(--rule);
    padding:var(--s4) 0 0}
}
/* A boxed picker inside a boxed form read as a card in a card: one rule above
   it groups the voice with its preview just as well. */
.voicepick{border:0;border-top:1px solid var(--rule);border-radius:0;
  padding:var(--s3) 0 0;margin-bottom:var(--s3);background:none}
.voicepick .picked{display:flex;align-items:center;gap:var(--s3);
  flex-wrap:wrap}
/* Only the name and its line of facts stack; the rule used to reach every span
   in the group, which stood the player's clock on two lines and its two mute
   glyphs one above the other - the "cluttered player" in the shop window. */
.voicepick .picked>span{display:flex;flex-direction:column}
.voicepick .picked audio{flex:1 1 12rem;width:auto;height:32px;margin:0}
.voicepick .picked .pl{flex:1 1 18rem}
.voicepick .advanced summary{cursor:pointer;font-size:.8rem;color:var(--muted)}
.voicelist{list-style:none;margin:var(--s2) 0 0;padding:0;max-height:15rem;
  overflow:auto;border:1px solid var(--line);border-radius:var(--sheet);
  background:var(--sunk)}
.voicelist li{padding:.45rem .6rem;cursor:pointer;font-size:.9rem;
  border-bottom:1px solid var(--rule);display:flex;align-items:center;
  gap:var(--s2)}
.voicelist li:hover{background:var(--raised)}
.compare{background:var(--card);border:1px solid var(--accent);
  border-radius:var(--sheet);padding:var(--s3);margin-bottom:var(--s4);
  display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap;
  box-shadow:var(--press)}
.compare input{flex:1 1 16rem;width:auto}
.pager{display:flex;gap:var(--s3);align-items:center;margin:var(--s4) 0}
.crumbs{font-size:.78rem;letter-spacing:.02em;color:var(--muted);
  margin:0 0 var(--s3)}
.crumbs a{color:var(--muted)}
.voicehead header{display:flex;align-items:center;gap:var(--s4);
  margin-bottom:var(--s3)}
.voicehead h1{margin:0}
.voicehead .tagline{margin:.35rem 0 0}
.voicehead audio{width:100%;max-width:32rem;margin:.3rem 0 var(--s3)}
.voicehead .grow{min-width:0}

/* --- the voice mark ----------------------------------------------------- */
/* Every voice wears a ring of its own measured loudness around its initial, so
   1,480 avatars are all different for a reason and still one family: same well,
   same weight, same geometry, hue by language family. */
.vmark{flex:none;display:block;overflow:visible}
.vmark .vm-well{fill:var(--raised);stroke:var(--line);stroke-width:1}
.vmark .vm-rays line{stroke:var(--mk,var(--accent));stroke-width:1.75;
  stroke-linecap:round;opacity:.92}
.vmark .vm-rays{transform-origin:20px 20px;transition:transform var(--slow)}
.vmark .vm-letter{fill:var(--text);font-family:var(--head);font-weight:600;
  font-size:12px;letter-spacing:0}
/* The tier reads as the ring's frame: Core bare, Studio hooped, Clone stitched. */
.vmark .vm-hoop{fill:none;stroke:var(--mk,var(--accent));stroke-width:1;
  opacity:.34}
.vmark .vm-hoop.dash{stroke-dasharray:2.4 3.4;opacity:.5}
/* No preview measured yet: the well and initial stand alone rather than a
   pattern standing in for speech that was never heard. */
.vmark.flat .vm-well{stroke-dasharray:2.4 3.4}
.vmark.tiny .vm-well{fill:var(--mk,var(--accent));stroke:none;opacity:.9}
.fam-english{--mk:#d97d3d}
.fam-indic{--mk:#d9a53d}
.fam-romance{--mk:#d96b4a}
.fam-germanic{--mk:#bd8a5f}
.fam-slavic{--mk:#c97f6b}
.fam-cjk{--mk:#93a0a8}
.fam-other{--mk:#b9afa4}
.vcard:hover .vmark .vm-rays{transform:scale(1.07)}
/* The ring breathes. Each ray is pathLength 1, so one dash animation shortens
   every ray by the same fraction of its own measured length - the envelope stays
   readable while it moves - and --i walks the phase round the ring. */
@keyframes vm-wave{0%,100%{stroke-dashoffset:.26}50%{stroke-dashoffset:0}}
.vmark .vm-rays line{stroke-dasharray:1;stroke-dashoffset:0}
@media(prefers-reduced-motion:no-preference){
  .vmark .vm-rays line{animation:vm-wave 3.4s cubic-bezier(.4,0,.2,1) infinite;
    animation-delay:calc(var(--i,0)*-.11s)}
  /* Under the pointer, and while that voice is actually speaking, the same wave
     runs at a speaking pace instead of an idle one. */
  .vcard:hover .vmark .vm-rays line,
  .playing .vmark .vm-rays line{animation-duration:1.15s}
  /* Kept apart: an engine without :has drops the whole selector list it sits
     in, and the rules above must survive that. */
  li:has(.pl.playing) .vmark .vm-rays line{animation-duration:1.15s}
}
/* Lists the browser builds pull the same drawing as a file, so those rows are
   not a second, slightly different avatar. */
.vmark-img{flex:none;display:block}
td.vrow{display:flex;align-items:center;gap:.45rem}
.voicelist li{display:flex;align-items:center;gap:var(--s2)}
#palette li a img.vmark-img{margin-right:.1rem}
#palette li a{align-items:center}
#palette li a b{display:flex;align-items:center;gap:var(--s2);min-width:0}

/* --- the drawn player --------------------------------------------------- */
/* One row: a cut play key, a 36-bar meter that fills as it plays, a clock and a
   mute. The real <audio> keeps working underneath; JS hides it and takes over,
   so with JS off the native controls are still there. It lives in the shared
   sheet because a clip plays on nine pages, not only on the landing one. */
.pl{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;gap:.7rem;
  align-items:center;background:var(--sunk);border:1px solid var(--line);
  border-radius:var(--sheet);padding:.55rem .7rem;box-shadow:var(--well);
  container-type:inline-size}
.pl.on{border-color:var(--accent)}
html.js .pl audio{display:none}
/* With JS off the native element is the only player there is, and in an auto
   grid cell Chrome draws it 40px wide - too narrow for a control bar - so it
   takes the whole row instead. */
html:not(.js) .pl audio{grid-column:1/-1;width:100%;min-width:15rem;
  min-height:54px}
html:not(.js) .pl-key,html:not(.js) .pl-meter,html:not(.js) .pl-clock,
html:not(.js) .pl-vol{display:none}
.pl-key{display:grid;place-items:center;width:2.5rem;height:2.5rem;padding:0;
  border:1px solid rgba(0,0,0,.28);border-radius:99px;
  background:linear-gradient(180deg,rgba(255,255,255,.16),rgba(0,0,0,.08)),
  var(--accent);color:var(--ink);cursor:pointer;box-shadow:var(--press-hi);
  transition:transform var(--fast),box-shadow var(--fast)}
.pl-key:hover{box-shadow:0 0 0 5px var(--halo)}
.pl-key:active{transform:scale(.94)}
.pl-key .ic{margin-left:1px}
.pl-ic{display:none;line-height:0}
.pl-key .play,.pl.busy .wait,.pl.playing .pause,.pl-vol .loud,
.pl.muted .hush{display:block}
.pl.playing .play,.pl.busy .play,.pl.busy .pause,.pl.muted .loud{display:none}
.pl.busy .wait{animation:spin 900ms linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.pl-meter{position:relative;display:flex;align-items:flex-end;gap:2px;
  height:2.4rem;cursor:pointer;border-radius:2px;padding:0 1px}
.pl-meter i{flex:1;min-width:2.5px;height:var(--h);background:var(--muted);
  opacity:.42;border-radius:1px;
  transition:background var(--fast),opacity var(--fast)}
.pl-meter i.done{background:var(--accent);opacity:1}
.pl-meter:hover i{opacity:.62}
.pl-meter:hover i.done{opacity:1}
.pl-meter i.at{background:var(--accent);box-shadow:0 0 0 1px var(--accent)}
.pl-head{position:absolute;top:-2px;bottom:-2px;width:2px;left:0;
  background:var(--text);opacity:0;border-radius:2px;
  transition:opacity var(--fast)}
.pl.playing .pl-head,.pl.scrubbing .pl-head{opacity:.55}
/* The time under the pointer, so a drag along the meter lands where you meant
   rather than where it guessed. */
.pl-tip{position:absolute;bottom:calc(100% + .35rem);left:0;
  transform:translateX(-50%);padding:.12rem .35rem;pointer-events:none;
  background:var(--raised);border:1px solid var(--line);border-radius:2px;
  font-family:var(--head);font-size:.7rem;color:var(--text);
  font-variant-numeric:tabular-nums;white-space:nowrap;
  opacity:0;transition:opacity var(--fast)}
.pl-meter:hover .pl-tip,.pl.scrubbing .pl-tip{opacity:1}
.pl.scrubbing .pl-meter{cursor:grabbing}
.pl-clock{font-family:var(--head);font-size:.8rem;color:var(--muted);
  font-variant-numeric:tabular-nums;white-space:nowrap;display:flex;gap:.3rem;
  align-items:baseline}
/* "0:00 / ..." before a clip has been asked for is the sort of half-built
   detail the page gets judged on: the clock keeps its place in the row and
   waits until there is a length to put in it. */
.pl-clock{visibility:hidden}
.pl.timed .pl-clock,.pl.playing .pl-clock,.pl.busy .pl-clock{visibility:visible}
/* The shelf card sets its title in 1rem b, which the elapsed time inherited:
   the clock read as one big number over a superscript duration. */
.pl-clock b{color:var(--text);font-weight:600;font-size:inherit;
  line-height:inherit;display:inline}
.pl-clock b::after{content:"/";color:var(--muted);margin-left:.3rem;
  font-weight:400}
.pl-vol{display:grid;place-items:center;width:1.9rem;height:1.9rem;padding:0;
  background:none;border:1px solid transparent;border-radius:var(--r-sm);
  color:var(--muted);cursor:pointer;box-shadow:none;
  transition:color var(--fast),border-color var(--fast)}
.pl-vol:hover{color:var(--text);border-color:var(--line)}
/* A clip the page is holding back - the recorder's own playback before a take
   exists - keeps its drawn shell out of the layout with it. */
.pl:has(audio[hidden]){display:none}
.pl-fail{color:var(--bad);font-size:.8rem;margin:.4rem 0 0}
.pl-key:focus-visible,.pl-vol:focus-visible,.pl-meter:focus-visible{
  outline:2px solid var(--accent);outline-offset:2px}
/* In a voice card those four parts leave the meter 60px - twenty hairlines
   packed together, a smear rather than a waveform - so a narrow player drops
   the mute and keeps one time: the clip's length, then where you are in it. */
@container (max-width:23rem){
  .pl-vol{display:none}
  .pl-clock{display:none}
  .pl.timed .pl-clock,.pl.playing .pl-clock,.pl.busy .pl-clock{display:flex}
  .pl-clock b{display:none}
  .pl.playing .pl-clock b,.pl.busy .pl-clock b{display:inline}
  .pl.playing .pl-clock b::after,.pl.busy .pl-clock b::after{content:none}
  .pl.playing .pl-clock [data-role=pl-dur],
  .pl.busy .pl-clock [data-role=pl-dur]{display:none}
  .pl-meter i{min-width:3px}
  .pl-key{width:2.2rem;height:2.2rem}
}

/* --- conversations ------------------------------------------------------ */
.castrow{border-left:2px solid var(--accent);padding-left:var(--s3);
  margin-bottom:var(--s2)}
.castrow .who{display:block;margin-bottom:.3rem}
.castrow .voicepick{margin-bottom:var(--s1)}

/* --- pricing ------------------------------------------------------------ */
.cycles{display:flex;gap:var(--s2);margin:var(--s4) 0}
/* stretch, not start: the feature lists have different lengths, so starting
   them left the four buy buttons stepping down the row. */
.plans{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));
  gap:var(--s4);align-items:stretch;margin-bottom:var(--s5)}
/* Column, so the buy button sits on the floor of every card: feature lists are
   different lengths and ragged card bottoms read as a broken table. */
.plans .plan{margin-bottom:0;display:flex;flex-direction:column;
  position:relative}
.plans .plan>.btn,.plans .plan>form,.plans .plan>.pill{margin-top:auto;
  align-self:start}
.plans .plan>.blurb{margin-bottom:var(--s4)}
.plans .plan.featured{border-color:var(--accent);box-shadow:var(--press-hi)}
.plans .price{font-family:var(--head);font-size:1.95rem;font-weight:600;
  margin:.2rem 0;letter-spacing:-.02em}
.plans .price small{font-family:var(--body);font-size:.85rem;font-weight:400;
  color:var(--muted)}
.plans .pitch{margin:0 0 var(--s2);font-weight:600}
.plans .blurb{color:var(--muted);font-size:.85rem}
.plans .feats{list-style:none;padding:0;margin:var(--s2) 0;font-size:.88rem}
/* A rule under every line turned four plans into forty rules: the lines are
   spaced instead and only the last one is closed off. */
.plans .feats li{padding:.24rem 0}
.plans .feats li:not(:last-child){border-bottom:0}
.plans.lite .plan{background:none;border:1px solid var(--line);
  border-radius:var(--sheet);padding:var(--s3);box-shadow:none}
.plans .flag{position:absolute;top:-.7rem;left:var(--s4);background:var(--accent);
  color:var(--ink);font-size:.66rem;letter-spacing:.12em;
  text-transform:uppercase;font-weight:600;padding:.15rem .55rem;
  border-radius:99px 99px 99px 4px;box-shadow:var(--press)}
.pricetable td,.pricetable th{vertical-align:top}
.pricetable tr.us{background:rgba(255,255,255,.02)}
.pricetable tr.us td:first-child{border-left:2px solid var(--accent)}
.faq dt{font-weight:600;margin-top:var(--s3);font-family:var(--head)}
.faq dd{margin:.2rem 0 0;color:var(--muted)}

/* --- marketing furniture shared with the landing page ------------------- */
.hero{max-width:760px;margin:var(--s8) auto var(--s6);text-align:center}
.hero h1{font-size:clamp(2rem,1.4rem + 2.4vw,2.6rem);line-height:1.1}
.hero p{color:var(--muted);font-size:1.05rem}
.tryout{max-width:760px;margin:0 auto var(--s7);padding:var(--s5)}
.tryout h2{margin-top:0}
.tryout textarea{min-height:4.2rem}
.tryout canvas{width:100%;height:72px;display:block;margin:var(--s4) 0 var(--s1);
  background:var(--sunk);border-radius:var(--sheet);box-shadow:var(--well)}
.cta{display:flex;gap:var(--s3);justify-content:center;margin:var(--s5) 0;
  flex-wrap:wrap}
.cta.start{margin:var(--s4) 0 0;justify-content:flex-start}
.facts{display:grid;grid-template-columns:repeat(2,1fr);gap:0 var(--s6);
  list-style:none;padding:0;text-align:left}
/* Four boxes inside a box: the facts are ruled off from each other instead. */
.facts li{padding:var(--s3) 0;border-top:1px solid var(--rule)}
.facts b{display:block}
.facts span{color:var(--muted);font-size:.85rem}
.shelf{list-style:none;padding:0;margin:var(--s4) 0 0;display:grid;
  grid-template-columns:repeat(auto-fit,minmax(17rem,1fr));gap:var(--s4)}
.shelf li{background:var(--sunk);border:1px solid var(--line);
  border-radius:var(--sheet);padding:var(--s3);box-shadow:var(--press)}
.shelf b{display:block;font-family:var(--head)}
.shelf audio{width:100%;height:34px;margin:var(--s3) 0 var(--s1)}
.shelf q{display:block;color:var(--muted);font-size:.85rem}
/* A library of eighty clips is a catalogue, not eighty panels: each entry is
   ruled off at the top and carries its own name, player and credit. */
.grid.clips{display:grid;
  grid-template-columns:repeat(auto-fill,minmax(19rem,1fr));
  gap:0 var(--s6);margin-top:var(--s2)}
/* A grid child is min-width:auto, so the credit's unbroken line of licence and
   source set the card's width and pushed the page sideways on a phone. */
.grid.clips>*{min-width:0}
.card.sound{background:none;box-shadow:none;border:0;border-radius:0;
  border-top:1px solid var(--rule);padding:var(--s3) 0 var(--s2);min-width:0}
.card.sound h3{margin:0 0 .15rem;font-size:.95rem}
.card.sound.mine{border-top-color:var(--accent)}
/* The action and the credit share one line, and the credit elides rather than
   wrapping: the licence is a link away, not something to read eighty times. */
.card.sound .soundfoot{display:flex;align-items:baseline;gap:var(--s3);
  margin:var(--s2) 0 0;min-width:0}
.card.sound .soundfoot .note{flex:1;min-width:0;margin:0;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.shelf-name{margin:var(--s5) 0 0;font-family:var(--body);font-size:.7rem;
  font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted)}
.lines textarea{min-height:3rem}

/* --- usage -------------------------------------------------------------- */
.months{list-style:none;padding:0;margin:var(--s2) 0 0;max-width:46rem}
.months li{display:flex;gap:var(--s4);align-items:baseline;flex-wrap:wrap;
  padding:var(--s2) 0;border-bottom:1px solid var(--rule)}
.months li b{font-family:var(--head);min-width:6.5rem}
.months li:last-child{border-bottom:none}
.months .kinds{color:var(--muted);font-size:.85rem;flex:1 1 14rem}
.months li.empty b,.months li.empty span{color:var(--muted)}
/* A span with a height is still a line of text: the meter has to be a block or
   it renders as a hairline rule under the figure. */
.bar{display:block;width:100%;max-width:24rem;
  background:var(--sunk);border:1px solid var(--line);border-radius:99px;
  height:.45rem;overflow:hidden;margin:.4rem 0 .15rem;box-shadow:var(--well)}
.bar i{display:block;height:100%;background:var(--accent)}
.bar.near i{background:var(--warn)}

/* --- developer pages ---------------------------------------------------- */
/* A reference is read by someone copying commands out of it, so the verb is a
   badge you can scan for and the example is the widest thing on the row. */
.endpoint{border-top:1px solid var(--rule);padding:var(--s3) 0 .2rem}
.endpoint:first-of-type{border-top:0}
.endpoint h3{margin:0 0 .35rem;display:flex;align-items:center;gap:var(--s2);
  flex-wrap:wrap;font-size:1rem}
.endpoint p{margin:.2rem 0 var(--s3);color:var(--muted);font-size:.9rem}
.verb{font-family:var(--mono);font-size:.66rem;font-weight:700;
  letter-spacing:.08em;padding:.2rem .45rem;border-radius:var(--r-sm);
  background:var(--sunk);border:1px solid var(--line);color:var(--muted)}
.verb.post{color:#e7b071;border-color:#4a3a2a}
.verb.get{color:#8fb9a3;border-color:#2f4238}
.verb.delete{color:var(--bad);border-color:#4a2f2f}
fieldset.inline{display:flex;gap:var(--s4);flex-wrap:wrap;padding:.6rem .75rem}
fieldset.inline label.check{margin:0}

/* --- the recorder ------------------------------------------------------- */
/* A take is a performance, so the row reads like a deck: key, clock, and a live
   level that only moves while the microphone is open. */
.rec{border:1px solid var(--line);border-radius:var(--sheet);
  padding:var(--s3);margin:0 0 var(--s3);background:var(--raised);
  box-shadow:var(--press)}
.rec-row{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.rec-clock{font-family:var(--mono);font-size:.95rem;min-width:3.2rem}
.rec-level{display:flex;align-items:center;gap:2px;height:22px;flex:1;
  min-width:90px}
.rec-level i{flex:1;max-width:5px;border-radius:2px;background:var(--accent);
  height:22px;transform:scaleY(var(--v,.06));transform-origin:center;
  transition:transform .08s linear;opacity:.85}
.rec [data-role="rec-audio"]{width:100%;margin:var(--s3) 0 .2rem}
.rec p{margin:var(--s2) 0 .3rem}
@media (prefers-reduced-motion:reduce){.rec-level i{transition:none}}
pre.trace{background:var(--sunk);border:1px solid var(--line);
  border-radius:var(--sheet);padding:var(--s2);font-family:var(--mono);
  font-size:.72rem;overflow:auto;max-height:16rem;color:var(--muted);
  white-space:pre-wrap}

/* --- the walkthrough ---------------------------------------------------- */
/* The veil dims the page without catching clicks, so the control being
   explained can still be used while it is explained. */
.tour-veil{position:fixed;inset:0;background:rgba(9,8,7,.55);z-index:40;
  pointer-events:none}
.tour-card{position:absolute;z-index:42;max-width:22rem;background:var(--raised);
  border:1px solid var(--line);border-radius:var(--sheet);padding:var(--s4);
  box-shadow:var(--deep)}
.tour-card h2{font-size:1.05rem;margin:.15rem 0 var(--s1)}
.tour-card p{margin:0 0 var(--s3)}
.tour-count{font-size:.68rem;letter-spacing:.12em;text-transform:uppercase;
  color:var(--muted)}
.tour-lit{position:relative;z-index:41;border-radius:var(--sheet);
  box-shadow:0 0 0 3px var(--accent),0 0 0 12px rgba(231,176,113,.18)}
@media (prefers-reduced-motion:no-preference){
  .tour-card{transition:top .18s ease,left .18s ease}
}

/* --- the signed-out footer --------------------------------------------- */
.foot{max-width:1100px;margin:0 auto;padding:var(--s5);color:var(--muted);
  font-size:.85rem;border-top:1px solid var(--line);display:flex;gap:var(--s4);
  flex-wrap:wrap;align-items:center}
.foot a{color:var(--muted)}
.foot a:hover{color:var(--text)}
.foot .lead{display:flex;align-items:center;gap:var(--s2);color:var(--text);
  font-family:var(--head)}
.foot .lead .mark{width:1.5rem;height:1.5rem}
.foot .lead .mark svg{width:1rem;height:1rem}
.foot .fine{margin-left:auto;color:var(--muted)}
/* The signed-out header sits on the artwork instead of in a grey bar. */
.topbar.public{background:transparent;padding:.95rem var(--s5)}
/* The drawn Naadly mark: sized like the glyph it replaces, and given the same
   optical weight in the footer, where the lockup is set smaller. */
.logo .mk,.foot .lead .mk{width:1.9rem;height:1.9rem;flex:none;object-fit:contain}
.foot .lead .mk{width:1.5rem;height:1.5rem}
/* The lockup is set by its height, so the drawn wordmark sits on the same
   baseline as the navigation beside it whatever the artwork's aspect. */
.logo .wm{width:auto;height:1.85rem;display:block}
.mark{display:grid;place-items:center;width:1.9rem;height:1.9rem;flex:none;
  border-radius:99px 99px 99px 3px;background:var(--raised);
  border:1px solid var(--line);color:var(--accent);box-shadow:var(--press)}
.mark svg{width:1.2rem;height:1.2rem}
.topbar.public .logo>span:last-child{font-size:1.14rem}
.topbar.public nav{gap:1.15rem;margin-left:var(--s3)}
.topbar.public nav a{font-size:.93rem;padding:.15rem 0;
  border-bottom:1px solid transparent;transition:color var(--fast),
  border-color var(--fast)}
.topbar.public nav a:hover{color:var(--text);text-decoration:none;
  border-bottom-color:var(--accent)}
.topbar.public .meta .ghost{color:var(--muted)}
.topbar.public .meta .ghost:hover{color:var(--text);text-decoration:none}
.topbar.public .pill{padding:.4rem .9rem;font-size:.9rem;
  transition:box-shadow var(--fast)}
.topbar.public .pill:hover{box-shadow:0 0 0 5px var(--halo)}

/* --- narrow screens ---------------------------------------------------- */
@media(max-width:1000px){
  /* The rail folds into a drawer over the top strip: a 15rem column on a phone
     leaves no room for the work itself. */
  /* Stacked, the two rows share the leftover height of a tall screen, which put
     a 148px void between the bar and a short page: they pack to the top. */
  .shell{grid-template-columns:minmax(0,1fr);align-content:start}
  .rail{position:relative;height:auto;flex-direction:row;align-items:center;
    gap:var(--s3);border-right:0;border-bottom:1px solid var(--line);
    padding:.6rem var(--s4);overflow:visible}
  .rail nav{position:absolute;top:100%;left:0;right:0;z-index:30;
    display:none;gap:var(--s4);padding:var(--s4);background:var(--card);
    border-bottom:1px solid var(--line);box-shadow:var(--deep);
    max-height:70vh;overflow:auto}
  .rail.open nav{display:flex}
  .burger{display:grid;place-items:center;margin-left:auto;width:2.3rem;
    height:2.3rem;background:var(--raised);border:1px solid var(--line);
    border-radius:var(--sheet);color:var(--text);cursor:pointer;
    box-shadow:var(--press)}
  .bench{padding:.55rem var(--s4)}
  .wrap{padding:var(--s4)}
}
/* --- the doorway: sign in, sign up, accept an invitation ------------------ */
/* This is the screen a customer sees more often than any other, and it was a
   480px form stuck to the top left of an empty page. The form is centred and
   given a panel beside it that plays a real catalogue clip, so the door argues
   for what is behind it. */
main.gate{max-width:64rem;margin:0 auto;padding:var(--s7) var(--s5);width:100%;
  display:flex;align-items:center;min-height:calc(100vh - 13rem)}
.gate-panel{display:grid;grid-template-columns:minmax(0,25rem) minmax(0,1fr);
  gap:var(--s7);align-items:center;width:100%}
.gate-form{margin:0}
.gate-form label{margin-bottom:var(--s4)}
.gate-form input{padding:.62rem .75rem;font-size:1rem}
.gate-form label .note{display:block;margin-top:.3rem;letter-spacing:0}
.gate-form .btn{width:100%;justify-content:center;padding:.68rem 1rem;
  font-size:.95rem}
.gate-form>.bad{margin:0 0 var(--s4);padding:.55rem .7rem;
  background:rgba(217,99,99,.09);border:1px solid rgba(217,99,99,.34);
  border-radius:var(--sheet)}
.gate-form>.note:first-of-type{margin:-.35rem 0 var(--s4)}
.gate-form>.muted:last-child{margin:var(--s4) 0 0;padding-top:var(--s3);
  border-top:1px solid var(--rule)}
.gate-proof{border-left:1px solid var(--rule);padding-left:var(--s5)}
.gate-proof .eyebrow{margin:0 0 var(--s3)}
.gate-clip{margin-bottom:var(--s4)}
.gate-clip header{display:flex;align-items:center;gap:var(--s3);
  margin-bottom:var(--s3)}
.gate-clip header b{display:block;font-family:var(--head);font-weight:600}
.gate-clip header .muted{display:block;font-size:.78rem}
.gate-clip q{display:block;margin-top:var(--s3);color:var(--muted);
  font-family:var(--head);font-size:.95rem;line-height:1.55}
.gate-list{list-style:none;margin:0;padding:0;color:var(--muted);
  font-size:.86rem}
.gate-list li{position:relative;padding:.32rem 0 .32rem 1.1rem}
.gate-list li::before{content:"";position:absolute;left:0;top:.85rem;
  width:.42rem;height:1px;background:var(--accent)}
@media(max-width:980px){.grid.work{grid-template-columns:1fr;gap:var(--s5)}
  .card.sidenote{border-left:0;border-top:1px solid var(--rule);
    padding:var(--s4) 0 0}}
@media(max-width:860px){.grid.two,.grid.three,.grid.aside,.grid.clips{
  grid-template-columns:1fr}
  /* The proof falls under the form rather than beside it, and loses the rule
     that only made sense as a column divider. */
  main.gate{padding:var(--s5) var(--s5) var(--s6);min-height:0;display:block}
  .gate-panel{grid-template-columns:1fr;gap:var(--s5);max-width:29rem;
    margin:0 auto}
  .gate-proof{border-left:0;border-top:1px solid var(--rule);padding:var(--s5) 0 0}
}
@media(max-width:640px){
  .topbar{gap:var(--s2);padding:.6rem .9rem}
  /* Two rows are unavoidable at this width, so they are made deliberate:
     the account line first, the search a full-width row under it. */
  .bench{gap:var(--s2) var(--s3);padding:.55rem .9rem}
  .bench .meta{order:1;flex:1 0 100%;margin-left:0;justify-content:flex-end;
    font-size:.85rem;row-gap:.1rem}
  .bench .kbd{order:2;flex:1 0 100%;width:auto}
  /* A phone has no Ctrl key, and the plan line wrapping to three rows made the
     strip taller than the page heading under it. */
  .bench .kbd kbd{display:none}
  .bench .meta>a.ghost{font-size:.8rem}
  .topbar.public .logo{flex:0 0 auto}
  .topbar.public .meta{margin-left:auto}
  .topbar.public nav{order:3;flex:1 0 100%;gap:1.1rem}
  .card{padding:var(--s4) var(--s4) var(--s3)}
  .foot .fine{margin-left:0;flex:1 0 100%}
  .facts{grid-template-columns:1fr}
  /* No room to point at anything on a phone: the walkthrough card sits at the
     bottom and the ring alone says which control is meant. */
  .tour-card{position:fixed !important;left:.6rem !important;right:.6rem;
    top:auto !important;bottom:.6rem;max-width:none}
}
@media (prefers-reduced-motion:reduce){
  *{animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important}
  .vcard:hover{transform:none}
}
