/* GENERATED by design/ship.py from design/reader/surface.css -- DO NOT EDIT. That file is the master; run `python3 design/export.py --shell` and this one is rewritten. */
/* ENGINE · THE SEARCH SURFACE — the sheet, its two columns, and the three
   kinds of row · bench: bench-surface.html · mounted by: surface.js
   ====================================================================== */
/* SEARCH IS THE SURFACE, AND STUDIO LIVES IN IT (Osca, 7 September).
   This supersedes two things at once:

     - search as a WINDOW.  `desktop/src-tauri/src/tabs.rs::open_search`
       builds a 1280x800 window of its own with three panes side by side.
       A window is a place you GO; this is a thing that opens OVER what you
       are already on, and closes without moving you.
     - studio as a DESTINATION. The tab-strip plan gave Studio its own tab
       beside Library and Reader. It has no tab here. Pulling a result in
       IS the pipeline, so the pipeline is the surface's right-hand column
       and is on the screen the whole time, whether or not anything runs.

   TWO COLUMNS, ONE FIELD, ALWAYS THE SAME WIDTH.

       +--------------------------------------------------+
       |  the field, across both                          |
       +----------------------------+---------------------+
       |  RESULTS                   |  THE WORKS          |
       |  yours and out there, in   |  the running job,   |
       |  one list, told apart by   |  the queue, and the |
       |  the spine                 |  step grid of       |
       |                            |  whatever row is    |
       |  ...                       |  open               |
       |  Video   (a hole)          |                     |
       |  Search the web            |                     |
       +----------------------------+---------------------+

   THE SPINE IS THE WHOLE DISTINCTION, and it is why the two kinds can sit
   in one list rather than in two lanes:

       a book you HAVE            a full spine, in the book's own hue
       a book you are GETTING     a spine that fills as it arrives
       a book OUT THERE           no spine, and the gutter still reserved

   The gutter is reserved in all three, so every title has the same `left`
   whatever the row is -- that is the invariant the bench prints, and it is
   what makes one list read as one list.

   IT IS CHROME, SO EVERY NUMBER HERE IS FIXED (bar.css's rule). The book is
   fluid -- 14.5px + 0.75vw and the rest -- and nothing in this file scales
   with the column. It belongs to the window, like the title bar it drops
   from.  */

:root{
  /* --- the sheet ------------------------------------------------------- */
  --sf-w:        880px;   /* one width. The columns split it; it never grows */
  --sf-top:       64px;   /* from the top edge -- clear of the 28px bar      */
  --sf-bottom:    64px;   /* the sheet stops here; the list scrolls inside   */
  --sf-radius:    14px;
  --sf-pad:       18px;
  --sf-scrim:     .34;    /* how much of what you were on is put back        */
  --sf-blur:      18px;

  /* --- the split ------------------------------------------------------- */
  --sf-split:     62%;    /* results | the works                            */
  --sf-gap:       18px;

  /* --- the field ------------------------------------------------------- */
  --sf-field:     20px;   /* the query, and it is the biggest type here      */
  --sf-fieldh:    54px;

  /* --- a row ----------------------------------------------------------- */
  --sf-row:       46px;   /* the minimum; a row grows to its own two lines   */
  --sf-gutter:    16px;   /* reserved for the spine, in every kind of row    */
  --sf-spine:    2.5px;
  --sf-title:     15px;
  --sf-meta:     9.5px;
  --sf-head:     9.5px;   /* a section head                                  */

  /* --- the step ribbon -------------------------------------------------- */
  --sf-cell:       7px;
  --sf-cellgap:    3px;

  /* --- the video hole ---------------------------------------------------- */
  --sf-video:    300px;   /* when it is open. Closed it is 0 and the shell
                             hides the webview by itself (videos_rect: a box
                             under 1px high is None)                         */

  /* --- ITS OWN PALETTE, AND ITS OWN TYPE (G-SURF2, 10 Sep) -----------------
     Osca: *"Opened from the library it's grey-tinted and loose; from a reader
     it's yellow-tinted and tight -- it must be the same sheet regardless of
     what's behind."* It was reading the HOST's tokens -- `--ground`, `--ink`,
     `--dim`, `--rule`, `--ui`, `--serif` -- and the two hosts disagree about
     every one of them:
       reader   tokens.css, with the reader's paper WARMTH folded into
                `--ground` -- so the sheet took the page's cream (the yellow)
       library  tokens.css is NOT LOADED, so all six are undefined, and a
                `var()` of an undefined name makes its whole declaration
                invalid: the background went TRANSPARENT (the grey was the
                library itself, blurred through it), every `font:` shorthand
                fell back to the inherited 16px (the loose), and the border
                vanished.
     Measured before this, off the two real pages at 1440x900 with the same
     query: 192 of 195 shared nodes differed in computed style.
     So the sheet carries its own six, and nothing in this file reads a host
     token any more. The values are tokens.css's own at `--warm: 0` -- the
     near-neutral paper, the reader's own formula with the warmth taken out --
     because chrome does not follow the book's paper (bar.css's rule: chrome
     is fixed). Dark is the same swap tokens.css makes, on the same three
     selectors, so Settings' theme reaches the sheet exactly as it reaches a
     page. */
  --sf-ground-hsl: 48 14% 98.5%;
  --sf-ground:  hsl(var(--sf-ground-hsl));
  --sf-ink:     hsl(42 18% 7%);
  --sf-dim:     #7a776d;
  --sf-rule:    #dedcd4;
  --sf-ui:      -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --sf-serif:   "Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
  /* HOW SOLID THE SHEET IS. 1 is opaque. It was 0 over the library (the
     background declaration was invalid, see above) and 1 over the reader;
     .97 lets 3 % of what is behind through the blur -- enough to say the
     sheet is OVER something, never enough to tint it. One number: the pixel
     proof (design/reader/pixelcheck/sheet.mjs) runs once at this value and
     once with it forced to 1, and at 1 the two hosts are identical inside the
     sheet to the pixel. */
  --sf-solid:   .97;
  --sf-sheet:   hsl(var(--sf-ground-hsl) / var(--sf-solid));
  /* the type every node inherits unless it says otherwise -- so an element
     with no size of its own takes 12px from HERE, not 16px from the library's
     body or 26.8px from the reader's fluid <html> */
  --sf-size:    12px;
  --sf-lh:      1.35;

  /* --- the phone --------------------------------------------------------- */
  --sf-narrow:   720px;   /* under this the sheet is the screen, one column  */
}

/* DARK IS THE SAME SWAP tokens.css MAKES, on the same selectors (prefs/ stamps
   html[data-theme]; "system" stamps nothing and leaves the media query in
   charge) -- and at warmth 0, like the light half. */
html[data-theme="dark"], html[data-dark]{
  --sf-ground-hsl: 240 7.3% 8.04%;
  --sf-ink: hsl(30 4.17% 90.59%); --sf-dim:#8c8a83; --sf-rule:#2e2e33;
}
@media (prefers-color-scheme: dark){
  html:not([data-theme="light"]){
    --sf-ground-hsl: 240 7.3% 8.04%;
    --sf-ink: hsl(30 4.17% 90.59%); --sf-dim:#8c8a83; --sf-rule:#2e2e33;
  }
}

/* ============================ THE SCRIM ================================= */
/* You are still ON something. The scrim says so and takes the dismiss. */
.sf-scrim{
  position:fixed; inset:0; z-index:8000;
  background:rgba(0,0,0,var(--sf-scrim));
  opacity:0; pointer-events:none; transition:opacity .16s ease;
}
.sf-scrim.on{ opacity:1; pointer-events:auto; }

/* ============================ THE SHEET ================================= */
.sf{
  position:fixed; z-index:8001;
  left:50%; top:var(--sf-top);
  width:var(--sf-w); max-width:calc(100vw - 32px);
  height:calc(100vh - var(--sf-top) - var(--sf-bottom));
  transform:translate(-50%, -8px); opacity:0; pointer-events:none;
  transition:opacity .16s ease, transform .16s ease;
  display:flex; flex-direction:column;
  box-sizing:border-box;
  background:var(--sf-sheet); color:var(--sf-ink);
  /* EVERY INHERITED PROPERTY, PINNED HERE, so no host reaches a node inside
     through inheritance: the library's 16px body, the reader's fluid rem, a
     page's letter-spacing or line-height. The list is what the two-host diff
     found and what could find it next. */
  font:400 var(--sf-size)/var(--sf-lh) var(--sf-ui);
  letter-spacing:normal; word-spacing:normal; text-transform:none;
  text-align:left; text-indent:0; white-space:normal;
  font-variant:normal; font-feature-settings:normal; font-kerning:auto;
  -webkit-font-smoothing:antialiased; text-rendering:auto;
  border:1px solid var(--sf-rule); border-radius:var(--sf-radius);
  box-shadow:0 26px 70px rgba(0,0,0,.28), 0 3px 10px rgba(0,0,0,.10);
  overflow:hidden;
  -webkit-backdrop-filter:blur(var(--sf-blur)); backdrop-filter:blur(var(--sf-blur));
}
.sf.on{ opacity:1; transform:translate(-50%, 0); pointer-events:auto; }
/* THE LIBRARY'S `* { box-sizing: border-box }` REACHED EVERY NODE HERE and
   the reader's page has no such rule -- 168 nodes measured apart, and the
   list and works columns a different width in each. `revert` hands each node
   back the browser's own value (content-box for a span, border-box where the
   UA says so), which is what the bench measured every rectangle against; the
   two rules below that want border-box say so themselves, later in the file. */
.sf *, .sf *::before, .sf *::after{ box-sizing:revert; }

/* ============================ THE FIELD ================================= */
/* One field for the whole surface. The bar upstairs carries only the door to
   here (Osca: "The BAR carries only the entry to it"), so this is the only
   place in the application a query is typed. */
.sf-field{
  flex:0 0 auto; height:var(--sf-fieldh);
  display:flex; align-items:center; gap:11px;
  padding:0 var(--sf-pad); box-sizing:border-box;
  border-bottom:1px solid var(--sf-rule);
}
/* the lookup ring, bar.css's own -- a ring with a hand, not a magnifier,
   because a lookup lands you at a PLACE IN A BOOK */
.sf-look{ flex:0 0 auto; width:18px; height:18px; display:block; color:var(--sf-dim); }
.sf-look svg{ width:18px; height:18px; display:block; fill:none; stroke:currentColor; stroke-width:1.4; stroke-linecap:round; }
.sf-field input{
  flex:1 1 auto; min-width:0; border:0; outline:0; background:transparent;
  font:var(--sf-field)/1.2 var(--sf-ui); letter-spacing:-.01em; color:var(--sf-ink);
}
.sf-field input::placeholder{ color:var(--sf-dim); }
.sf-esc{
  flex:0 0 auto; font:600 9px/1 var(--sf-ui); letter-spacing:.12em;
  text-transform:uppercase; color:var(--sf-dim);
  background:transparent; border:1px solid var(--sf-rule); border-radius:5px;
  padding:5px 7px; cursor:pointer;
}
.sf-esc:hover{ color:var(--sf-ink); }

/* ============================ THE COLUMNS =============================== */
.sf-cols{ flex:1 1 auto; display:flex; min-height:0; }
.sf-list{
  flex:0 0 var(--sf-split); min-width:0;
  padding:6px var(--sf-pad) var(--sf-pad);
  overflow-y:auto; overscroll-behavior:contain;
}
.sf-works{
  flex:1 1 auto; min-width:0;
  padding:6px var(--sf-pad) var(--sf-pad);
  border-left:1px solid var(--sf-rule);
  overflow-y:auto; overscroll-behavior:contain;
}

/* a section head, in both columns */
.sf-h{
  display:block; padding:14px 0 6px;
  font:600 var(--sf-head)/1 var(--sf-ui); letter-spacing:.14em;
  text-transform:uppercase; color:var(--sf-dim);
}
.sf-h:first-child{ padding-top:6px; }

/* ============================== A ROW =================================== */
.sf-row{
  position:relative; display:flex; align-items:flex-start; gap:10px;
  min-height:var(--sf-row);
  padding:9px 0 9px var(--sf-gutter);
  border-bottom:1px solid var(--sf-rule);
  color:inherit; text-decoration:none;
  border-radius:6px;
}
.sf-row:last-child{ border-bottom:0; }
.sf-row .spine{
  position:absolute; left:0; top:9px; width:var(--sf-spine);
  height:0; border-radius:var(--sf-spine);
  background:var(--sf-dim); transition:height .28s ease;
}
.sf-row .body{ flex:1 1 auto; min-width:0; }
.sf-row .t{
  display:block; font-family:var(--sf-serif); font-size:var(--sf-title);
  line-height:1.24; letter-spacing:-.02em; color:var(--sf-ink);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
/* THE SECOND LINE IS A ROW, NOT A STRING (Round 2 item 5).
   It was one span with `white-space:nowrap; text-overflow:ellipsis`, holding
   `author · source` joined — so the ellipsis ate the SOURCE off the right end
   whenever the author was long, and the one word a person needs to judge a
   result was the first thing to go. Measured on the mock's own long author
   ("Benedictus de Spinoza, translated from the Latin by R. H. M. Elwes, with
   an introduction"): the source was not on the row at all.
   Now it is a flex row: the source, the language and the text/audio marker are
   `flex:0 0 auto` and CANNOT be cut; the author is the only `1 1 auto`, so it
   is the thing that truncates. A WORK row still puts a plain string in here
   and that keeps working — a lone text node in a flex row lays out as one
   item, and `min-width:0` lets it shrink. */
.sf-row .s{
  display:flex; align-items:baseline; gap:7px; margin-top:.45em;
  font:var(--sf-meta)/1.3 var(--sf-ui); letter-spacing:.14em;
  text-transform:uppercase; color:var(--sf-dim);
  overflow:hidden; white-space:nowrap; min-width:0;
}
.sf-row .s > .sf-who{
  flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis;
}
.sf-row .s > .sf-src-tag,
.sf-row .s > .sf-lang,
.sf-row .s > .sf-ta{ flex:0 0 auto; }
.sf-row .s > .sf-src-tag{ color:var(--sf-ink); font-weight:600; }
.sf-row .s > .sf-lang{ opacity:.7; }

/* ITEM 6 · TEXT, AUDIO, OR BOTH — three states and no fourth. Both is the
   only one that is good news, so it is the only one with any weight. */
.sf-ta{ letter-spacing:.1em; }
.sf-ta.ta-both{ color:#3f7a4a; }
.sf-ta.ta-text{ opacity:.75; }
.sf-ta.ta-audio{ color:#a8532a; }

/* ITEM 4 · the facts, on their own wrapping line — *"don't drop data because
   it's long"*, so they wrap rather than truncate */
.sf-facts{
  display:flex; flex-wrap:wrap; gap:4px 10px; margin-top:.4em;
  font:var(--sf-meta)/1.4 var(--sf-ui); letter-spacing:.1em;
  text-transform:uppercase; color:var(--sf-dim);
}
.sf-facts i{ font-style:normal; }
.sf-preview{
  display:block; margin-top:.45em; max-width:60ch;
  font:12px/1.5 var(--sf-serif); color:var(--sf-dim);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}

/* G-SURF2 · WHERE IT CAME FROM, on the row. One line under the second:
   the origin, then the file. Lowercase and monospaced -- both are names you
   may have to type or find, and letter case is part of a path, which the
   meta line's small capitals would have thrown away. Each half truncates on
   its own, the origin first; the whole of both is in each half's title and,
   selected, in THE WORKS. */
.sf-prov{
  display:flex; align-items:baseline; gap:6px; margin-top:.4em; min-width:0;
  font:10px/1.35 ui-monospace, SFMono-Regular, Menlo, monospace;
  color:var(--sf-dim); white-space:nowrap; overflow:hidden;
}
.sf-prov .po{ flex:0 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; }
.sf-prov .pf{ flex:0 1 auto; min-width:3em; overflow:hidden; text-overflow:ellipsis;
  color:var(--sf-ink); opacity:.78; }
.sf-prov .sep{ flex:0 0 auto; opacity:.6; }
.sf-prov .po:empty, .sf-prov .po:empty + .sep{ display:none; }
/* an import that did not come in: studio's own sentence, whole, wrapping */
.sf-prov.err{ display:block; white-space:pre-wrap; overflow-wrap:anywhere;
  max-height:6.8em; overflow:auto; color:#a8532a; }
.sf-provpane .sf-path, .sf-provpane .sf-origin{ padding-top:5px; }
.sf-provpane .sf-origin{ color:var(--sf-ink); }

/* ITEM 8 · the whole row is a target, and it looks like one */
.sf-row.r-out{ cursor:pointer; }
.sf-row.r-out:hover{ background:rgba(127,127,127,.07); }
.sf-row.r-out:hover .t{ text-decoration:underline; text-underline-offset:2px; }
.sf-row.r-out.sel{ background:rgba(127,127,127,.10); }

/* ITEMS 1+2 · the WORKING band owns running, and its header owns Hold all */
.sf-h.sf-workhead{
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
}
.sf-h.sf-workhead .wl{ flex:1 1 auto; }
.sf-h.sf-workhead .sf-verb{ flex:0 0 auto; }
.sf-heldwhy{
  flex:1 0 100%; text-transform:none; letter-spacing:0;
  font:11px/1.4 var(--sf-ui); color:#a8532a;
}
.sf-rowacts{ display:inline-flex; align-items:center; gap:5px; }
.sf-row.r-queued .spine{ opacity:.45; height:calc(100% - 26px); }
.sf-row.r-queued .t{ opacity:.8; }

/* ITEM 7 · the audition, in the panel */
.sf-peekpane{ border-top:1px solid var(--sf-rule); margin-top:8px; }
.sf-peekaudio{ padding:6px 0; }
.sf-peekaudio audio{ width:100%; height:32px; }
.sf-peektext, .sf-candtext{
  margin:6px 0 10px; padding:0; max-height:200px; overflow:auto;
  white-space:pre-wrap; word-break:break-word;
  font:11.5px/1.5 var(--sf-serif); color:var(--sf-dim);
}
.sf-pair{
  margin:2px 0 8px; font:10.5px/1.45 var(--sf-ui); color:var(--sf-dim);
}
/* THE VERBS NEVER CRUSH THE WORDS (Osca, 9 Oct 16:24: "as layout for audio files, this is awful"): a recording row
   carries four verbs (Audition · Open · Attach to … · Use as voice) and `.end` was `flex:0 0 auto`, so the body shrank
   to nothing -- the title to "Time Mac…", the facts to one word a line. The row wraps: the body keeps at least 240px
   and the verbs go under the words as one line of their own when they do not fit beside them; a long verb (the
   join's progress) wraps inside `.end` rather than pushing. */
.sf-row{ flex-wrap:wrap; }
.sf-row .body{ flex:1 1 240px; }
/* and DETERMINISTIC (the 9 Oct Stranger: the rows flipped between two heights on every redraw -- the verbs wrapped
   or not with the scrollbar's width): three verbs or more ALWAYS go under the words, whatever the width */
.sf-row:has(> .end > :nth-child(3)) > .end{ flex:1 0 100%; }
.sf-row .end{
  flex:0 1 auto; max-width:100%; display:flex; flex-wrap:wrap; align-items:center; gap:7px;
  padding-top:2px;
  font:var(--sf-meta)/1.3 var(--sf-ui); letter-spacing:.12em;
  text-transform:uppercase; color:var(--sf-dim);
}

/* --- ON THE SHELF: the row IS the door, and the spine is full ----------- */
/* §5.8, 8 Sep -- EVERY ROW ON THE LEFT IS A TARGET, and one rule says so.
   Osca: *"Right now hovering a book on the left does nothing -- only ADD is a
   target."* It was three rules with three different answers: `.r-shelf` was
   a pointer, `.sf-hit` was a pointer, and `.r-out` -- the fetchable result,
   the row that complaint is about -- had neither cursor nor hover, so four
   fifths of it was dead space above a button. This is the whole of it now,
   and the per-kind rules below say only what is still DIFFERENT about a kind
   (the spine's height), never whether it can be clicked. */
.sf-row:not(.sf-query){ cursor:pointer; }
.sf-row:not(.sf-query):hover{ background:rgba(127,127,127,.07); }
.sf-row.sel{ background:rgba(127,127,127,.10); }
/* the selected row is named by the spine as well as the wash, so it is still
   legible at the top of a long list with the pointer somewhere else */
.sf-row.sel .spine{ opacity:1; }

.sf-row.r-shelf{ cursor:pointer; }
.sf-row.r-shelf .spine{ height:calc(100% - 18px); }
/* folded into `.sf-row:not(.sf-query):hover` above (8 Sep, §5.8) */

/* --- OUT THERE: no spine, and one verb --------------------------------- */
.sf-row.r-out .spine{ height:0; }
.sf-row.r-out .t{ color:var(--sf-ink); }

/* --- WORKING: the spine fills, and a hairline runs under the row -------- */
.sf-row.r-work{ cursor:pointer; }
.sf-row.r-work .spine{ height:calc((100% - 18px) * var(--p, 0)); }
.sf-row.r-work .under{
  position:absolute; left:0; right:0; bottom:-1px; height:1px;
  background:linear-gradient(to right,
    var(--hue) 0, var(--hue) calc(var(--p, 0) * 100%),
    transparent calc(var(--p, 0) * 100%));
}

/* WHAT A SHELF ROW SAYS AT ITS RIGHT, and the second target on it. The row
   is the door -- it opens the book -- so "show me its steps" cannot also be
   the row; it is this, and it stops the click from reaching the door. */
.sf-row .end .cnt{ white-space:nowrap; }
.sf-peek{
  flex:0 0 auto; display:flex; align-items:center; justify-content:center;
  width:18px; height:18px; padding:0; margin-right:-4px;
  background:none; border:0; border-radius:4px; cursor:pointer; opacity:0;
  transition:opacity .12s ease;
}
.sf-row:hover .sf-peek, .sf-row.sel .sf-peek, .sf-peek:focus-visible{ opacity:1; }
.sf-peek:hover{ background:rgba(127,127,127,.12); }
.sf-peek .chev{ margin:0; transform:rotate(-45deg) translate(-1px,1px); }

/* the one verb, the library's drawn read button at this row's size */
.sf-verb{
  font:600 9px/1 var(--sf-ui); letter-spacing:.10em; text-transform:uppercase;
  color:var(--sf-ground); background:var(--sf-ink);
  border:0; border-radius:999px; padding:.62em 1.15em; cursor:pointer;
  white-space:nowrap;
}
.sf-verb[disabled]{ background:transparent; color:var(--sf-dim);
  box-shadow:inset 0 0 0 1px var(--sf-rule); cursor:default; }

/* ========================= THE STEP RIBBON ============================== */
/* studio/state.py STEPS, in its order and its length: parse, interpret,
   speak, restitch, align, prosody, dict, export. Eight cells at a row's
   scale is a lot of furniture, so the bench carries a three-cell coarse
   version too (parse / voice / ready) -- one switch, and Osca picks. */
.sf-steps{ display:flex; gap:var(--sf-cellgap); align-items:center; }
.sf-steps i{
  display:block; width:var(--sf-cell); height:var(--sf-cell);
  border-radius:1.5px; background:transparent;
  box-shadow:inset 0 0 0 1px var(--sf-rule);
}
.sf-steps i.ok  { background:var(--hue, var(--sf-ink)); box-shadow:none; }
.sf-steps i.run { background:var(--hue, var(--sf-ink)); opacity:.45;
                  animation:sfPulse 1.1s ease-in-out infinite; box-shadow:none; }
.sf-steps i.bad { background:#a8532a; box-shadow:none; }
@keyframes sfPulse{ 0%,100%{ opacity:.28 } 50%{ opacity:.72 } }

/* ============================ THE WORKS ================================= */
/* studio/studio.html's cockpit, folded in. The card, the queue and the grid
   are the same three things it draws, at this width. */
.sf-card{ padding:2px 0 10px; border-bottom:1px solid var(--sf-rule); }
.sf-card .l{ display:flex; justify-content:space-between; gap:8px;
  font:11px/1.35 var(--sf-ui); color:var(--sf-ink); }
.sf-card .l b{ font-weight:600; }
.sf-card .l span:last-child{ color:var(--sf-dim); font-variant-numeric:tabular-nums; }
.sf-bar{ display:block; height:3px; margin:8px 0 7px; border-radius:2px;
  background:var(--sf-rule); overflow:hidden; }
.sf-bar i{ display:block; height:100%; background:var(--hue, var(--sf-ink));
  width:calc(var(--p, 0) * 100%); transition:width .3s ease; }
/* slides as a picture, not by margin-left (Osca 14 Oct 17:29, draft D approved): the same bar at the same place
   at every instant -- 36% wide from -36% to 100% of the track is -100% to +277.778% of its own width */
.sf-bar.indeterminate i{ width:36%; will-change:transform; animation:sfSlide 1.5s ease-in-out infinite; }
@keyframes sfSlide{ 0%{ transform:translateX(-100%) } 100%{ transform:translateX(277.778%) } }
.sf-st{ font:10px/1.3 var(--sf-ui); color:var(--sf-dim); }
.sf-lnk{ background:none; border:0; padding:0; font:inherit; color:var(--sf-dim);
  text-decoration:underline; text-underline-offset:2px; cursor:pointer; }
.sf-lnk:hover{ color:var(--sf-ink); }
.sf-lnk[disabled]{ opacity:.45; cursor:default; text-decoration:none; }

.sf-q{ display:flex; align-items:center; gap:7px; padding:6px 0;
  font:10.5px/1.3 var(--sf-ui); color:var(--sf-ink); border-bottom:1px solid var(--sf-rule); }
.sf-q .qn{ flex:1 1 auto; min-width:0; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.sf-q .qv{ flex:0 0 auto; color:var(--sf-dim); }
.sf-q .qx{ flex:0 0 auto; background:none; border:0; padding:2px; color:var(--sf-dim);
  cursor:pointer; opacity:0; transition:opacity .12s ease; }
.sf-q:hover .qx{ opacity:1; }
.sf-q .qx:hover{ color:var(--sf-ink); }

/* the grid: one line per chapter, its eight cells at the right */
.sf-grid{ display:block; }
.sf-gr{ display:flex; align-items:center; gap:8px; padding:5px 0;
  font:10.5px/1.3 var(--sf-ui); color:var(--sf-ink); border-bottom:1px solid var(--sf-rule); }
.sf-gr .gid{ flex:0 0 auto; color:var(--sf-dim); font-variant-numeric:tabular-nums; }
.sf-gr .gt{ flex:1 1 auto; min-width:0; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }

.sf-note{ display:block; padding:8px 0; font:10.5px/1.45 var(--sf-ui); color:var(--sf-dim); }

/* ======================= VIDEO, AND THE WEB ============================= */
/* The two lanes that are not books keep their place -- at the foot of the one
   list rather than in panes of their own. Video is CLOSED until asked: the
   hole is 0 high, and a box under a pixel is `None` to `videos_rect`, so the
   shell's second webview is hidden without this page saying anything. */
.sf-video{ height:0; overflow:hidden; transition:height .2s ease;
  border-radius:6px; background:transparent; }
.sf-video.open{ height:var(--sf-video); }
.sf-video iframe{ display:block; width:100%; height:var(--sf-video); border:0; }
.sf-row .chev{ display:inline-block; width:7px; height:7px; margin-left:2px;
  border-right:1.2px solid var(--sf-dim); border-bottom:1.2px solid var(--sf-dim);
  transform:rotate(45deg) translate(-1px,-1px); transition:transform .2s ease; }
.sf-row.open .chev{ transform:rotate(-135deg) translate(-2px,-2px); }
.sf-row .q{ display:block; margin-top:.45em; font:var(--sf-meta)/1.4 var(--sf-ui);
  letter-spacing:0; text-transform:none; color:var(--sf-dim); white-space:normal;
  overflow-wrap:anywhere; }

/* ============================== THE PHONE =============================== */
/* One column, the whole screen. The works is not a second column here -- it
   is a band at the TOP of the one column, and only when something runs,
   because that is the only time it beats a result for the room. */
@media (max-width:720px), (pointer:coarse){
  .sf{ left:0; top:0; width:100%; max-width:none; height:100%;
       transform:translate(0, 10px); border-radius:0; border:0;
       padding-top:env(safe-area-inset-top, 0px); }
  .sf.on{ transform:translate(0,0); }
  .sf-cols{ flex-direction:column; }
  .sf-list{ flex:1 1 auto; order:2; }
  .sf-works{ flex:0 0 auto; order:1; border-left:0;
             border-bottom:1px solid var(--sf-rule); max-height:38vh; }
  .sf-works.empty{ display:none; }
  :root{ --sf-title:17px; --sf-meta:10.5px; --sf-row:56px; --sf-field:19px; }
}


/* ==========================================================================
   8 SEPTEMBER — WHAT EACH SOURCE DID, THE ELSEWHERE HITS, AND A COLUMN THAT
   ACTS. Nothing here changes a row's geometry: the gutter, the spine and the
   title's left are untouched, because `titleLefts` being a set of size ONE is
   the invariant the whole list rests on and every new row goes through the
   same `rowShell()`.
   ====================================================================== */

/* --- the per-source report, AT THE TOP OF RESULTS (G-SURF2, 10 Sep) -----
   It was a row of chips under the list, drawn once the answer was in, and
   while the search was out the page had one grey "Searching…" note -- which
   a redraw a microtask later took away. Now it is the first thing under the
   Results head for as long as there is a query: ASKING while `/search` is
   out (every source by name, the seconds, a bar filling against studio's
   25 s), ANSWERED after (what each source did). Same element both times, so
   nothing jumps when the answer lands.

   WHILE ASKING IT IS STICKY AT BOTH EDGES -- `top` AND `bottom` -- so a long
   WORKING band above it cannot push it off either end of the list: scrolled
   down, it holds the top; pushed below the fold, it holds the bottom. A wait
   you cannot see is the thing this exists to end. Opaque there, because rows
   pass under it. */
.sf-src{ display:flex; flex-wrap:wrap; align-items:center; gap:5px;
         padding:8px 0 10px; border-bottom:1px solid var(--sf-rule); }
.sf-srchead{ flex:1 0 100%; display:flex; align-items:baseline; gap:10px; min-width:0;
  font:11px/1.4 var(--sf-ui); color:var(--sf-dim); }
.sf-srchead .hl{ flex:1 1 auto; min-width:0; overflow-wrap:anywhere; }
.sf-srchead .ck{ flex:0 0 auto; font-variant-numeric:tabular-nums; }
.sf-src.asking{ position:sticky; top:0; bottom:0; z-index:2;
                background:var(--sf-ground); }
.sf-src.asking .sf-srchead{ font:600 13px/1.35 var(--sf-ui); color:var(--sf-ink); }
.sf-src.asking .sf-srchead .ck{ font-weight:400; color:var(--sf-dim); }
.sf-srcbar{ flex:1 0 100%; display:block; height:2px; margin:1px 0 3px;
  border-radius:1px; background:var(--sf-rule); overflow:hidden; }
.sf-srcbar i{ display:block; height:100%; width:0; background:var(--sf-ink);
  transition:width .5s linear; }
.sf-srcsub{ flex:1 0 100%; padding-top:2px; font:10.5px/1.45 var(--sf-ui);
  color:var(--sf-dim); }
/* asked, not yet answered: dashed, with a dot that breathes on the step
   cells' own clock -- present and plainly unfinished */
.sf-chip.s-ask{ border-style:dashed; }
.sf-chip.s-ask i::before{ content:""; display:inline-block; width:5px; height:5px;
  margin-right:4px; vertical-align:1px; border-radius:50%; background:currentColor;
  animation:sfPulse 1.1s ease-in-out infinite; }
.sf-chip{ display:inline-flex; align-items:baseline; gap:5px; cursor:default;
          padding:2px 7px; border-radius:10px; border:1px solid var(--sf-rule);
          font:var(--sf-meta)/1.5 var(--sf-ui); color:var(--sf-dim); }
.sf-chip b{ font-weight:600; color:var(--sf-ink); }
.sf-chip i{ font-style:normal; font-variant-numeric:tabular-nums; }
/* the four words, and only two of them are bad news */
.sf-chip.s-n{ border-color:color-mix(in srgb, var(--sf-ink) 30%, transparent); }
.sf-chip.s-n i{ color:var(--sf-ink); }
.sf-chip.s-down, .sf-chip.s-failed{ cursor:pointer;
  border-color:#a8532a; color:#a8532a; }
.sf-chip.s-down b, .sf-chip.s-failed b{ color:#a8532a; }
.sf-chip.s-off{ cursor:pointer; opacity:.72; }
.sf-chip.s-nothing{ opacity:.62; }
.sf-chip.s-drop{ opacity:.72; }
/* SURFACE-PRESS (26 Sep): a chip with rows is a FILTER -- pointer, and the
   one that is on is filled; `filtered` too. A still-running source is the
   fifth word: its rows so far, and a breathing "still asking" after them. */
.sf-chip.s-n, .sf-chip.s-drop, .sf-chip.s-still{ cursor:pointer; }
.sf-chip.on{ background:var(--sf-ink); border-color:var(--sf-ink); color:var(--sf-ground); }
.sf-chip.on b, .sf-chip.on i{ color:var(--sf-ground); }
.sf-chip.s-still{ border-style:dashed;
  border-color:color-mix(in srgb, var(--sf-ink) 30%, transparent); }
.sf-chip.s-still i:first-of-type{ color:var(--sf-ink); }
.sf-chip.s-still i.still::before{ content:""; display:inline-block; width:5px; height:5px;
  margin-right:4px; vertical-align:1px; border-radius:50%; background:currentColor;
  animation:sfPulse 1.1s ease-in-out infinite; }
.sf-chip.s-rejoined::after{ content:"↺"; font-size:.9em; opacity:.7; }
.sf-srcwhy{ flex:1 0 100%; padding:5px 0 0; color:var(--sf-dim);
            font:var(--sf-meta)/1.5 var(--sf-ui); }
/* the sentence under a row: why it was dropped, why it has no Add */
.sf-row .sf-why{ display:block; padding-top:2px; font:var(--sf-meta)/1.45 var(--sf-ui);
  color:var(--sf-dim); overflow-wrap:anywhere; }
.sf-row .sf-borrow{ color:#a8532a; }
.sf-row .sf-open-ptr{ display:block; padding-top:2px; font:var(--sf-meta)/1.45 var(--sf-ui);
  color:var(--sf-dim); }
.sf-row .sf-open-ptr i{ font-style:normal; }
.sf-row.sf-flash{ background:color-mix(in srgb, var(--sf-ink) 10%, transparent); }

/* --- a hit out there is still a row, and it still lines up --------------- */
.sf-row.sf-hit{ cursor:pointer; }
/* folded into `.sf-row:not(.sf-query):hover` above (8 Sep, §5.8) */
.sf-row.sf-query .t{ color:var(--sf-dim); }
.sf-row.sf-find{ cursor:pointer; }
/* folded into `.sf-row:not(.sf-query):hover` above (8 Sep, §5.8) */
.sf-row.sf-ch .spine{ height:calc(100% - 22px); opacity:.8; }
.sf-row .end .sf-steps{ margin-right:6px; }
/* the second verb on a row: present, and plainly the quieter of the two */
.sf-verb.ghost{ background:transparent; border:1px solid var(--sf-rule); color:var(--sf-dim); }
.sf-verb.ghost:hover{ color:var(--sf-ink); }

/* --- the works column, acting ------------------------------------------- */
.sf-acts{ display:flex; flex-wrap:wrap; gap:6px; padding:8px 0 2px; }
.sf-acts .sf-verb{ flex:0 0 auto; }
.sf-q.pick{ cursor:pointer; }
.sf-q.pick:hover{ background:rgba(127,127,127,.07); }
.sf-gr.pick{ cursor:pointer; }
.sf-gr.pick:hover{ background:rgba(127,127,127,.07); }
.sf-gr .sf-verb{ flex:0 0 auto; padding:1px 6px; font-size:9.5px; }
/* G-RUN: the row's own small verb -- the surgical door, never a second bar */
.sf-gr .sf-verb.sf-cell{ font-size:8.5px; letter-spacing:.06em; padding:2px 7px; }
.sf-runrow{ padding:6px 0 4px; }
.sf-runrow .sf-run{ max-width:100%; white-space:normal; text-align:left; line-height:1.35; }
.sf-log{ border-top:1px solid var(--sf-rule); margin-top:8px; }
.sf-logtext{ margin:0; padding:6px 0 10px; max-height:220px; overflow:auto;
             white-space:pre-wrap; word-break:break-word;
             font:10px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;
             color:var(--sf-dim); }

/* ==========================================================================
   8 SEPTEMBER, §4 — THE WORKS IS THE FULL STUDIO
   Four choices above the step grid: the cloned voice, WHERE it runs, the
   model, and the thirty seconds that proves all three. `studio/studio.html`'s
   own rows at this width — a label on the left, pills on the right, one
   sub-line under them. Nothing here touches `.sf-row`: the gutter, the spine
   and the title's left are untouched, so `titleLefts` being a set of size ONE
   is exactly as true as it was before this landed.

   A PILL THAT CANNOT BE PICKED IS DASHED, NEVER ABSENT (Osca, 8 Sep). It is a
   <span class="off">, not a button, because the server would refuse to write
   it — and the dashes are the whole visual difference, so an unusable Kaggle
   and an unusable engine read as the same kind of fact.
   ========================================================================== */
.sf-studio{ display:block; padding:2px 0 4px; }

.sf-prow{ display:flex; align-items:flex-start; gap:10px; padding:7px 0;
  border-bottom:1px solid var(--sf-rule); }
.sf-prow:last-child{ border-bottom:0; }
.sf-prow .pl{ flex:0 0 54px; padding-top:4px;
  font:600 var(--sf-head)/1.2 var(--sf-ui); letter-spacing:.12em;
  text-transform:uppercase; color:var(--sf-dim); }
.sf-prow .pc{ flex:1 1 auto; min-width:0; }

.sf-pills{ display:flex; flex-wrap:wrap; gap:5px; }
.sf-pill{
  font:10.5px/1.25 var(--sf-ui); color:var(--sf-ink);
  background:transparent; border:1px solid var(--sf-rule); border-radius:999px;
  padding:3px 9px; cursor:pointer; white-space:nowrap;
  display:inline-flex; align-items:center; gap:5px;
}
.sf-pill:hover{ border-color:var(--sf-ink); }
.sf-pill[aria-selected="true"]{ background:var(--sf-ink); color:var(--sf-ground);
  border-color:var(--sf-ink); }
.sf-pill[disabled]{ opacity:.45; cursor:default; }
/* the dashed one: present, plainly not a choice, and carrying its reason */
.sf-pill.off{ border-style:dashed; color:var(--sf-dim); cursor:default;
  white-space:normal; max-width:100%; }
.sf-pill.imp{ border-style:dashed; color:var(--sf-dim); }
.sf-pill.imp:hover{ color:var(--sf-ink); border-color:var(--sf-ink); }
/* the reference's play/pause, INSIDE the selected pill and nothing else moves */
.sf-pill .pp{ font-style:normal; font-size:9px; line-height:1; cursor:pointer;
  opacity:.8; }
.sf-pill .pp:hover{ opacity:1; }

.sf-vsub{ display:block; }
.sf-sub{ display:block; padding:5px 0 0; font:10.5px/1.45 var(--sf-ui); color:var(--sf-dim); }
.sf-sub b{ color:var(--sf-ink); font-weight:600; }
.sf-refslot{ display:block; }
.sf-refslot audio{ display:none; }   /* the pill's glyph IS the control */

/* `voice/port.py::limits()`, verbatim, ABOVE the GPU-minutes on purpose */
.sf-limits{ display:block; padding:6px 0 0; font:10px/1.5 var(--sf-ui); color:var(--sf-dim); }
.sf-limits b{ display:block; color:var(--sf-ink); font-weight:600; }
.sf-limits span{ display:block; }

.sf-sample{ display:block; }
.sf-sample audio{ display:block; width:100%; margin-top:8px; height:30px; }
.sf-est{ display:flex; flex-wrap:wrap; gap:4px 16px; padding:6px 0 0;
  font:10.5px/1.4 var(--sf-ui); color:var(--sf-ink); }
.sf-est .k{ color:var(--sf-dim); }
.sf-est b{ font-weight:600; font-variant-numeric:tabular-nums; }

/* one column: the label stacks over its pills rather than eating the width */
@media (max-width:720px), (pointer:coarse){
  .sf-prow{ flex-direction:column; gap:4px; }
  .sf-prow .pl{ flex:0 0 auto; padding-top:0; }
}

/* --- the addendum: a multi-file item, answered here --------------------- */
/* `stage_for_ingest` answered `{status:"choose", files:[…]}` — IA's own file
   list. It is the queue's own row shape, because it is the same kind of thing:
   a short list of names you press one of. */
.sf-choose{ display:block; border-bottom:1px solid var(--sf-rule); padding-bottom:6px; }
.sf-choose .sf-q .qn{ font-variant-numeric:tabular-nums; }


/* ==========================================================================
   8 SEPTEMBER, §5.8 — WHAT A RESULT IS, WHEN IT IS NOT A BOOK YET
   Clicking a fetchable result or a recording cannot fill the step grid: there
   are no steps, because there is no book. So THE WORKS answers the question
   the click asked — what IS this — out of the candidate's own fields, and
   puts the verbs that can act on it in the same place.
   ========================================================================== */
.sf-cand{ display:block; border-bottom:1px solid var(--sf-rule); padding-bottom:8px; }
.sf-cand .ct{ font:600 13px/1.35 var(--sf-ui); color:var(--sf-ink); padding:2px 0 6px; }
.sf-fields{ display:grid; grid-template-columns:auto 1fr; gap:3px 10px;
  font:10.5px/1.4 var(--sf-ui); }
.sf-fields .k{ color:var(--sf-dim); white-space:nowrap; }
.sf-fields .v{ color:var(--sf-ink); min-width:0; overflow-wrap:anywhere; }
.sf-url{ display:block; padding:7px 0 0; font:10px/1.4 ui-monospace, SFMono-Regular,
  Menlo, monospace; color:var(--sf-dim); overflow-wrap:anywhere; }


/* ==========================================================================
   14 SEPTEMBER, SURFACE STAGE 1 — EVERY RENDER, ALL BOOKS
   `studio.html::panelQueue` was a modal over the host's own front page. It is
   a band at the top of THE WORKS now: the machine, above the book, shut until
   it is asked for. Its head borrows `.sf-workhead`'s layout for the reason
   the two are the same kind of thing — a list title with the controls that
   belong to the LIST rather than to any row in it.
   ========================================================================== */
.sf-all{ display:block; border-bottom:1px solid var(--sf-rule); padding-bottom:6px; }
.sf-h.sf-allhead{ display:flex; align-items:baseline; gap:8px; }
.sf-h.sf-allhead .wl{ flex:1 1 auto; }
.sf-h.sf-allhead .sf-verb{ flex:0 0 auto; }
/* A GROUP IS NOT A BOOK ON A SHELF, and the row says so by weight rather
   than by a badge — the spine rule this surface keeps (told apart by the
   spine, never by a badge and never by being in two different lanes). */
.sf-row.r-all .t{ font-weight:500; }
.sf-row.r-all .s{ font-variant-numeric:tabular-nums; }
/* the three states a person scans for: out now, finished, and gone wrong */
.sf-row.r-all.rfailed .spine, .sf-row.r-all.rstopped .spine{ opacity:.55; }
.sf-row.r-all.rvoiced .spine, .sf-row.r-all.rpulled .spine{ opacity:.75; }
.sf-row.r-all.rheld .spine{ opacity:.45; }
/* A CHAPTER WITH AUDIO AND NO WORD TIMINGS. It is a fact, not a failure, so
   it is said in the row's own voice rather than in the red one -- and the
   ribbon's align cell says the same, or the row would give two answers. */
.sf-gr .sf-notime{ flex:0 0 auto; color:#a8532a; font-style:normal; }

/* ==========================================================================
   14 SEPTEMBER — ON THE DRIVE, THE THIRD STATE A ROW CAN BE IN
   `studio.html::panelSources` was a modal list of buttons. A file in
   TTS_DATA/sources/ is neither yours (no book) nor out there (nothing to
   fetch): it is here, and one press parses it in place. It is told apart the
   way every other row is — by the spine, never by a badge.
   ========================================================================== */
.sf-row.r-drive .spine{ opacity:.6; }
.sf-row.r-drive .t{ font-weight:500; }
.sf-row.r-drive .sf-prov{ font:10px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; }


/* ==========================================================================
   G-DROPDOWN (16 Sep) — THE COLUMN IS HEADED BY THE BOOK; THE PICKERS ARE
   DROPDOWNS. Osca: "drop-downs in the selectors ... let me scroll through
   them, if large ... Select in the bottom right, then when selected, just
   show those on the studio side." One primitive (`dropdown()` in surface.js)
   draws Voice, Language, Where and Model: a shut FACE naming the choice, a
   list that scrolls at nine rows, radio or checkbox rows, Select bottom
   right. A greyed row is the dashed pill's rule kept: present, plainly not a
   choice, carrying its reason.
   ========================================================================== */
/* the head: the selected book's title, the author under it in its hue */
.sf-h.sf-subj{
  text-transform:none; letter-spacing:-.02em;
  font:600 15px/1.25 var(--sf-serif); color:var(--sf-ink);
  padding:6px 0 0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.sf-subja{ display:block; padding:2px 0 8px; font:10.5px/1.3 var(--sf-ui);
  color:var(--sf-dim); border-bottom:1px solid var(--sf-rule); }
.sf-h.sf-subj + .sf-note{ padding-top:6px; }

.sf-ddrow{ display:flex; align-items:center; gap:6px; min-width:0; }
.sf-ddrow .sf-dd{ flex:1 1 auto; min-width:0; }
/* the reference's play/pause, BESIDE the face, for the chosen voice only */
.sf-pp{ flex:0 0 auto; font:11px/1 var(--sf-ui); color:var(--sf-ink);
  background:transparent; border:1px solid var(--sf-rule); border-radius:999px;
  width:22px; height:22px; cursor:pointer; padding:0; }
.sf-pp:hover{ border-color:var(--sf-ink); }

.sf-dd{ position:relative; display:block; min-width:0; }
.sf-ddface{
  display:flex; align-items:center; gap:8px; width:100%; min-width:0;
  font:11px/1.25 var(--sf-ui); color:var(--sf-ink); text-align:left;
  background:transparent; border:1px solid var(--sf-rule); border-radius:8px;
  padding:5px 9px; cursor:pointer;
}
.sf-ddface:hover{ border-color:var(--sf-ink); }
.sf-ddface[aria-expanded="true"]{ border-color:var(--sf-ink); }
.sf-ddface[disabled]{ opacity:.55; cursor:default; }
.sf-ddface .fx{ flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* `sf-cx`, not `cx`: cast.css's `.cx` is a fixed, centred glass panel (z 71), and a chevron named `cx` wore it over the sheet -- the cream bar, 9 Oct */
.sf-ddface .sf-cx{ flex:0 0 auto; font-size:9px; color:var(--sf-dim); }

/* the open list: over the column, not in its flow, so the rows below do not
   jump when it opens; nine rows tall then it scrolls */
.sf-ddpop{
  position:absolute; left:0; right:0; top:calc(100% + 3px); z-index:5;
  background:var(--sf-sheet, var(--sf-ground)); border:1px solid var(--sf-rule);
  border-radius:8px; box-shadow:0 8px 24px rgba(0,0,0,.14);
  overflow:hidden;
}
.sf-ddpop[hidden]{ display:none; }
.sf-ddlist{ display:block; max-height:234px; overflow:auto; overscroll-behavior:contain;
  padding:3px 0; outline:none; }
.sf-opt{
  display:flex; align-items:baseline; gap:8px; width:100%; min-width:0;
  font:11px/1.3 var(--sf-ui); color:var(--sf-ink); text-align:left;
  background:transparent; border:0; padding:5px 9px; cursor:pointer;
}
.sf-opt:hover, .sf-opt.focus{ background:hsl(var(--sf-ground-hsl) / .5); box-shadow:inset 3px 0 0 var(--sf-rule); }
.sf-opt.focus{ box-shadow:inset 3px 0 0 var(--sf-ink); }
.sf-opt .tk{ flex:0 0 12px; font-style:normal; font-size:10px; color:var(--sf-dim); }
.sf-opt[aria-selected="true"] .tk{ color:var(--sf-ink); }
.sf-opt[aria-selected="true"] .tx{ font-weight:600; }
.sf-opt .tx{ flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.sf-opt .sx{ flex:0 0 auto; font-size:10px; color:var(--sf-dim); font-variant-numeric:tabular-nums; }
.sf-opt[disabled]{ opacity:.45; cursor:default; }
/* G-RUN: an action row (All / None) -- it rewrites the ticks, it is not one */
.sf-opt.act{ padding-left:29px; color:var(--sf-dim); text-transform:uppercase;
  font-size:9.5px; letter-spacing:.08em; }
.sf-opt.act:hover, .sf-opt.act.focus{ color:var(--sf-ink); }
/* the greyed row: not a choice, and it says why in its title */
.sf-opt.off{ color:var(--sf-dim); cursor:default; white-space:normal; padding-left:29px; }
.sf-ddfoot{ display:flex; align-items:center; justify-content:flex-end; gap:8px;
  padding:5px 7px; border-top:1px solid var(--sf-rule); }
.sf-ddfoot .hx{ flex:1 1 auto; font:9.5px/1.3 var(--sf-ui); color:var(--sf-dim); }
.sf-ddfoot .sf-ddsel{ flex:0 0 auto; }

/* the model's cost note: shut to its first line, "more ▸" opens it in place */
.sf-limits{ position:relative; }
.sf-limits.shut span:nth-of-type(n+2){ display:none; }
.sf-more{ display:inline-block; margin-top:2px; padding:0; border:0; background:transparent;
  font:10px/1.5 var(--sf-ui); color:var(--sf-dim); cursor:pointer; text-decoration:underline dotted; }
.sf-more:hover{ color:var(--sf-ink); }

/* the phone: the same dropdown, full width, the list in the flow so a thumb
   can scroll it without the sheet scrolling underneath */
@media (max-width:720px), (pointer:coarse){
  .sf-ddpop{ position:static; box-shadow:none; margin-top:4px; }
  .sf-ddlist{ max-height:min(234px, 40vh); }
  .sf-opt{ padding:8px 10px; font-size:12px; }
  .sf-ddface{ padding:8px 10px; font-size:12px; }
}
/* ===================================================== G-SET: chips + verb row */
.sf-chips{ display:flex; flex-wrap:wrap; gap:6px; padding:4px 0 8px; }
.sf-chips .sf-chip{ display:inline-flex; align-items:center; gap:4px;
  padding:3px 8px; border-radius:4px; font-size:12px; cursor:default;
  background:color-mix(in srgb, var(--hue, #888) 18%, transparent);
  border:1px solid color-mix(in srgb, var(--hue, #888) 30%, transparent); }
.sf-chipx{ all:unset; cursor:pointer; font-size:14px; line-height:1; opacity:.6;
  padding:0 2px; }
.sf-chipx:hover{ opacity:1; }
.sf-setverbs{ padding:8px 0; display:flex; flex-wrap:wrap; gap:6px; }

/* ============================================================ SOURCE-DOOR
   (D9, 26 Sep) the origin half of a provenance line is a BUTTON when there is
   an origin: same type, same colour, underlined on hover so it reads as the
   door it is. The band above the list is the one row the door opens on. */
.sf-prov .po.sf-door{ background:none; border:0; padding:0; margin:0; font:inherit;
  color:inherit; cursor:pointer; text-align:left; text-decoration:underline dotted; }
.sf-prov .po.sf-door:hover{ color:var(--sf-ink); text-decoration:underline; }
.sf-doorband{ margin:0 0 6px; padding:0 0 6px; border-bottom:1px solid var(--sf-rule); }
.sf-doorband .sf-row.r-door{ border-left:2px solid var(--sf-ink); }
.sf-provpane .sf-fate{ padding-top:6px; font-size:11px; line-height:1.4; color:var(--sf-dim); }

/* ============================================================ SURFACE-ONE
   (28 Sep) Osca: search everything first, KINDS after; one field; the book
   first; keep the two panes. */

/* (1) the kind pills -- drawn only once there are results, above them, "All"
   first and chosen; glyphs, the word is the aria-label. Sticky at the top of
   the list's own scroller so a pill is always one press away. */
.sf-kinds{ position:sticky; top:-6px; z-index:3; display:flex; flex-wrap:wrap; gap:6px;
  margin:0 calc(-1 * var(--sf-pad)); padding:8px var(--sf-pad) 8px;
  background:var(--sf-sheet); border-bottom:1px solid var(--sf-rule); }
.sf-kind{ display:inline-flex; align-items:center; gap:5px; height:26px; padding:0 10px;
  border:1px solid var(--sf-rule); border-radius:13px; background:transparent;
  color:var(--sf-dim); font:500 12px/1 var(--sf-ui); cursor:pointer; }
.sf-kind svg{ width:15px; height:15px; display:block; }
.sf-kind b{ font-weight:600; }
.sf-kind i{ font-style:normal; font-variant-numeric:tabular-nums; opacity:.8; }
.sf-kind:hover{ color:var(--sf-ink); border-color:color-mix(in srgb, var(--sf-ink) 35%, transparent); }
.sf-kind.on{ background:var(--sf-ink); border-color:var(--sf-ink); color:var(--sf-ground); }
.sf-kind.on i{ opacity:1; }
.sf-list > [hidden], .sf-list .sf-part > [hidden]{ display:none !important; }

/* (4) a passage found in the open book: the words around it, the match marked */
.sf-row.sf-pass .t{ white-space:normal; font-weight:400; }
.sf-row.sf-pass .t mark{ background:color-mix(in srgb, var(--sf-ink) 16%, transparent);
  color:inherit; border-radius:2px; padding:0 1px; font-weight:600; }

/* (2)(5) THE PHONE. One field on screen: the sheet's field IS the pill -- it
   sits where the foot bar's pill sits, at the foot, rounded like it, and the
   sheet covers the bar so there is never a second one. Before a selection the
   list is the whole sheet; once a book or a thing is selected the list is the
   top half and the selected thing the bottom half, two scrollers. */
@media (max-width:720px), (pointer:coarse){
  .sf-field{ order:3; height:auto; border-bottom:0; border-top:1px solid var(--sf-rule);
    padding:8px 12px calc(8px + env(safe-area-inset-bottom, 0px)); gap:8px; }
  .sf-field input{ height:40px; padding:0 14px; border-radius:20px; text-align:center;
    background:color-mix(in srgb, var(--sf-ink) 7%, transparent); font-size:17px; }
  .sf-field input:focus{ text-align:left; }
  .sf-field .sf-look{ display:none; }
  .sf-cols{ order:1; flex:1 1 auto; min-height:0; }
  .sf-list{ order:1; flex:1 1 0; min-height:0; overflow-y:auto; }
  .sf-works{ order:2; flex:0 0 0; max-height:none; display:none;
             border-bottom:0; border-top:1px solid var(--sf-rule); }
  .sf.sf-hassel .sf-works, .sf.sf-hassel .sf-works.empty{ display:block; flex:1 1 0; min-height:0; overflow-y:auto; }
  .sf.sf-hassel .sf-list{ flex:1 1 0; }
}

/* ===== BOOK-PANE (EXPORT, 28 Sep): the right column is the book's page ===== */
.sf-h.sf-subj{ font-size:20px; white-space:normal; padding-top:10px; }
.sf-subja{ font:italic 13px/1.3 var(--sf-serif); border-bottom:0; padding-bottom:10px; }
.sf-bookpane{ padding:0 0 14px; border-bottom:1px solid var(--sf-rule); }
.sf-bfacts{ font:600 9.5px/1.4 var(--sf-ui); letter-spacing:.12em; text-transform:uppercase; color:var(--sf-dim); }
.sf-bookpane .sf-open{ margin:12px 0 4px; font-size:10px; padding:.8em 1.6em; }
.sf-bhead{ padding:16px 0 6px; font:600 var(--sf-head)/1 var(--sf-ui); letter-spacing:.14em; text-transform:uppercase; color:var(--sf-dim); }
.sf-btoc{ display:flex; flex-direction:column; }
.sf-bch{ text-align:left; background:none; border:0; border-top:1px solid var(--sf-rule); padding:7px 0;
  font:13px/1.35 var(--sf-serif); color:var(--sf-ink); cursor:pointer; }
.sf-bch:hover{ color:var(--sf-ink); background:rgba(127,127,127,.08); }
.sf-studiofold{ margin-top:10px; }
.sf-studiosum{ cursor:pointer; list-style:none; padding:12px 0 6px; font:600 var(--sf-head)/1 var(--sf-ui);
  letter-spacing:.14em; text-transform:uppercase; color:var(--sf-dim); }
.sf-studiosum::-webkit-details-marker{ display:none; }
.sf-studiosum::after{ content:" \203A"; }
.sf-studiofold[open] > .sf-studiosum::after{ content:" \2304"; }

/* THE SHEET IN THE LIBRARY'S GLASS (DESIGN, 29 Sep; Osca: "ALL doors ... the same app"). It was already a blurred
   sheet with the book serif in its rows and the shelf's capitals in its headings; what differed from the Library's
   objects: the corner (14 -> 16, the first-run card's), the hairline (the rule colour -> ink at 12 %, as every
   glass piece has), and the ESC key (a 5 px box -> a capsule, like the band's ⌘K). */
.sf{ border-radius:16px; border-color:color-mix(in srgb, var(--sf-ink) 12%, transparent); }
.sf-esc{ border-radius:999px; padding:5px 9px; border-color:color-mix(in srgb, var(--sf-ink) 12%, transparent); }
/* ON THE PHONE THE PILL IS THE FIELD (Osca, 28 Sep; the all-doors Stranger, 29 Sep: the sheet's own "Search
   everything" field sat at y 795-852, wholly under the band's pill, a word peeking out). The sheet draws no field of
   its own on the phone -- what is typed goes in the pill (band.js PHONE-PASS) -- and its list ends above the band. */
html[data-phone] .sf-field{ display:none; }
html[data-phone] .sf{ padding-bottom:calc(var(--band-foot, var(--pbar-h, 56px)) + 12px); }
/* the phone on its side: the sheet's rows keep clear of the island's side and the other side (29 Sep) */
@media (orientation: landscape){
  html[data-phone] .sf{ padding-left: var(--safe-left, env(safe-area-inset-left, 0px)); padding-right: var(--safe-right, env(safe-area-inset-right, 0px)); }
}
html[data-phone] .sf{ padding-top: var(--safe-top, env(safe-area-inset-top, 0px)); }
@media (orientation: landscape){
  html[data-phone] .sf{ left: var(--safe-left, env(safe-area-inset-left, 0px)); right: var(--safe-right, env(safe-area-inset-right, 0px)); width: auto; padding-left: 0; padding-right: 0; }
}
/* "you typed …" (ASKS #129): the Surface's own small line, in the serif's italic, above the rows */
.sf-corrected{ margin:10px 0 2px; padding:0 var(--sf-pad, 16px); font:italic 13px/1.4 var(--sf-serif, Georgia, serif); color:var(--sf-dim); }
/* THE PHONE IS THE PHONE ON ITS SIDE TOO (ASKS #111; measured in band 852 x 393: the sheet kept the Mac's
   translate(-50%) under the landscape rule's left, so it stood at x -307 and its rows ran under the island). The
   phone's own sheet above answers `(max-width:720px), (pointer:coarse)`; a phone on its side is wider than 720, so
   the same sheet is also keyed on html[data-phone], which every master is given on the phone. */
html[data-phone] .sf{ top:0; max-width:none; height:100%; transform:translate(0, 10px); border-radius:0; border:0; }
html[data-phone] .sf.on{ transform:translate(0, 0); }
html[data-phone] .sf-cols{ flex-direction:column; order:1; flex:1 1 auto; min-height:0; }
html[data-phone] .sf-list{ order:1; flex:1 1 0; min-height:0; overflow-y:auto; }
html[data-phone] .sf-works{ order:2; flex:0 0 0; max-height:none; display:none; border-left:0; border-bottom:0; border-top:1px solid var(--sf-rule); }
html[data-phone] .sf.sf-hassel .sf-works, html[data-phone] .sf.sf-hassel .sf-works.empty{ display:block; flex:1 1 0; min-height:0; overflow-y:auto; }
@media (orientation: portrait){ html[data-phone] .sf{ left:0; width:100%; } }
/* ONE RECIPE FOR THE SMALL CAPITALS (ASKS #105, the Stranger: "three recipes for the small capital label"). Measured in
   band across the Library, book view, Surface, Settings, Tell Frank, Reports, first run: a LABEL is 11 px, 600, .13 em
   (Settings' heads, Tell Frank, Reports, the failure card, the book view's byline); an ACTION is 12 px, 600, .13 em
   (Read, Send, Sign in); the META line under a name in a dense list is --sf-meta, 400, .13 em. The Surface's heads were
   9.5 at .14 and its meta .14 / .12: they take the two recipes. The ESC keycap is a key, not a label. */
.sf{ --sf-head:11px; }
.sf-h{ letter-spacing:.13em; }
.sf-row .s, .sf-row .end{ letter-spacing:.13em; }
.sf-verb{ font-size:11px; letter-spacing:.13em; }
.sf-bfacts{ font-size:11px; letter-spacing:.13em; }   /* the Surface's book facts line, the same LABEL */
/* the TELL FRANK line on a broken search (ASKS #136; surface.js brokeLine): the failure card's own words, in the LABEL recipe */
.sf-note .sf-tell{ -webkit-appearance:none; appearance:none; background:none; border:0; padding:0 0 0 4px; cursor:pointer;
  font:600 11px/1.4 var(--sf-ui); letter-spacing:.13em; text-transform:uppercase; color:var(--sf-ink); }

/* THE FIELD RISES WHERE YOU PRESSED (ASKS #158; PHOTOS rule 3; the Stranger, 30 Sep: "the Search pill opens a sheet
   with no field -- the input 0 x 0 in a hidden .sf-field -- so nothing can be typed"). The PHONE-PASS pill field lived
   only on the canvas's sketch; the real sheet drew none, and every page's centre was a dead end. Now, as Settings'
   find does (settings-look.css): on the phone the sheet's own field IS the pill -- the same capsule, in the same place
   (the band's row: --pad from the edges, --gap over the home indicator's half, --band-float tall, a phone's width on
   its side), the caret in it the moment the pill is pressed, the hits above it -- and the band steps aside while the
   sheet is up, so there is one field on screen and the pill is not drawn twice. The × stands where the mic stood: a
   press is close, as Esc is. */
html[data-phone] .sf-field{
  display:flex; position:absolute; z-index:2; order:3;
  bottom:calc(var(--gap, 8px) + var(--safe-bottom, env(safe-area-inset-bottom, 0px)) / 2);
  left:50%; transform:translateX(-50%);
  width:calc(min(560px, 100% - 2 * var(--pad, 12px)) - var(--band-float, 48px) - var(--gap, 8px));
  margin-left:calc((0px - var(--band-float, 48px) - var(--gap, 8px)) / 2);
  height:var(--band-float, 48px); box-sizing:border-box;
  padding:0 var(--pad, 12px); gap:calc(var(--gap, 8px) - 2px);
  border:1px solid color-mix(in srgb, var(--sf-ink) 12%, transparent); border-radius:calc(var(--band-float, 48px) / 2);
  background:color-mix(in srgb, var(--sf-ground, var(--sf-sheet)) 58%, transparent);
  -webkit-backdrop-filter:saturate(1.8) blur(18px); backdrop-filter:saturate(1.8) blur(18px);
  box-shadow:0 4px 18px rgba(0, 0, 0, .14);
}
html[data-phone] .sf-field .sf-look{ display:block; width:16px; height:16px; color:var(--sf-dim); transform:translateY(2px); }
html[data-phone] .sf-field .sf-look svg{ width:16px; height:16px; stroke-width:1.25; }
html[data-phone] .sf-field input{
  height:100%; padding:0; border:0; border-radius:0; background:transparent; text-align:left;
  font:400 17px/1.2 var(--sf-ui); letter-spacing:0; caret-color:var(--sf-accent, currentColor);
  -webkit-appearance:none; appearance:none;
}
html[data-phone] .sf-field .sf-esc{
  position:absolute; top:-1px; right:calc(-1px - var(--band-float, 48px) - var(--gap, 8px));
  width:var(--band-float, 48px); height:var(--band-float, 48px); padding:0; display:grid; place-items:center;
  border:1px solid color-mix(in srgb, var(--sf-ink) 12%, transparent); border-radius:50%;
  background:color-mix(in srgb, var(--sf-ground, var(--sf-sheet)) 58%, transparent);
  -webkit-backdrop-filter:saturate(1.8) blur(18px); backdrop-filter:saturate(1.8) blur(18px);
  box-shadow:0 4px 18px rgba(0, 0, 0, .14); color:var(--sf-ink); -webkit-tap-highlight-color:transparent;
}
.sf-esc svg{ display:none; }
html[data-phone] .sf-esc span{ display:none; }
html[data-phone] .sf-esc svg{ display:block; width:16px; height:16px; fill:none; stroke:currentColor; stroke-width:1.25; stroke-linecap:round; }
/* the band steps aside while the sheet is up: band.css (html[data-phone][data-sheet] .band) */

/* A RECORDING'S ROW ON THE PHONE (Z9 · Z13, DESIGN #197, 1 Oct): its three verbs took the whole width and the title
   stood one letter wide ("W / 18 / PARTS / 12 / H"). On the phone the verbs go under the title, the row's full width. */
html[data-phone] .sf-row.sf-hit{ flex-wrap:wrap; }
html[data-phone] .sf-row.sf-hit .body{ flex:1 1 calc(100% - 40px); }
html[data-phone] .sf-row.sf-hit .end{ flex:1 1 100%; flex-wrap:wrap; }
/* the voice cards in the pane: Share this voice under the Voice row (voicepage.css draws the block) */
.sf-share{ display:block; margin-top:6px; }

/* ===== SIMPLER STUDIO COLUMN + TWO SCROLLS ON THE LEFT (Osca, 9 Oct 01:03) =====
   The left column holds two parts when there is both: what is YOURS (the shelf, this book, the work) on top and what
   is OUT THERE (every source, the Elsewhere lanes) under it, each with its own scroll. One part alone fills it. */
.sf-list.sf-split2{ display:flex; flex-direction:column; overflow:hidden; padding-bottom:0; }
.sf-list.sf-split2 > .sf-part{ flex:1 1 0; min-height:0; overflow-y:auto; overscroll-behavior:contain; }
.sf-list.sf-split2 > .sf-out{ border-top:1px solid var(--sf-rule); padding-bottom:var(--sf-pad); }
/* the book's two presses side by side: Open, and Pair with another book */
.sf-bacts{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin:12px 0 4px; }
.sf-bacts .sf-open{ margin:0; }
.sf-pairbtn{ font-size:10px; padding:.8em 1.4em; }
/* the settings and each chapter's steps: one quiet line, opened when wanted */
.sf-moreset, .sf-each{ margin:10px 0 0; border-top:1px solid var(--sf-rule); }
.sf-moresum{ cursor:pointer; list-style:none; padding:10px 0 6px;
  font:600 9.5px/1.4 var(--sf-ui); letter-spacing:.12em; text-transform:uppercase; color:var(--sf-dim); }
.sf-moresum::-webkit-details-marker{ display:none; }
.sf-moresum::after{ content:" \25B8"; }
details[open] > .sf-moresum::after{ content:" \25BE"; }
.sf-moresum:hover{ color:var(--sf-ink); }
@media (max-width:720px), (pointer:coarse){
  .sf-list.sf-split2{ overflow:hidden; }
}
.sf-each > .sf-provpane > .sf-h:first-child{ display:none; }   /* the summary already says it */
.sf-workfold{ margin:6px 0 0; border-top:1px solid var(--sf-rule); }
.sf-workfold > .sf-workhead .wl{ display:none; }   /* the summary says it once */
/* yours takes what it needs (up to most of the column) and scrolls past that; out there takes the rest */
.sf-list.sf-split2 > .sf-mine{ flex:0 1 auto; max-height:60%; }
html[data-phone] .sf-list.sf-split2 > .sf-mine{ flex:0 1 auto; max-height:60%; }
.sf-list.sf-split2 > .sf-out{ flex:1 1 0; }

/* ==========================================================================
   SURFACE, 10 Oct (ASKS #242-#247) -- THE LIST HOLDS STILL, AND EVERY JOB HAS A STOP.
   A result row is ONE height, whatever it holds: its title, one line of what a person decides by, its verbs at the
   right, all of them visible. Measured before (test-surface-hold.mjs): six heights from 65 to 181 px on one list,
   and "Sample" printed half under ADD on hover. The strip over Elsewhere is one height asking and answered. */
:root{ --sf-rowfix:54px; }
@media (max-width:700px){ :root{ --sf-rowfix:60px; } }
.sf-row.sf-fixed{
  height:var(--sf-rowfix); min-height:0; box-sizing:border-box;
  padding-top:0; padding-bottom:0; padding-right:2px; flex-wrap:nowrap; align-items:center; overflow:hidden;
}
.sf-row.sf-fixed .body{ flex:1 1 auto; min-width:0; }
.sf-row.sf-fixed > .end,
.sf-row.sf-fixed:has(> .end > :nth-child(3)) > .end{
  flex:0 0 auto; flex-wrap:nowrap; max-width:62%; padding-top:0;
}
.sf-row.sf-fixed .s{ margin-top:.4em; }
.sf-row .s > .sf-fact{ flex:0 0 auto; opacity:.85; }
.sf-row .s > .sf-fact.sf-borrow{ color:#a8532a; opacity:1; }
.sf-row .s > .sf-fact.sf-others{ opacity:.7; }
.sf-row .s > .sf-jobline{ color:var(--sf-ink); text-transform:none; letter-spacing:0;
  font:11px/1.3 var(--sf-ui); }
.sf-row .s > .sf-jobline .sf-left{ font-variant-numeric:tabular-nums; }
/* a title is not a web link: no underline under the pointer (POLISH 1) */
.sf-row.r-out:hover .t{ text-decoration:none; }
/* the verb that names a book truncates inside itself; its whole name is its title */
.sf-verb.sf-attach{ max-width:220px; overflow:hidden; text-overflow:ellipsis; }
/* the row that is asking what it will cost, and the row that is working, are marked by their wash, not by moving */
.sf-row.sf-askcost{ background:color-mix(in srgb, var(--sf-ink) 6%, transparent); }
.sf-row.sf-attaching .spine{ height:calc(100% - 18px); background:var(--sf-ink); opacity:.55; }

/* the strip: head one line, chips one row that scrolls sideways (no OS scrollbar), the progress a hairline */
.sf-src{ position:relative; flex-direction:column; flex-wrap:nowrap; align-items:stretch; gap:6px;
         height:58px; box-sizing:border-box; padding:8px 0 8px; overflow:hidden; }
.sf-srchead{ flex:0 0 auto; white-space:nowrap; overflow:hidden; }
.sf-srchead .hl{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; overflow-wrap:normal; }
.sf-src.asking .sf-srchead{ font:600 11px/1.4 var(--sf-ui); }
.sf-chiprow{ display:flex; flex-wrap:nowrap; gap:5px; overflow-x:auto; overflow-y:hidden;
             scrollbar-width:none; -webkit-mask-image:linear-gradient(to right, #000 92%, transparent); }
.sf-chiprow::-webkit-scrollbar{ display:none; }
.sf-chiprow .sf-chip{ flex:0 0 auto; white-space:nowrap; }
.sf-src .sf-srcbar{ position:absolute; left:0; right:0; bottom:-1px; margin:0; height:2px; }
.sf-srchead .hl.sf-filterline{ color:var(--sf-ink); }

/* a job beside its button: what it is doing, the time, Stop */
.sf-jobrow, .sf-runrow{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.sf-jobline{ font:12px/1.45 var(--sf-ui); color:var(--sf-ink); }
.sf-elapsed{ font-variant-numeric:tabular-nums; }
.sf-works .sf-askcost{ display:flex; flex-direction:column; gap:8px; margin:8px 0 4px; padding:10px 12px;
             border-radius:8px; background:color-mix(in srgb, var(--sf-ink) 5%, transparent); }
.sf-works .sf-askcost .sf-acts{ display:flex; gap:8px; }

/* the right column's other editions of the row pressed */
.sf-alt{ display:flex; align-items:center; gap:10px; padding:5px 0; border-bottom:1px solid var(--sf-rule); }
.sf-alt-t{ flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
           font:12px/1.4 var(--sf-ui); color:var(--sf-ink); }

.sf-runrow > .sf-askcost{ flex:1 1 100%; }

/* the run's slot keeps its height after its question is answered, so the pointer does not land on Settings */
.sf-runrow.sf-held{ align-content:flex-start; align-items:flex-start; }
/* the sample's states are one height: idle, making, stopped (the second Stranger: Stop threw Read aloud up 59 px) */
.sf-sample{ position:relative; min-height:64px; }
.sf-sample > .sf-bar{ position:absolute; left:0; right:0; top:-7px; margin:0; }
.sf-sample .sf-jobrow{ flex-wrap:nowrap; min-height:28px; }
.sf-sample .sf-sub, .sf-sample .sf-jobrow + span{ display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; min-height:2.9em; }
/* verbs on result rows line up across rows */
.sf-row.sf-fixed .end .sf-verb{ min-width:74px; text-align:center; box-sizing:border-box; }
/* a chip keeps its width from asking to answered, so the row of chips does not slide */
.sf-chiprow .sf-chip{ min-width:8.6em; justify-content:space-between; box-sizing:border-box; }
.sf-sample .sf-jobrow{ align-items:flex-start; }
.sf-sample > .sf-bar, .sf-sample > .sf-bar.indeterminate{ position:absolute; left:0; right:0; top:-7px; margin:0; }
.sf-sample .sf-sub{ height:2.9em; min-height:0; }
/* the whole-book question sits in the button's own place: no inset, so Read it aloud is where the press was */
.sf-runrow > .sf-askcost{ margin:0; padding:0; background:none; border-radius:0; }
.sf-runrow > .sf-askcost .sf-jobline{ font-size:11.5px; color:var(--sf-dim); }
.sf-sample .sf-jobrow{ height:30px; min-height:0; }
.sf-sample .sf-jobrow .sf-jobline{ flex:1 1 auto; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; align-self:center; }

/* the reserved slots for readings: three rows tall from the moment a reading is asked for */
.sf-recslots{ min-height:calc(3 * var(--sf-rowfix)); border-bottom:1px solid var(--sf-rule); }
.sf-recslots > .sf-note{ display:block; padding:16px 0 0 var(--sf-gutter); }

/* every verb on a result row is one height, outlined or filled */
.sf-row.sf-fixed .end .sf-verb{ height:26px; padding-top:0; padding-bottom:0; line-height:26px; }
/* THE KEYBOARD IS UP (C · SEARCH, 11 Oct; P2, 14 Oct; surface.js fitKeyboard): the sheet runs on to the screen's foot
   UNDER the keyboard (no Library showing between the pill and the keys, as Safari), and the field rides on the keys:
   its bottom is the keyboard's height (--sf-kb) and a gap -- no home indicator under it to clear. The list's foot clears
   the keyboard and the pill the same way. */
html[data-phone] .sf[data-kb] .sf-field{ bottom:calc(var(--sf-kb, 0px) + var(--gap, 8px)); }
html[data-phone] .sf[data-kb]{ padding-bottom:calc(var(--sf-kb, 0px) + var(--gap, 8px) + var(--band-float, 48px) + 12px); }

/* ======================================================================
   THE APPROVED SURFACE, STAGE 1 -- THE LEFT SIDE (Osca, 11 Oct 12:52; design/surface-drafts/SURFACE-DRAFT-11-oct-APPROVED.html).
   A row surface-skin.js has dressed (.sk): one grid -- picture 40 · title and one line · a fixed column of icon buttons --
   so the buttons sit in the same place on every row. Sentence case, no spaced capitals; least text. */
.sf .sf-row.sk{
  display:grid; grid-template-columns:40px minmax(0, 1fr) auto; align-items:center; column-gap:12px;
  min-height:64px; padding:6px 8px 6px 6px; border-bottom:0; border-radius:8px; flex-wrap:nowrap;
}
.sf .sf-row.sk > .spine{ display:none; }
.sf .sf-row.sk > .body{ min-width:0; }
.sf .sf-row.sk .t{ font:400 15px/1.25 var(--sf-ui); letter-spacing:0; }
.sf .sf-row.sk .s{ display:block; margin-top:2px; font:400 13px/1.35 var(--sf-ui); letter-spacing:0; text-transform:none;
  color:var(--sf-dim); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.sf .sf-row.sk .sf-prov, .sf .sf-row.sk .sk-hide{ display:none; }
.sf .sf-row.sk > .end{ display:flex; flex-wrap:nowrap; justify-content:flex-end; align-items:center; gap:4px; padding:0;
  min-width:68px; font:400 12px/1 var(--sf-ui); letter-spacing:0; text-transform:none; }
.sk-pic{ width:40px; height:56px; border-radius:3px; overflow:hidden; display:grid; place-items:center; flex:none;
  box-shadow:0 1px 3px rgba(0,0,0,.18); color:rgba(255,255,255,.9); font:400 22px/1 var(--sf-serif); background:var(--sf-rule); }
.sk-pic img{ width:100%; height:100%; object-fit:cover; display:block; }
.sk-pic.sk-round{ width:40px; height:40px; border-radius:50%; box-shadow:none; font:600 14px/1 var(--sf-ui); }
.sf .sk-ic{ width:32px; height:32px; padding:0; border:0; border-radius:50%; background:transparent; color:var(--sf-dim);
  display:grid; place-items:center; cursor:pointer; box-shadow:none; }
.sf .sk-ic:hover{ background:rgba(127,127,127,.12); color:var(--sf-ink); }
.sf .sk-ic svg{ width:20px; height:20px; fill:none; stroke:currentColor; stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round; }
.sf .sk-ic.sk-busy svg{ animation:sk-spin 1s linear infinite; }
.sf .sk-ic[disabled]{ opacity:.6; cursor:default; }
@keyframes sk-spin{ to{ transform:rotate(360deg); } }
.sf .sf-row.sk > .end{ width:auto; max-width:none; flex:none; }
.sf .sf-row.sk .sk-ic{ min-width:0; width:32px; flex:none; margin:0; }   /* .sf-verb's 74px floor spread the two icons apart */
.sf .sf-row.sk .t{ display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* THE APPROVED CHIP ROW (11 Oct): words on filled pills, one line that never wraps; the chosen one inverted. */
.sf-kinds.sf-chips5{ flex-wrap:nowrap; overflow-x:auto; scrollbar-width:none; gap:8px; padding:4px 0 10px; }
.sf-kinds.sf-chips5::-webkit-scrollbar{ display:none; }
.sf-chips5 .sf-kind{ height:30px; padding:0 14px; border:0; border-radius:15px; background:color-mix(in srgb, var(--sf-ink) 9%, transparent);
  color:var(--sf-ink); font:500 13px/30px var(--sf-ui); letter-spacing:0; text-transform:none; white-space:nowrap; flex:none; }
.sf-chips5 .sf-kind:hover{ background:color-mix(in srgb, var(--sf-ink) 15%, transparent); }
.sf-chips5 .sf-kind.on{ background:var(--sf-ink); color:var(--sf-ground); }

/* a passage on the same grid: the quotation mark stands in the picture's place, faint, in the reading face */
.sf .sf-row.sk.sk-passrow{ border-left:0; padding-left:6px; }
.sf .sf-row.sk.sk-passrow .t{ font:400 15px/1.3 var(--sf-serif); }
.sk-pic.sk-pass{ width:40px; height:40px; background:none; box-shadow:none; color:var(--sf-dim); opacity:.6; font:400 34px/1 var(--sf-serif); padding-top:10px; }
/* the sources strip is Elsewhere's alone (Osca, 11 Oct: one row of chips, "NOT two rows") */
.sf-list:not([data-chip="elsewhere"]) .sf-src .sf-chiprow{ display:none; }
.sf-list:not([data-chip="elsewhere"]) .sf-src{ height:auto; }

/* RECENT SEARCHES: the draft's heading -- the words left, bold; Clear on the right, quiet */
.sf .sk-sh{ display:flex; justify-content:space-between; align-items:baseline; margin:10px 8px 4px 6px; }
.sf .sk-sh b{ font:700 15px/1 var(--sf-ui); color:var(--sf-ink); letter-spacing:0; text-transform:none; }
.sf .sk-clear{ border:0; background:none; padding:4px 0; font:400 12px/1 var(--sf-ui); color:var(--sf-dim); cursor:pointer; letter-spacing:0; text-transform:none; }
.sf .sk-clear:hover{ color:var(--sf-ink); }
.sk-pic.sk-q{ background:color-mix(in srgb, var(--sf-ink) 9%, transparent); color:var(--sf-dim); }
.sk-pic.sk-q svg{ width:16px; height:16px; fill:none; stroke:currentColor; stroke-width:1.7; stroke-linecap:round; }
.sf .sk-ic.sk-have{ color:var(--sf-ink); cursor:default; }
.sf .sk-ic.sk-have:hover{ background:none; }
.sf .sf-row.sk-recent{ cursor:pointer; }
.sf .sf-row.sk-recent:hover{ background:color-mix(in srgb, var(--sf-ink) 5%, transparent); }

/* ================================================================ THE RIGHT SIDE, A TEXT OF YOURS (approved draft)
   The new face sits over surface.js's column; the old pieces it replaces are hidden, the live ones moved into it. */
.sf-works.sk-side-on > .sf-h.sf-subj, .sf-works.sk-side-on > .sf-subja, .sf-works.sk-side-on > .sf-bookpane,
/* the legacy READ IT ALOUD block is never shown under this face (Osca 14 Oct, #11): its live parts are moved into it */
.sf-works.sk-side-on > .sf-studiofold, .sf-works.sk-side-on > details.sf-each:not(.sk-fold){ display:none; }
.sk-side{ display:grid; gap:14px; padding:4px 2px 8px; font-family:var(--sf-ui); color:var(--sf-ink); }
.sk-who{ display:grid; grid-template-columns:64px minmax(0,1fr); gap:14px; align-items:end; }
.sk-big{ width:64px; height:90px; border-radius:4px; overflow:hidden; box-shadow:0 2px 8px rgba(0,0,0,.22); display:grid; place-items:center;
  color:rgba(255,255,255,.88); font:400 34px/1 var(--sf-serif); }
.sk-big img{ width:100%; height:100%; object-fit:cover; display:block; }
.sk-who h3{ margin:0; font:600 19px/1.15 var(--sf-serif); color:var(--sf-ink); letter-spacing:0; text-transform:none; text-wrap:balance; }
.sk-by{ font:13.5px/1.3 var(--sf-ui); margin-top:3px; }
.sk-meta{ font:12.5px/1.3 var(--sf-ui); color:var(--sf-dim); margin-top:2px; }
.sk-primary{ display:flex; gap:8px; }
.sk-b{ height:36px; padding:0 16px; border-radius:18px; font:600 13.5px/34px var(--sf-ui); white-space:nowrap; letter-spacing:0; text-transform:none;
  border:1px solid var(--sf-rule); background:transparent; color:var(--sf-ink); cursor:pointer; }
.sk-b.sk-dark{ background:var(--sf-ink); color:var(--sf-ground); border-color:var(--sf-ink); }
.sk-b.sk-wide{ flex:1; }
.sk-b.sk-ib{ width:36px; padding:0; display:grid; place-items:center; flex:none; }
.sk-b.sk-ib svg{ width:18px; height:18px; fill:none; stroke:currentColor; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round; }
.sk-sec{ display:grid; gap:8px; padding-top:12px; border-top:1px solid var(--sf-rule); position:relative; }
.sk-sec > b{ font:700 13px/1 var(--sf-ui); display:flex; justify-content:space-between; align-items:center; letter-spacing:0; text-transform:none; }
.sk-sec > b span{ font-weight:400; color:var(--sf-dim); }
.sk-ver{ display:grid; grid-template-columns:30px minmax(0,1fr) auto; gap:10px; align-items:center; font:13.5px/1.2 var(--sf-ui); }
.sk-ver small{ color:var(--sf-dim); font-size:12.5px; }
.sk-pl{ width:30px; height:30px; border-radius:50%; border:0; padding:0; background:color-mix(in srgb, var(--sf-ink) 9%, transparent); color:var(--sf-ink); display:grid; place-items:center; cursor:pointer; }
.sk-pl svg{ width:12px; height:12px; }
.sk-mkrow{ display:flex; flex-wrap:wrap; gap:6px; align-items:center; }
.sk-mkrow > .sf-ddrow{ flex:1; min-width:0; display:flex; gap:6px; align-items:center; }
.sk-mkrow > .sf-ddrow .sf-dd{ flex:1; min-width:0; }
.sk-mkrow .sk-b.sk-ib{ width:34px; height:34px; border-radius:50%; }
.sk-mkrow > .sf-runrow{ display:contents; }
.sk-mkrow .sf-run.sk-make{ height:34px; line-height:34px; padding:0 16px; border-radius:17px; background:var(--sf-ink); color:var(--sf-ground); border-color:var(--sf-ink);
  font:600 13px/34px var(--sf-ui); letter-spacing:0; text-transform:none; min-width:0; }
.sk-mkrow .sf-run.sk-make[disabled]{ opacity:.45; }
.sk-mkrow .sf-jobline{ flex-basis:100%; font:12.5px/1.3 var(--sf-ui); color:var(--sf-dim); letter-spacing:0; text-transform:none; }
.sk-shelves{ display:flex; flex-wrap:wrap; gap:6px; align-items:center; }
.sk-shelf{ display:inline-flex; align-items:center; gap:2px; font:12.5px/1 var(--sf-ui); padding:7px 10px; border-radius:13px; border:0;
  background:color-mix(in srgb, var(--sf-ink) 9%, transparent); color:var(--sf-ink); letter-spacing:0; text-transform:none; }
.sk-shelfx{ width:16px; height:16px; margin:-4px -4px -4px 2px; padding:0; border:0; background:none; color:var(--sf-dim); display:none; place-items:center; cursor:pointer; }
.sk-shelf:hover .sk-shelfx{ display:grid; }
.sk-shelfx svg{ width:12px; height:12px; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; }
.sk-shelfadd{ background:none; border:1px dashed var(--sf-dim); color:var(--sf-dim); cursor:pointer; }
.sk-shelfmenu{ display:grid; gap:2px; padding:6px; border:1px solid var(--sf-rule); border-radius:10px; background:var(--sf-ground); box-shadow:0 6px 20px rgba(0,0,0,.25); }
.sk-shelfopt{ text-align:left; border:0; background:none; padding:7px 8px; border-radius:6px; font:13px/1.2 var(--sf-ui); color:var(--sf-ink); cursor:pointer; letter-spacing:0; text-transform:none; }
.sk-shelfopt:hover{ background:color-mix(in srgb, var(--sf-ink) 8%, transparent); }
.sk-shelfnew{ border:1px solid var(--sf-rule); border-radius:6px; padding:7px 8px; font:13px/1.2 var(--sf-ui); background:transparent; color:var(--sf-ink); }
.sk-act{ display:grid; grid-template-columns:22px minmax(0,1fr) auto; gap:10px; align-items:center; font:13.5px/1.2 var(--sf-ui); padding:2px 0; border:0; background:none;
  color:var(--sf-ink); text-align:left; cursor:pointer; letter-spacing:0; text-transform:none; width:100%; }
.sk-acti svg{ width:18px; height:18px; fill:none; stroke:currentColor; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round; color:var(--sf-dim); display:block; }
.sk-act small{ display:block; color:var(--sf-dim); font-size:12px; margin-top:2px; }
.sk-chev{ color:var(--sf-dim); font-size:16px; }
.sk-foot{ display:grid; padding-top:4px; }
.sk-foot > details.sk-fold{ border-top:1px solid var(--sf-rule); margin:0; padding:0; }
.sk-foot > details.sk-fold > summary{ display:flex; justify-content:space-between; list-style:none; cursor:pointer; padding:9px 0;
  font:13px/1 var(--sf-ui); color:var(--sf-dim); letter-spacing:0; text-transform:none; }
.sk-foot > details.sk-fold > summary::-webkit-details-marker{ display:none; }
.sk-foot > details.sk-fold > summary::after{ content:"\203A"; }
.sk-foot > details.sk-fold[open] > summary::after{ transform:rotate(90deg); }
.sk-mkrow .sf-pp, .sk-side .sk-gone, .sk-side .sf-sample > .sf-sub{ display:none !important; }
.sk-side .sf-sample .sf-jobrow:empty{ display:none; }
.sk-side .sf-sample{ font:12.5px/1.3 var(--sf-ui); color:var(--sf-dim); letter-spacing:0; text-transform:none; }
.sk-side .sf-sample:not(:has(.sf-jobrow > :not(.sk-gone))):not(:has(audio)){ display:none; }

/* THE RIGHT SIDE, A TEXT NOT YET YOURS: everything of surface.js's column but the new face is put away */
/* the side's kind is a CLASS the skin keeps in step (surface-skin.js sideKinds), not a :has(): in Chromium a :has()
   on .sf-works made every DOM change anywhere on the page restyle the whole document -- 572 ms a change on the complete
   Shakespeare (Osca 14 Oct, #4 smoothness). Same specificity, same faces. */
.sf-works.sk-side-on.sk-has-notyours > :not(.sk-side){ display:none; }
.sk-about{ display:grid; gap:12px; }
.sk-owned{ display:flex; align-items:center; gap:6px; font:12.5px/1.3 var(--sf-ui); color:var(--sf-dim); }
.sk-owned svg{ width:15px; height:15px; display:block; color:var(--sf-ink); }
.sk-blurb{ margin:0; font:14px/1.5 var(--sf-serif); color:var(--sf-ink); }
.sk-facts{ display:grid; }
.sk-facts div{ display:grid; grid-template-columns:96px minmax(0,1fr); gap:10px; padding:7px 0; border-top:1px solid var(--sf-rule); font:12.5px/1.35 var(--sf-ui); }
.sk-facts div span:first-child{ color:var(--sf-dim); }
.sk-tags{ display:flex; flex-wrap:wrap; gap:6px; }
.sk-tags span{ font:12px/1 var(--sf-ui); padding:6px 10px; border-radius:12px; background:color-mix(in srgb, var(--sf-ink) 9%, transparent); color:var(--sf-ink); }
.sk-foot > details.sk-candfold > .sf-cand > .sf-h:first-child{ display:none; }

/* THE RIGHT SIDE, AN AUTHOR: the round portrait, then who they were, theirs on your shelf, and the way to the rest */
.sf-works.sk-side-on.sk-has-author > :not(.sk-side){ display:none; }
.sk-big.sk-roundbig{ height:64px; border-radius:50%; box-shadow:none; font:600 20px/1 var(--sf-ui); color:rgba(255,255,255,.92); }
.sk-sh2{ display:flex; justify-content:space-between; align-items:center; margin:4px 0 0; font:700 13px/1 var(--sf-ui); color:var(--sf-ink);
  letter-spacing:0; text-transform:none; }
.sk-sh2 > span{ font-weight:400; color:var(--sf-dim); }
button.sk-sh2{ border:0; background:none; padding:6px 0; width:100%; cursor:pointer; border-top:1px solid var(--sf-rule); padding-top:12px; }
.sk-go{ display:inline-flex; align-items:center; gap:2px; font:600 13px/1 var(--sf-ui) !important; color:var(--sf-ink) !important; }
.sk-go svg{ width:16px; height:16px; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; display:block; }
.sf .sf-row.sk.sk-mini{ min-height:60px; cursor:pointer; padding-left:0; }
.sf .sf-row.sk.sk-lit{ background:color-mix(in srgb, var(--sf-ink) 8%, transparent); }

/* TWO HEADINGS ON THE LEFT: "Yours" and "Elsewhere", the draft's -- bold, sentence case, what is in it on the right */
.sf-part > .sf-h.sk-hush{ display:none; }
.sf-part > .sf-h.sk-parthead{ display:flex; justify-content:space-between; align-items:baseline; margin:12px 8px 4px 6px; padding:0; border:0;
  font:700 15px/1 var(--sf-ui); color:var(--sf-ink); letter-spacing:0; text-transform:none; }
.sf-part > .sf-h.sk-parthead > span{ font:400 12px/1 var(--sf-ui); color:var(--sf-dim); font-variant-numeric:tabular-nums; }
.sf-list:not([data-chip="elsewhere"]) .sf-src:not(.sk-said) .sf-srchead{ display:none; }
.sf-list:not([data-chip="elsewhere"]) .sf-src:not(.sk-said){ padding:0; min-height:0; }

/* SURFACE, 11 Oct (afternoon): the chips start where the pictures do; a reading pressed has its own face; the two ways
   out (YouTube, the web) sit on the same grid as every row */
.sf-kinds.sf-chips5{ padding-left:24px; padding-right:24px; }
.sf-works.sk-side-on.sk-has-reading > :not(.sk-side){ display:none; }
.sf .sf-row.sf-query.sk-qrow{ display:grid; grid-template-columns:40px minmax(0,1fr) 32px; align-items:center; column-gap:12px; min-height:64px; text-decoration:none; }
.sf .sf-row.sf-query.sk-qrow .sk-pic{ width:40px; height:40px; border-radius:50%; display:grid; place-items:center; }
.sf .sf-row.sf-query.sk-qrow .spine{ display:none; }
.sf .sf-row.sf-query.sk-qrow .t{ font:400 15px/1.25 var(--sf-ui); color:var(--sf-ink); }
.sf .sf-row.sf-query.sk-qrow .s{ display:block; font:400 12.5px/1.3 var(--sf-ui); color:var(--sf-dim); }
.sk-ic.sk-open svg, .sk-b.sk-ib svg{ fill:none; stroke:currentColor; stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round; }
.sf-list.sf-split2 > .sf-part > .sf-h.sk-parthead{ position:sticky; top:0; z-index:2; margin:0; padding:12px 8px 6px 6px; background:var(--sf-ground); }
.sf .sf-row.sk-recent.sel{ background:color-mix(in srgb, var(--sf-ink) 8%, transparent); }
.sf .sf-h.sk-libhead{ display:block; margin:10px 8px 4px 6px; font:700 15px/1 var(--sf-ui); color:var(--sf-ink); letter-spacing:0; text-transform:none; }
.sf-part > .sf-h.sk-hush.sk-libhead{ display:none; }
.sf .sf-h.sk-inbook{ display:block; margin:8px 8px 2px 6px; font:500 12px/1.2 var(--sf-ui); color:var(--sf-dim); letter-spacing:0; text-transform:none; }
.sf .sk-hide{ display:none !important; }
.sk-vers{ display:grid; gap:6px; }
.sk-vers:empty{ display:none; }
.sk-ver.sk-on > span{ font-weight:600; }
/* ASKS #278: telling Frank something is wrong is a quiet line at the foot of the card, not a mark on every row */
.sk-foot .sk-tell{ display:block; width:100%; text-align:left; border:0; border-top:1px solid var(--sf-rule); background:none; padding:9px 0;
  font:400 12.5px/1.3 var(--sf-ui); color:var(--sf-dim); letter-spacing:0; text-transform:none; cursor:pointer; }
.sk-foot .sk-tell:hover{ color:var(--sf-ink); }
.sf-row .end > .tf-thumb{ display:none !important; }
/* Stranger 11 Oct: Peek (a text's opening, a reading's sound) shows under the card, not behind it; the voice list is
   wide enough for the names, on its own ground */
.sf-works.sk-side-on > .sf-peekpane{ display:block !important; }
.sf-works.sk-side-on.sk-has-notyours > .sf-peekpane, .sf-works.sk-side-on.sk-has-reading > .sf-peekpane{ display:block !important; }
.sk-mkrow .sf-ddpop{ min-width:220px; background:var(--sf-ground); z-index:20; box-shadow:0 8px 24px rgba(0,0,0,.18); }

/* ===== THE PHONE SURFACE, EDGE TO EDGE (Osca, 11 Oct 18:00-18:22) =====
   "SPACE matters SO much on a phone ... DO NOT eat into the horizontal space with margins INSIDE a thing": every part
   and row runs the phone's full width, set apart by a band of ground between them, never by an inset. Nothing typed:
   RECENT, one row of small covers that scrolls sideways (a cover tapped opens out in place, in that row), then Recent
   searches with the rest of the height, nearest the search bar at the bottom. The chips scroll sideways. */
html[data-phone] .sf-kinds{ margin:0 !important; width:100%; max-width:100%; box-sizing:border-box; padding:6px 12px 8px !important;
  overflow-x:auto; overscroll-behavior-x:contain; touch-action:pan-x; -webkit-overflow-scrolling:touch; }
html[data-phone] .sf-list{ padding-left:0 !important; padding-right:0 !important; }
html[data-phone] .sf .sf-row.sk{ padding-left:12px; padding-right:8px; margin-left:0; margin-right:0; border-radius:0; }
html[data-phone] .sf .sf-part > .sf-h.sk-parthead{ margin:0; padding:12px 12px 4px; }
html[data-phone] .sf-list:has(> .sf-part.sk-cards){ display:flex; flex-direction:column; }
html[data-phone] .sf-part.sk-cards{ flex:1 1 auto; min-height:0; display:flex; flex-direction:column; gap:8px; padding:0; }
html[data-phone] .sk-card{ border-radius:0; padding:0 0 4px; background:color-mix(in srgb, var(--sf-ink) 4%, var(--sf-ground)); }
html[data-phone] .sk-card > .sk-sh{ margin:12px 12px 6px; }
html[data-phone] .sk-card-searches{ flex:1 1 auto; min-height:0; overflow-y:auto; overscroll-behavior:contain; }
html[data-phone] .sf-list.sf-split2{ gap:8px; padding:0; }
html[data-phone] .sf-list.sf-split2 > .sf-part{ border-radius:0; border-top:0; padding:0; background:color-mix(in srgb, var(--sf-ink) 4%, var(--sf-ground)); }
html[data-phone] .sf-list.sf-split2 > .sf-part > .sf-h.sk-parthead{ background:color-mix(in srgb, var(--sf-ink) 4%, var(--sf-ground)); }
/* RECENT: the strip of covers */
.sk-strip{ display:flex; gap:10px; overflow-x:auto; scroll-padding-inline:12px; overscroll-behavior-x:contain; scroll-snap-type:x proximity; padding:2px 12px 10px; scrollbar-width:none; touch-action:pan-x; }
.sk-strip::-webkit-scrollbar{ display:none; }
.sk-cov{ flex:none; width:56px; height:80px; border:0; padding:0; border-radius:3px; overflow:hidden; background:none; cursor:pointer; scroll-snap-align:start;
  box-shadow:0 1px 3px rgba(0,0,0,.18); display:grid; place-items:center; color:rgba(255,255,255,.9); font:400 26px/1 var(--sf-serif); }
.sk-cov img{ width:100%; height:100%; object-fit:cover; display:block; }
/* a cover tapped widens, in place, into the row it would be anywhere else: cover · title · Text · author · EN */
.sk-open1{ flex:none; width:calc(100vw - 24px); max-width:420px; display:grid; grid-template-columns:56px minmax(0,1fr) 28px; column-gap:12px;
  align-items:center; scroll-snap-align:start; border:0; padding:0; background:none; text-align:left; cursor:pointer; }
.sk-open1 .sk-o-t{ display:block; font:400 15px/1.25 var(--sf-ui); color:var(--sf-ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.sk-open1 .sk-o-s{ display:block; font:400 12.5px/1.3 var(--sf-ui); color:var(--sf-dim); margin-top:3px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.sk-open1 .sk-ic{ width:28px; height:28px; display:grid; place-items:center; color:var(--sf-dim); }
.sk-open1 .sk-ic svg{ width:16px; height:16px; fill:none; stroke:currentColor; stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round; }
/* › means "go into it, here": an author opens inside its own part, with a way back */
.sk-drill-back{ display:flex; align-items:center; gap:6px; width:100%; border:0; background:none; padding:10px 12px 4px; font:600 13px/1 var(--sf-ui); color:var(--sf-ink); cursor:pointer; letter-spacing:0; text-transform:none; }
.sk-drill-back svg{ width:16px; height:16px; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
.sk-drill{ padding:0 12px 12px; }
.sf-part.sk-drilled > :not(.sk-drill):not(.sk-drill-back){ display:none !important; }
.sf-part.sk-drilled > .sk-drill-back{ padding-top:12px; font-size:15px; font-weight:700; }
html[data-phone] .sf.sf-hassel .sf-works, html[data-phone] .sf.sk-authoron .sf-works,
html[data-phone] .sf.sf-hassel .sf-works.empty{
  display:block; position:absolute; left:0; right:0; bottom:0; z-index:5; flex:none; height:auto; max-height:86%; min-height:40%;
  overflow-y:auto; overscroll-behavior:contain; border:0; border-radius:22px 22px 0 0; padding:0 18px calc(24px + var(--safe-bottom, env(safe-area-inset-bottom, 0px)));
  background:var(--sf-ground); box-shadow:0 -10px 40px rgba(0,0,0,.18); transition:transform .25s ease; }
html[data-phone] .sf.sk-authoron .sf-works{ display:block; }
html[data-phone] .sf-works > .sk-grab{ position:sticky; top:0; z-index:2; display:grid !important; place-items:center; height:22px; margin:0 -18px 6px; background:var(--sf-ground); cursor:pointer; }
html[data-phone] .sf-works > .sk-grab > span{ width:40px; height:5px; border-radius:3px; background:color-mix(in srgb, var(--sf-ink) 22%, transparent); }
html[data-phone] .sf-works.sk-side-on > :not(.sk-side):not(.sk-grab):not(.sf-peekpane){ display:none !important; }
html[data-phone] .sk-side .sk-cloudsay{ display:block; margin-top:8px; font:12.5px/1.35 var(--sf-ui); color:var(--sf-dim); letter-spacing:0; text-transform:none; }

/* a long title with no spaces ("calculus_08_Techniques_of_Integration") breaks inside the card, never past its edge (seen on the iPhone Air simulator after the 18:29 export) */
.sk-who h3{ overflow-wrap:anywhere; word-break:break-word; }

/* THE MAC'S RECENT ROW (14 Oct): the phone's strip, covers a little larger, no snap, the column's own inset */
html:not([data-phone]) .sk-strip-mac{ padding:2px 0 12px; gap:8px; scroll-snap-type:none; touch-action:auto; }
html:not([data-phone]) .sk-strip-mac .sk-cov{ width:64px; height:88px; }

/* ================================================================ CONTENTS CHOOSE WHAT MAKE MAKES (Osca 14 Oct, #10)
   Each chapter row: a tick · the title (it opens the book there) · the row's steps (next step as a quiet press, the
   step ribbon). All / None and the count at the head. Make reads "Make 3 chapters" when some are chosen. */
.sf-tocpick{ display:flex; align-items:center; gap:6px; padding:6px 0 8px; font:12px/1.3 var(--sf-ui); color:var(--sf-dim); }
.sf-tocall{ font:600 11.5px/1 var(--sf-ui); padding:6px 10px; border-radius:13px; border:1px solid var(--sf-rule);
  background:none; color:var(--sf-ink); cursor:pointer; }
.sf-tocall:hover:not([disabled]){ border-color:var(--sf-dim); }
.sf-tocall[disabled]{ opacity:.4; cursor:default; }
.sf-tocn{ margin-left:auto; text-align:right; }
.sf-bchrow{ display:flex; align-items:center; gap:8px; border-top:1px solid var(--sf-rule); }
.sf-bchrow > .sf-bch{ flex:1 1 auto; min-width:0; border-top:0; }
.sf-bchrow:not(.on) > .sf-bch{ color:var(--sf-dim); }
.sf-btick{ flex:0 0 auto; width:18px; height:18px; margin:0; padding:0; border-radius:5px; border:1.5px solid var(--sf-dim);
  background:none; cursor:pointer; position:relative; }
.sf-bchrow.on > .sf-btick{ background:var(--sf-ink); border-color:var(--sf-ink); }
.sf-bchrow.on > .sf-btick::after{ content:""; position:absolute; left:5px; top:1.5px; width:4px; height:9px;
  border:solid var(--sf-ground); border-width:0 2px 2px 0; transform:rotate(45deg); }
.sf-btick:focus-visible{ outline:2px solid var(--sf-ink); outline-offset:2px; }
.sf-bchrow{ position:relative; }
.sf-bchmade{ flex:0 0 auto; width:6px; height:6px; border-radius:50%; background:var(--sf-ink); margin-right:2px; }
.sf-bchmade.notime{ background:#a8532a; }
/* the row's steps lie over its right end only while the pointer (or the keyboard) is on the row, so a title never
   gives up its width to them */
.sf-bchend{ position:absolute; right:0; top:50%; transform:translateY(-50%); display:none; align-items:center; gap:6px;
  padding:3px 0 3px 10px; background:var(--sf-ground); box-shadow:-10px 0 10px -4px var(--sf-ground); }
.sf-bchrow:hover > .sf-bchend, .sf-bchrow:focus-within > .sf-bchend{ display:flex; }
.sf-bchend .sf-notime{ font:11px/1 var(--sf-ui); color:#a8532a; }
.sf-bchend .sf-cell{ font-size:8.5px; letter-spacing:.06em; padding:2px 7px; }
/* "Make 3 chapters" is longer than "Make": the voice keeps a readable width and Make goes under it when it must */
.sk-mkrow > .sf-ddrow{ min-width:112px; }
.sk-foot .sf-tocfold > summary .sk-tocn{ margin-left:auto; margin-right:8px; font:12px/1 var(--sf-ui); color:var(--sf-dim); }
.sk-foot .sf-tocfold > summary{ align-items:center; }
/* MORE SETTINGS, kept as a dropdown under Make (Osca 14 Oct, #11) */
.sk-sec > details.sk-more{ margin:2px 0 0; border-top:0; }
.sk-sec > details.sk-more > summary{ list-style:none; cursor:pointer; padding:6px 0; font:13px/1.3 var(--sf-ui); letter-spacing:0;
  text-transform:none; color:var(--sf-dim); display:flex; justify-content:space-between; }
.sk-sec > details.sk-more > summary::-webkit-details-marker{ display:none; }
.sk-sec > details.sk-more > summary::after{ content:"\203A"; }
.sk-sec > details.sk-more[open] > summary::after{ transform:rotate(90deg); }
.sk-sec > .sk-cloudsay{ display:block; font:12.5px/1.35 var(--sf-ui); color:var(--sf-dim); letter-spacing:0; text-transform:none; }
.sk-sec > .sk-again{ justify-self:start; }

/* =====================================================================================================================
   J4 · THE SURFACE'S FRONT, FROM THE MASTER: the chips at the top (no title), the chosen one's row under them, + apart in
   the corner; banners as wide as the Surface; rows that scroll sideways to its edges.
   ===================================================================================================================== */
.sk-home{ position: relative; padding: 4px 44px 6px 0; }
.sk-chips{ display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; padding: 4px 0; }
.sk-chips::-webkit-scrollbar{ display: none; }
.sk-chip{ -webkit-appearance: none; appearance: none; flex: none; border: 1px solid color-mix(in srgb, var(--sf-ink, var(--fg, #111)) 14%, transparent);
  background: transparent; color: inherit; border-radius: 999px; padding: 8px 14px; font: 500 14px/1 var(--chrome-ui-font, -apple-system, system-ui, sans-serif); cursor: pointer; }
.sk-chip.on{ background: var(--sf-ink, var(--fg, #111)); color: var(--sf-bg, var(--bg, #fff)); border-color: transparent; }
.sk-sub .sk-chip{ padding: 6px 12px; font-size: 13px; }
.sk-plus{ -webkit-appearance: none; appearance: none; position: absolute; right: 0; top: 4px; width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--sf-ink, var(--fg, #111)) 14%, transparent); background: transparent; color: inherit; padding: 0; }
.sk-plus svg{ width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; }
.sk-plusmenu{ position: absolute; right: 0; top: 46px; z-index: 5; min-width: 220px; padding: 6px; border-radius: 14px; display: flex; flex-direction: column;
  background: var(--sf-bg, var(--bg, #fff)); box-shadow: 0 12px 40px rgba(0,0,0,.18); border: 1px solid color-mix(in srgb, var(--sf-ink, #111) 10%, transparent); }
.sk-plusmenu button{ all: unset; cursor: pointer; padding: 10px 12px; border-radius: 9px; font: 400 15px/1.3 var(--chrome-ui-font, system-ui); }
.sk-plusmenu button:hover{ background: color-mix(in srgb, var(--sf-ink, #111) 7%, transparent); }
.sk-banner{ display: flex; justify-content: space-between; align-items: baseline; margin: 22px 0 10px; padding-top: 14px;
  border-top: 1px solid color-mix(in srgb, var(--sf-ink, var(--fg, #111)) 10%, transparent); }
.sk-banner b{ font: 500 20px/1.2 var(--serif, Georgia, serif); }
.sk-banner i{ font: 400 13px/1 var(--chrome-ui-font, system-ui); font-style: normal; opacity: .55; }
.sk-row{ display: flex; gap: 14px; overflow-x: auto; scrollbar-width: none; padding-bottom: 8px; margin-right: -24px; padding-right: 24px; }
.sk-row::-webkit-scrollbar{ display: none; }
.sk-bk{ all: unset; cursor: pointer; flex: none; width: 108px; display: flex; flex-direction: column; gap: 4px; }
.sk-bkc{ width: 108px; height: 158px; border-radius: 3px; overflow: hidden; display: grid; place-items: center; color: #fff; font: 500 40px/1 var(--serif, Georgia, serif);
  box-shadow: 0 6px 16px rgba(0,0,0,.14); }
.sk-bkc img{ width: 100%; height: 100%; object-fit: cover; }
.sk-bk b{ font: 500 13px/1.25 var(--serif, Georgia, serif); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; margin-top: 4px; }
.sk-bk i{ font: 400 12px/1.2 var(--chrome-ui-font, system-ui); font-style: normal; opacity: .6; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sk-au{ all: unset; cursor: pointer; flex: none; width: 84px; display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; }
.sk-aup{ width: 64px; height: 64px; border-radius: 50%; display: grid; place-items: center; color: #fff; font: 600 18px/1 var(--chrome-ui-font, system-ui); }
.sk-au b{ font: 500 12px/1.25 var(--chrome-ui-font, system-ui); }
.sk-wait{ margin: 4px 0 6px; font: 400 14px/1.5 var(--chrome-ui-font, system-ui); opacity: .62; max-width: 560px; }
.sk-say{ position: fixed; left: 50%; bottom: 110px; transform: translateX(-50%); z-index: 200; max-width: 86vw; padding: 12px 16px; border-radius: 14px;
  background: #17150f; color: #f6f1e7; font: 400 14px/1.4 var(--chrome-ui-font, system-ui); box-shadow: 0 10px 30px rgba(0,0,0,.25); }
html[data-phone] .sk-home{ padding-right: 44px; }
html[data-phone] .sk-bk{ width: 96px; } html[data-phone] .sk-bkc{ width: 96px; height: 140px; }
html[data-phone] .sk-home, html[data-phone] .sk-banner, html[data-phone] .sk-wait, html[data-phone] .sk-row{ margin-left: 16px; }
html[data-phone] .sk-home{ margin-right: 12px; }
.sk-home, .sk-banner, .sk-wait, .sk-row, .sk-chips{ flex: none; }
html[data-phone] .sk-banner{ margin-right: 16px; }
/* =====================================================================================================================
   J4 v2 · THE SURFACE AS THE MASTER DRAWS IT (PORT-GAPS S1-S2): filled pills, the chosen one black; a banner as wide as
   the Surface in Frank's blue with books standing as objects; every cover an object (page block, drop) on a baseline.
   ===================================================================================================================== */
.sk-chip{ border: 0 !important; background: color-mix(in srgb, var(--sf-ink, var(--fg, #111)) 7%, transparent) !important; }
.sk-chip.on{ background: var(--sf-ink, var(--fg, #111)) !important; color: var(--sf-bg, var(--bg, #fff)) !important; }
.sk-hero{ position: relative; flex: none; margin: 14px -24px 6px; padding: 30px 24px 24px; min-height: 190px; box-sizing: border-box; background: #2e3f8f; color: #fff; overflow: hidden; }
html[data-phone] .sk-hero{ margin: 12px 0 6px; padding: 26px 18px 20px; }
.sk-hk{ font: 600 11px/1.3 var(--chrome-ui-font, system-ui); letter-spacing: .12em; text-transform: uppercase; opacity: .85; }
.sk-ht{ font: 400 32px/1.1 var(--serif, Georgia, serif); margin: 8px 0 18px; max-width: 46%; }
html[data-phone] .sk-ht{ font-size: 26px; max-width: 48%; }
.sk-hplay{ -webkit-appearance: none; appearance: none; border: 0; cursor: pointer; display: inline-flex; align-items: center; gap: 8px; padding: 10px 18px 10px 14px; border-radius: 999px;
  background: #fff; color: #17150f; font: 500 14px/1 var(--chrome-ui-font, system-ui); }
.sk-hplay svg{ width: 12px; height: 12px; fill: currentColor; }
.sk-hobjs{ position: absolute; right: 24px; bottom: 24px; display: flex; gap: 14px; align-items: flex-end; }
html[data-phone] .sk-hobjs{ right: 16px; bottom: 22px; gap: 8px; }
.sk-hobjs .sk-bk{ width: auto; } .sk-hobjs .sk-bk b, .sk-hobjs .sk-bk i{ display: none; }
.sk-hobjs .sk-bkc{ width: 84px; height: 124px; } html[data-phone] .sk-hobjs .sk-bkc{ width: 52px; height: 78px; }
.sk-hobjs .sk-bk:nth-child(2) .sk-bkc{ width: 96px; height: 140px; } html[data-phone] .sk-hobjs .sk-bk:nth-child(2) .sk-bkc{ width: 60px; height: 90px; }
.sk-bkc, .sk-cov{ border-radius: 1px 3px 3px 1px !important; box-shadow: 1px 1px 0 #f6f2e8, 2px 1px 0 #e6dfcd, 3px 2px 0 #f6f2e8, 4px 2px 0 #e6dfcd, 5px 3px 0 rgba(0,0,0,.18), 7px 9px 14px rgba(0,0,0,.18) !important; }
.sk-row{ align-items: flex-end; padding-top: 6px; }
.sk-bk{ align-items: center; text-align: center; } .sk-bk b, .sk-bk i{ text-align: center; }
.sk-banner b{ font: 600 19px/1.2 var(--chrome-ui-font, system-ui) !important; letter-spacing: -.01em; }
.sk-banner{ border-top: 0 !important; padding-top: 4px !important; }
.sk-hobjs .sk-bk{ width: auto !important; flex: none; }
.sk-hero{ display: flex; flex-direction: column; align-items: flex-start; }
.sk-ht{ max-width: 50%; }
html[data-phone] .sk-hobjs .sk-bk:nth-child(3){ display: none; }
html[data-phone] .sk-ht{ max-width: 55%; }
/* J4 v2 (the master): the Mac's Surface is ONE column until something is chosen -- the works column only when it has work */
html:not([data-phone]) .sf .sf-works.empty{ display: none !important; }
html[data-phone] .sk-card{ background: transparent !important; }
html:not([data-phone]) .sf .sf-cols:has(> .sf-works.empty) > .sf-list{ flex: 1 1 auto !important; width: auto !important; max-width: none !important; }
/* the master: on the Mac the Surface is ONE very large card, rising from the foot to just under the title bar */
html:not([data-phone]) .sf.on{ width: min(1320px, calc(100vw - 48px)) !important; top: 44px !important; bottom: 0 !important; height: auto !important; max-height: none !important;
  border-radius: 22px 22px 0 0 !important; }
.sk-row.sk-authors{ padding-top: 4px; align-items: flex-start; }
/* J4 v3 · the Surface's coloured sections (the master): the kinds of book as tiles in their own looks; Frank's picks in a
   green band; a season in teal; short and slim as a list; the voices people are using, moving */
.sk-kinds{ gap: 10px; padding: 14px 0 4px; }
.sk-kind{ -webkit-appearance: none; appearance: none; border: 0; cursor: pointer; flex: none; width: 150px; height: 88px; border-radius: 14px; padding: 12px 14px; box-sizing: border-box;
  display: flex; flex-direction: column; justify-content: flex-end; text-align: left; }
html[data-phone] .sk-kind{ width: 116px; height: 80px; }
.sk-kind b{ font: 400 22px/1 var(--serif, Georgia, serif); } .sk-kind i{ font: 400 11.5px/1.25 var(--chrome-ui-font, system-ui); font-style: normal; opacity: .8; margin-top: 4px; }
.sk-k-science{ background-color: #eef3fb; background-image: linear-gradient(#d4e0f5 1px, transparent 1px), linear-gradient(90deg, #d4e0f5 1px, transparent 1px); background-size: 14px 14px; color: #0f2f6b; }
.sk-k-science b{ font: 700 21px/1 var(--chrome-ui-font, system-ui); letter-spacing: -.01em; }
.sk-k-poetry{ background: #ffe1dc; color: #7a1b3b; } .sk-k-poetry b{ font-style: italic; font-size: 26px; }
.sk-k-history{ background: radial-gradient(ellipse at 20% 10%, #f8ecd0, #e2c48f); color: #4a2a10; } .sk-k-history b{ font-variant: small-caps; letter-spacing: .08em; }
.sk-k-philosophy{ background: linear-gradient(115deg, #f4f2ee 0%, #e4e0d8 28%, #f7f5f1 44%, #d9d4cb 68%, #f4f2ee 100%); color: #1d1a15; } .sk-k-philosophy b{ font-size: 13px; letter-spacing: .24em; text-transform: uppercase; }
.sk-k-plays{ background: #6e1d24; color: #f6e7d8; } .sk-k-fiction{ background: #2f5440; color: #eef3ea; }
.sk-band{ flex: none; margin: 22px -24px 6px; padding: 22px 24px 18px; }
html[data-phone] .sk-band{ margin: 22px 0 6px; padding: 20px 16px 16px; }
.sk-band .sk-bt{ font: 400 28px/1.15 var(--serif, Georgia, serif); } .sk-band .sk-bs{ font: 400 14px/1.4 var(--chrome-ui-font, system-ui); opacity: .82; margin-top: 4px; }
.sk-band .sk-row{ margin-top: 14px; } .sk-band .sk-bk b, .sk-band .sk-bk i{ color: inherit; opacity: .92; }
.sk-band-green{ background: #2f5440; color: #f3efe2; } .sk-band-teal{ background: #2a9d8f; color: #fff; }
.sk-slim{ display: grid; grid-template-columns: 1fr 1fr; gap: 6px 18px; flex: none; }
html[data-phone] .sk-slim{ margin: 0 16px; }
.sk-sl{ -webkit-appearance: none; appearance: none; border: 0; background: none; cursor: pointer; display: flex; align-items: center; gap: 12px; padding: 6px 0; text-align: left; color: inherit; min-width: 0; }
.sk-sl .sk-bkc{ width: 30px !important; height: 44px !important; flex: none; font-size: 12px; }
.sk-slt{ min-width: 0; } .sk-slt b{ display: block; font: 500 14.5px/1.25 var(--chrome-ui-font, system-ui); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sk-slt i{ display: block; font: 400 12.5px/1.25 var(--chrome-ui-font, system-ui); font-style: normal; opacity: .6; }
.sk-vrow{ gap: 10px; }
.sk-wave{ -webkit-appearance: none; appearance: none; cursor: pointer; flex: none; display: flex; align-items: center; gap: 10px; border-radius: 16px; padding: 10px 14px 10px 10px; min-width: 240px;
  background: var(--sf-bg, #fff); color: inherit; border: 0; box-shadow: 0 0 0 1px color-mix(in srgb, var(--sf-ink, #111) 10%, transparent); text-align: left; }
.sk-wpb{ flex: none; width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center; background: var(--vc); color: #fff; }
.sk-wpb svg{ width: 13px; height: 13px; fill: currentColor; margin-left: 2px; }
.sk-wt b{ display: block; font: 600 14px/1.2 var(--chrome-ui-font, system-ui); } .sk-wt i{ display: block; font: 400 11.5px/1.2 var(--chrome-ui-font, system-ui); font-style: normal; opacity: .62; }
.sk-wv{ display: flex; align-items: center; gap: 2px; height: 30px; margin-left: 6px; }
.sk-wv i{ width: 2.5px; border-radius: 2px; background: currentColor; opacity: .4; transform-origin: center; animation: skwv 1.3s ease-in-out infinite alternate; }
@keyframes skwv{ 0%{ transform: scaleY(.45); } 50%{ transform: scaleY(1); } 100%{ transform: scaleY(.65); } }
@media (prefers-reduced-motion: reduce){ .sk-wv i{ animation: none; } }
.sk-every{ flex: none; margin-top: 26px; }
html[data-phone] .sk-every{ margin-left: 16px; margin-right: 16px; }
.sk-every > b{ display: block; font: 600 19px/1.2 var(--chrome-ui-font, system-ui); margin-bottom: 10px; }
.sk-links{ display: flex; flex-wrap: wrap; gap: 8px 18px; } .sk-links button{ -webkit-appearance: none; appearance: none; border: 0; background: none; padding: 0; cursor: pointer; color: inherit; font: 400 15px/1.4 var(--chrome-ui-font, system-ui); }
html[data-phone] .sk-kinds, html[data-phone] .sk-vrow{ margin-left: 16px; }

/* the Surface's communities (the master's fm-cmc): a card each, its colour, its next reading in red */
.sk-cms { display: grid; gap: 8px; margin: 0 0 8px; }
html:not([data-phone]) .sk-cms { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.sk-cm { all: unset; box-sizing: border-box; cursor: pointer; display: flex; gap: 12px; align-items: center; padding: 8px; border-radius: 14px;
  background: color-mix(in srgb, var(--fg, #111) 5%, var(--bg, #fff)); transition: transform .18s ease, box-shadow .18s ease; }
.sk-cm:hover { transform: translateY(-1px); box-shadow: 0 6px 18px -10px rgba(0,0,0,.35); }
.sk-cmb { width: 58px; height: 66px; border-radius: 10px; flex: none; display: grid; place-items: center; overflow: hidden; background: var(--cc); }
.sk-cmb img { width: 40px; height: auto; border-radius: 1px 3px 3px 1px; box-shadow: 1px 2px 6px rgba(0,0,0,.35); }
.sk-cmb em { color: rgba(255,255,255,.88); font: 600 13px / 1 Georgia, serif; font-style: normal; }
.sk-cmt { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.sk-cmt b { font: 600 14px / 1.25 var(--ui-font, system-ui); }
.sk-cmt i { font: 400 11.5px / 1.3 var(--ui-font, system-ui); font-style: normal; opacity: .62; }
.sk-cmt em { font: 500 11.5px / 1.3 var(--ui-font, system-ui); font-style: normal; color: #c4501d; }
/* a row of book objects stands on one floor: every caption is the same height (two lines of title, one of author), so a
   one-line title never lifts its book, and an author never runs under the next book */
.sk-row .sk-bk b{ min-height: 2.5em; max-width: 100%; }
.sk-row .sk-bk i{ max-width: 100%; min-height: 1.2em; }
.sk-hobjs .sk-bk b{ min-height: 0; }
/* the master (fm-MAC .fm-card: left 0, right 0, top 12, bottom 0): on the Mac and the web the Surface is the whole width
   of the window, edge to edge, rising to just under the top -- not a centred card (Osca 16 Oct 23:49) */
html:not([data-phone]) .sf.on{ width: 100vw !important; max-width: none !important; left: 0 !important; transform: none !important; top: 12px !important; bottom: 0 !important;
  border-radius: 22px 22px 0 0 !important; border-left: 0 !important; border-right: 0 !important; }
html:not([data-phone]) .sf:not(.on){ left: 0 !important; width: 100vw !important; max-width: none !important; transform: translateY(24px) !important; }
/* the Voices view: your voices as a grid of moving waves */
.sk-vgrid{ display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; margin: 0 0 14px; }
html[data-phone] .sk-vgrid{ grid-template-columns: 1fr; margin-left: 16px; margin-right: 16px; }
.sk-vgrid .sk-wave{ width: auto !important; }
.sk-wave .sk-wv i{ background: var(--vc, currentColor) !important; opacity: .85; }
.sk-wave .sk-wpb{ background: var(--vc) !important; }
/* S3 · THE SEARCH PILL AT THE FOOT (the master, Mac and web: "Search Frank: books, people, voices, lines" with x beside
   it). The field leaves the top of the card and floats at its foot, a glass pill; Esc is the round x beside it. */
html:not([data-phone]) .sf.on .sf-field{ position: absolute !important; left: 50%; bottom: 22px; transform: translateX(-50%); z-index: 6; width: min(640px, calc(100% - 160px)); height: 54px;
  border: 0 !important; border-radius: 27px; padding: 0 20px !important; overflow: visible;
  background: color-mix(in srgb, var(--sf-sheet, #fff) 82%, transparent); -webkit-backdrop-filter: blur(22px) saturate(1.4); backdrop-filter: blur(22px) saturate(1.4);
  box-shadow: 0 14px 40px rgba(0,0,0,.18), 0 0 0 .5px rgba(0,0,0,.10); }
html:not([data-phone]) .sf.on .sf-field input{ font-size: 17px; }
html:not([data-phone]) .sf.on .sf-esc{ position: absolute; right: -58px; top: 50%; transform: translateY(-50%); width: 44px; height: 44px; padding: 0; border: 0; border-radius: 50%;
  font-size: 0; color: transparent; background: color-mix(in srgb, var(--sf-sheet, #fff) 82%, transparent); -webkit-backdrop-filter: blur(22px); backdrop-filter: blur(22px);
  box-shadow: 0 10px 28px rgba(0,0,0,.16), 0 0 0 .5px rgba(0,0,0,.10); cursor: pointer; }
html:not([data-phone]) .sf.on .sf-esc::before{ content: "\00d7"; font: 300 26px/44px var(--sf-ui, system-ui); color: var(--sf-ink, #111); display: block; text-align: center; }
html:not([data-phone]) .sf.on .sf-list, html:not([data-phone]) .sf.on .sf-works{ padding-bottom: 110px !important; }
html:not([data-phone]) .sf.on .sk-chips, html:not([data-phone]) .sf.on .sk-home{ margin-top: 14px; }
.sk-band-dark{ background: #17150f; color: #f3efe2; } .sk-band-red{ background: #a8241f; color: #fff; }
.sk-withface{ position: relative; }
.sk-face{ position: absolute; z-index: 3; left: calc(50% + 30px); top: calc(158px - 18px); width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center;
  color: #fff; font: 600 11px/1 var(--chrome-ui-font, system-ui); box-shadow: 0 0 0 2.5px currentColor, 0 4px 10px rgba(0,0,0,.3); }
.sk-band-dark .sk-face{ box-shadow: 0 0 0 2.5px #17150f, 0 4px 10px rgba(0,0,0,.3); } .sk-band-red .sk-face{ box-shadow: 0 0 0 2.5px #a8241f, 0 4px 10px rgba(0,0,0,.3); }
html[data-phone] .sk-face{ top: calc(140px - 18px); left: calc(50% + 24px); }

/* SEARCH RESULTS AS BOOKS (Osca 17 Oct 10:23: "rows of one cover then loads of white space, then the add button ... make
   it look like the plans AND the rest of the Surface, with larger book covers and titles; click one and it opens in
   the right column, then you add it"). Every result that is a BOOK -- yours, or out there -- is a book object in a grid:
   the cover large, the title in the serif and the author under it. A press selects it and the right column answers
   (Open for yours; Sample and Add for one out there). A passage, a chapter, a person and the "search YouTube / the web"
   lines stay lines, full width, between the grids. */
.sf .sf-part{ display:grid !important; grid-template-columns:repeat(auto-fill, minmax(150px, 1fr)); column-gap:26px; row-gap:0; align-items:start; }
html[data-phone] .sf .sf-part{ grid-template-columns:repeat(3, minmax(0, 1fr)); column-gap:14px; }
.sf .sf-part > *{ grid-column:1 / -1; }
.sf .sf-part > .sf-row.sk.r-shelf:not(.sf-pass):not(.sf-ch):not(.sf-find):not(.sf-query),
.sf .sf-part > .sf-row.sk.r-out:not(.sf-find):not(.sf-query){
  grid-column:auto; display:flex !important; flex-direction:column; align-items:center; text-align:center; gap:0;
  min-height:0; padding:12px 6px 18px; border-radius:14px; background:none !important; position:relative; cursor:pointer;
  transition:background .2s; }
.sf .sf-part > .sf-row.sk.r-shelf:not(.sf-pass):not(.sf-ch):not(.sf-find):not(.sf-query) > .sk-pic,
.sf .sf-part > .sf-row.sk.r-out:not(.sf-find):not(.sf-query) > .sk-pic{
  width:min(100%, 150px); height:auto; aspect-ratio:2 / 3; border-radius:1px 4px 4px 1px; font-size:44px;
  box-shadow:1px 0 0 #f6f2e8, 2px 1px 0 #e6dfcd, 3px 2px 0 #f6f2e8, 4px 2px 0 #e2dac6, 5px 3px 0 rgba(0,0,0,.16), 6px 10px 18px rgba(0,0,0,.20);
  transition:transform .35s cubic-bezier(.2,.8,.2,1), box-shadow .35s; }
html[data-phone] .sf .sf-part > .sf-row.sk > .sk-pic{ font-size:30px; }
.sf .sf-part > .sf-row.sk.r-shelf:not(.sf-pass):not(.sf-ch):not(.sf-find):not(.sf-query):hover > .sk-pic,
.sf .sf-part > .sf-row.sk.r-out:not(.sf-find):not(.sf-query):hover > .sk-pic{ transform:translateY(-4px); }
.sf .sf-part > .sf-row.sk.sel:not(.sf-pass):not(.sf-ch):not(.sf-find):not(.sf-query){ background:color-mix(in srgb, var(--sf-ink, #111) 5%, transparent) !important; }
.sf .sf-part > .sf-row.sk.sel:not(.sf-pass):not(.sf-ch):not(.sf-find):not(.sf-query) > .sk-pic{ transform:translateY(-4px);
  box-shadow:1px 0 0 #f6f2e8, 2px 1px 0 #e6dfcd, 3px 2px 0 #f6f2e8, 4px 2px 0 #e2dac6, 5px 3px 0 rgba(0,0,0,.16), 8px 18px 26px rgba(0,0,0,.28); }
.sf .sf-part > .sf-row.sk.r-shelf:not(.sf-pass):not(.sf-ch):not(.sf-find):not(.sf-query) > .body,
.sf .sf-part > .sf-row.sk.r-out:not(.sf-find):not(.sf-query) > .body{ width:100%; margin-top:12px; }
.sf .sf-part > .sf-row.sk:not(.sf-pass):not(.sf-ch):not(.sf-find):not(.sf-query) .t{
  display:-webkit-box !important; -webkit-box-orient:vertical; -webkit-line-clamp:2; white-space:normal !important;
  font:400 15px/1.25 var(--sf-serif, Georgia, serif) !important; color:var(--sf-ink); }
.sf .sf-part > .sf-row.sk:not(.sf-pass):not(.sf-ch):not(.sf-find):not(.sf-query) .s{ font-size:12px !important; margin-top:4px; }
html[data-phone] .sf .sf-part > .sf-row.sk:not(.sf-pass):not(.sf-ch):not(.sf-find):not(.sf-query) .t{ font-size:13px !important; }
/* the buttons: a round + on the cover's corner for one out there (Add), nothing on yours (the press opens it) */
.sf .sf-part > .sf-row.sk.r-shelf:not(.sf-pass):not(.sf-ch):not(.sf-find):not(.sf-query) > .end{ display:none !important; }
.sf .sf-part > .sf-row.sk.r-out:not(.sf-find):not(.sf-query) > .end{ position:absolute; top:4px; right:calc(50% - min(50%, 75px) - 6px); min-width:0 !important; padding:0; gap:4px; }
.sf .sf-part > .sf-row.sk.r-out:not(.sf-find):not(.sf-query) > .end .sk-ic{ width:34px !important; height:34px; background:color-mix(in srgb, var(--sf-sheet, #fff) 86%, transparent);
  -webkit-backdrop-filter:blur(14px); backdrop-filter:blur(14px); box-shadow:0 4px 14px rgba(0,0,0,.18), 0 0 0 .5px rgba(0,0,0,.08); color:var(--sf-ink);
  opacity:0; transform:scale(.9); transition:opacity .2s, transform .2s; }
.sf .sf-part > .sf-row.sk.r-out:not(.sf-find):not(.sf-query):hover > .end .sk-ic,
.sf .sf-part > .sf-row.sk.r-out.sel:not(.sf-find):not(.sf-query) > .end .sk-ic,
html[data-phone] .sf .sf-part > .sf-row.sk.r-out > .end .sk-ic{ opacity:1; transform:none; }
.sf .sf-part > .sf-row.sk.r-out:not(.sf-find):not(.sf-query) > .end .sf-samp{ display:none; }
/* the section heads span the grid, with room above */
.sf .sf-part > .sf-h.sk-parthead{ margin-top:18px; }
.sf .sf-part > .sk-libhead{ display:none !important; }
.sf .sf-part > .sf-row.sk:not(.sf-pass):not(.sf-ch):not(.sf-find):not(.sf-query) > .body{ flex:none !important; }
.sf .sf-part > .sf-row.sk.r-out.sf-fixed:not(.sf-find):not(.sf-query){ height:auto !important; overflow:visible !important; }
.sf .sf-part{ flex:none !important; min-height:min-content; }
/* the Mac's Surface is a solid card (the master): nothing of the shelf shows through it */
html:not([data-phone]) .sf.on{ background:hsl(var(--sf-ground-hsl)) !important; -webkit-backdrop-filter:none !important; backdrop-filter:none !important; }

/* D111: Add to Library / In your Library, under the first press */
.sk-b.sk-keep{ margin-top: 8px; width: 100%; background: transparent; border: 1px solid color-mix(in srgb, currentColor 22%, transparent); }
.sk-b.sk-keep[disabled]{ opacity: .6; cursor: default; }
/* D111: signed out on the web the Surface IS the page (the master #m/WEB/surface): it sits under the banner, square,
   with no dimmed shelf behind it -- the banner's picture is the way to sign in */
html[data-browser][data-web]:not([data-phone]) .sf.on{ top: 56px !important; height: calc(100% - 56px) !important; border-radius: 0 !important; box-shadow: none !important; }
html[data-browser][data-web]:not([data-phone]) .sf-scrim{ display: none !important; }
html[data-browser][data-web]:not([data-phone]) .sk-grab{ display: none !important; }
/* D111: the Surface's corner says Sign in when you have no account */
.sk-home .sk-signin{ position: absolute; top: 0; right: 0; height: 36px; padding: 0 16px; border-radius: 18px; border: 0; cursor: pointer;
  background: var(--chrome-fg, #17150f); color: var(--chrome-bg, #fcfcfb); font: 500 14px/1 var(--chrome-ui-font, -apple-system, system-ui, sans-serif); }
html[data-browser] .sk-home{ padding-right: 100px; }
html[data-browser] .sk-home .sk-signin{ top: 4px; }

/* D113 · A BOOK IN THE SURFACE, AS THE MASTER DRAWS IT (#m/WEB/surface/book): the cover large and centred, the title in the
   book serif under it, the author and its facts centred, Read and Add to Library in one row */
.sk-side .sk-who{ display: flex !important; flex-direction: column !important; align-items: center !important; text-align: center; gap: 14px; padding-top: 8px; }
.sk-side .sk-who .sk-big{ width: 132px; height: 196px; border-radius: 3px; box-shadow: 0 10px 28px rgba(0,0,0,.18), 2px 0 0 #e9e4d8, 4px 0 0 #dcd6c8; }
.sk-side .sk-who .sk-big img{ width: 100%; height: 100%; object-fit: cover; }
.sk-side .sk-who h3{ font: 400 28px/1.15 var(--serif, "Iowan Old Style", Palatino, Georgia, serif); margin: 0; }
.sk-side .sk-who .sk-by{ font-size: 14px; margin-top: 6px; }
.sk-side .sk-who .sk-meta{ margin-top: 8px; }
.sk-side .sk-primary{ display: flex; justify-content: center; gap: 8px; flex-wrap: wrap; margin-top: 16px; }
.sk-side .sk-primary .sk-b.sk-wide{ flex: none; width: auto; padding: 0 22px; }
.sk-side .sk-primary .sk-b.sk-keep{ margin-top: 0; width: auto; padding: 0 18px; }

/* D114: the book's facts as chips, and its chapters by name */
.sk-side .sk-who .sk-meta{ display: none; }
.sk-side .sk-facts{ display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin-top: 12px; }
.sk-side .sk-fact{ font-size: 12px; padding: 4px 10px; border-radius: 999px; background: color-mix(in srgb, currentColor 7%, transparent); color: var(--sf-ink2, inherit); }
.sk-side .sk-chaps{ margin-top: 22px; }
.sk-side .sk-chaps > b{ display: block; font: 600 17px/1.2 var(--chrome-ui-font, -apple-system, system-ui, sans-serif); margin-bottom: 6px; }
.sk-side .sk-chlist{ display: flex; flex-direction: column; }
.sk-side .sk-ch{ all: unset; cursor: pointer; display: flex; gap: 12px; align-items: baseline; padding: 10px 2px; border-bottom: 1px solid color-mix(in srgb, currentColor 9%, transparent); font-size: 14px; }
.sk-side .sk-ch:hover .sk-cht{ text-decoration: underline; }
.sk-side .sk-chn{ min-width: 22px; color: var(--chrome-accent, #c02c46); font-variant-numeric: tabular-nums; }
.sk-side .sk-cht{ flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sk-side .sk-chmore{ font-size: 13px; opacity: .6; margin: 10px 0 0; }
/* S6 · LINES: a passage people keep, in the book's own type, its book and who under it */
.sk-lines{ display: grid; gap: 10px; margin: 6px 0 22px; }
.sk-line{ display: block; text-align: left; width: 100%; border: 0; cursor: pointer; padding: 14px 18px; border-radius: 16px;
  background: color-mix(in srgb, var(--fg, #111) 5%, transparent); color: inherit; font: inherit; }
.sk-line q{ display: block; font: 400 19px/1.4 var(--serif, "Iowan Old Style", Palatino, Georgia, serif); quotes: "\201C" "\201D"; }
.sk-lineby{ display: block; margin-top: 6px; font-size: 13px; opacity: .6; }
.sk-ch .sk-chl{ margin-left: auto; padding-left: 10px; font-size: 12px; opacity: .55; white-space: nowrap; font-variant-numeric: tabular-nums; }
/* S6 · INSIDE FRANK'S BOOKS: a passage, the words you typed marked, its book and chapter under it */
.sk-inside{ margin-top: 10px; }
.sk-in{ all: unset; box-sizing: border-box; display: block; width: 100%; cursor: pointer; padding: 10px 12px; border-radius: 12px; }
.sk-in:hover{ background: color-mix(in srgb, currentColor 6%, transparent); }
.sk-inq{ display: block; font: 400 15px/1.45 var(--serif, "Iowan Old Style", Palatino, Georgia, serif); }
.sk-inq mark{ background: color-mix(in srgb, #f2c94c 55%, transparent); color: inherit; border-radius: 3px; padding: 0 1px; }
.sk-inby{ display: block; margin-top: 3px; font-size: 12.5px; opacity: .6; }
/* ITEM 201 · PEOPLE IN FRANK: a face in its own colour, the name, "@handle · place · followers" under it */
.sk-ppl{ margin-top: 10px; }
.sk-pp{ all: unset; box-sizing: border-box; display: flex; align-items: center; gap: 12px; width: 100%; cursor: pointer; padding: 8px 12px; border-radius: 12px; }
.sk-pp:hover{ background: color-mix(in srgb, currentColor 6%, transparent); }
.sk-pp .sk-face{ position: static; flex: none; width: 36px; height: 36px; font-size: 13px; box-shadow: none; }
.sk-ppt{ min-width: 0; display: flex; flex-direction: column; }
.sk-ppt b{ font: 600 15px/1.3 var(--chrome-ui-font, system-ui); }
.sk-ppt i{ font-style: normal; font-size: 12.5px; opacity: .6; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* D140 · A RECORDING IS A CD (surface-skin.js picFor): a square case, the disc in it, the recording's art on the disc's
   face, the hole in the middle -- never a book's shape, never a voice's */
.sk-pic.sk-cd{ aspect-ratio:1 / 1 !important; height:auto; border-radius:3px !important; background:linear-gradient(135deg, #f4f4f6, #d9dbe0) !important;
  box-shadow:inset 3px 0 0 rgba(0,0,0,.12), inset 4px 0 0 rgba(255,255,255,.6), 0 6px 16px rgba(0,0,0,.18) !important; position:relative; }
.sk-pic.sk-cd .sk-disc{ position:absolute; inset:8%; border-radius:50%; overflow:hidden; background:var(--cd, #556);
  box-shadow:0 0 0 1px rgba(0,0,0,.18), 0 2px 6px rgba(0,0,0,.25); }
.sk-pic.sk-cd .sk-disc img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.sk-pic.sk-cd .sk-disc::after{ content:""; position:absolute; inset:0; border-radius:50%;
  background:conic-gradient(from 20deg, rgba(255,255,255,.0), rgba(255,255,255,.28), rgba(255,255,255,0) 18%, rgba(255,255,255,0) 50%, rgba(255,255,255,.22) 62%, rgba(255,255,255,0) 72%);
  mix-blend-mode:screen; }
.sk-pic.sk-cd .sk-disc i{ position:absolute; left:50%; top:50%; width:24%; height:24%; transform:translate(-50%,-50%); border-radius:50%; z-index:2;
  background:radial-gradient(circle, #efeff2 0 30%, rgba(255,255,255,.75) 31% 62%, rgba(0,0,0,.18) 63% 66%, transparent 67%); }

/* D167 (Osca 18 Oct: each book in its own shape, the same shape wherever it is): a cover box keeps its height and takes
   its width from the book's own picture (--ar, set when the picture loads, surface-skin.js); a book with no picture is
   Frank's cover at the shelf's one shape, 88:120 */
.sk-bkc, .sk-cov{ width:auto !important; aspect-ratio:var(--ar, 88 / 120); }
.sf .sf-part > .sf-row.sk.r-shelf:not(.sf-pass):not(.sf-ch):not(.sf-find):not(.sf-query) > .sk-pic:not(.sk-cd),
.sf .sf-part > .sf-row.sk.r-out:not(.sf-find):not(.sf-query) > .sk-pic:not(.sk-cd){ aspect-ratio:var(--ar, 88 / 120); }
