/* All color lives in this block. Light is the default; the phone's dark setting
   switches to the mockup's original dark palette. Accent (lamp) and type are the
   same in both; only surfaces, text, borders and shadows change. */
:root{
    color-scheme:light dark;
    /* light (default) */
    --chrome:#F6F1E7;        /* app background: warm paper */
    --chrome-2:#FFFCF6;      /* raised panels */
    --chrome-3:#DCD3C1;      /* borders on chrome */
    --page:#FFFDF8;          /* the lit page */
    --page-edge:#E6DDCA;     /* page rule */
    --ink:#23262F;           /* text on page */
    --ink-mut:#6F7280;       /* muted on page */
    --on-chrome:#23262F;     /* text on chrome */
    --on-chrome-mut:#5F6375; /* muted on chrome */
    --masthead-bg:rgba(246,241,231,.9);
    --hover-edge:#BFB39A;
    --btn-hover:#EEE6D6;
    --shadow-deep:rgba(70,52,20,.22);
    --shadow:rgba(70,52,20,.18);
    --lamp-text:#94600C;     /* amber dark enough to read on paper */
    /* What bma_ui.css spends on "this is required of you" (the Required tag,
       the field hint, the reason under a held button): the lamp's readable
       amber, a prompt colour, never an error red (BMA UX conventions II). */
    --accent:var(--lamp-text);
    /* A value a field REJECTS (too short, the two passwords differ, a key with
       a gap): its own colour, apart from the prompt amber, at 4.5:1 or better
       on the card in both themes (BMA UX conventions II). */
    --error:#B3261E;
    /* shared by both themes */
    --lamp:#F0B54A;          /* amber: what you are hearing */
    --lamp-hover:#F5C466;
    --lamp-soft:rgba(240,181,74,.30);
    --lamp-glow:0 0 0 6px rgba(240,181,74,.14);
    --lamp-halo:rgba(240,181,74,.45);
    --lamp-wash:rgba(240,181,74,.10);
    --lamp-edge:rgba(240,181,74,.4);
    --ribbon:#C9553F;        /* bookmark ribbon: your saved place */
    --ribbon-soft:rgba(201,85,63,.25);
    --ok:#6FA97F;
    --ok-wash:rgba(111,169,127,.12);
    --ok-edge:rgba(111,169,127,.35);
    --r:14px;
    --serif:"Literata",Georgia,"Times New Roman",serif;
    --sans:"Karla",system-ui,-apple-system,"Segoe UI",sans-serif;
    /* used by the scaffolder's .v2-badge rule */
    --paper:var(--page);
    --ink-faint:var(--ink-mut);
  }
  @media (prefers-color-scheme: dark){
    :root{
      /* dark: the mockup's original palette */
      --chrome:#1E2236;
      --chrome-2:#272C45;
      --chrome-3:#363C5C;
      --page:#F4EFE4;
      --page-edge:#E3DBC7;
      --on-chrome:#EDE9DF;
      --on-chrome-mut:#A6ABC4;
      --masthead-bg:rgba(30,34,54,.9);
      --hover-edge:#4A5178;
      --btn-hover:#2F3552;
      --shadow-deep:rgba(0,0,0,.7);
      --shadow:rgba(0,0,0,.6);
      --lamp-text:var(--lamp);
      --error:#FF8A80;
    }
  }
  *{box-sizing:border-box}
  html,body{margin:0}
  body{background:var(--chrome);color:var(--on-chrome);font-family:var(--sans);font-size:16px;line-height:1.5;-webkit-font-smoothing:antialiased}
  a{color:inherit}
  button{font:inherit;color:inherit}
  /* The focus ring is the dark amber (--lamp-text: about 5:1 on the paper in
     light, the bright amber on the dark palette), not --lamp, which is 1.6:1
     on the paper; WCAG 2.2 asks 3:1 of a focus indicator. */
  :focus-visible{outline:2px solid var(--lamp-text);outline-offset:2px}
  /* Side padding takes the safe-area insets: viewport-fit=cover (base.html)
     lets a notched phone in landscape draw under the notch (ac-15 part A). */
  .wrap{max-width:1120px;margin:0 auto;padding:0 max(20px,env(safe-area-inset-right,0px)) 0 max(20px,env(safe-area-inset-left,0px))}

  /* Masthead */
  /* The sticky masthead is 60px tall: every jump (scrollIntoView, an anchor,
     the restored place) stops below it, never under it (task 04V). */
  html{scroll-padding-top:72px}
  .masthead{position:sticky;top:0;z-index:30;background:var(--masthead-bg);backdrop-filter:blur(10px);border-bottom:1px solid var(--chrome-3)}
  .masthead .wrap{display:flex;align-items:center;gap:14px;height:60px}
  .brand{display:flex;align-items:center;gap:10px;font-family:var(--serif);font-weight:600;font-size:22px;letter-spacing:.01em}
  /* The brand is a link home (run-through finding F2): it keeps the brand's
     look, not a link's, and is a full tap target like the masthead's buttons
     (AC 15's phone masthead test). */
  a.brand{color:inherit;text-decoration:none;min-height:44px}
  .brand .lamp{width:12px;height:12px;border-radius:50%;background:var(--lamp);box-shadow:0 0 18px 4px var(--lamp-halo)}
  .masthead .spacer{flex:1}
  /* base.html puts the masthead inside .wrap (the mockup nests them the other
     way round), so the row is laid out here, on one line (ac-15 part A): on a
     desktop the brand then the four screen links; on a phone the brand, the
     current screen's name and the Menu button (Tim's review-copy check,
     10/12/2026). The links come after the button in the markup, so a phone's
     Tab order runs brand, Menu, then the open menu; `order` draws them right
     after the brand on a desktop. */
  .wrap > .masthead{display:flex;align-items:center;gap:8px;min-height:60px}
  .masthead form{margin:0}
  .masthead .brand{order:-2;margin-right:18px}
  .masthead .site-menu{order:-1;display:flex;align-items:stretch;align-self:stretch}
  /* `.masthead` in front: `.btn`'s own display rules come later in this sheet. */
  .masthead .nav-here,.masthead .menu-btn,.masthead .menu-signout{display:none}
  .masthead .menu-btn[hidden]{display:none}
  .chip{font-size:13px;color:var(--on-chrome-mut);border:1px solid var(--chrome-3);border-radius:100px;padding:5px 12px;white-space:nowrap}

  /* The screen links (task 04N), in the top bar (Tim's review-copy check,
     10/12/2026): plain text, muted; the current one bold over a 3px amber
     rule that sits on the bar's bottom edge. */
  .stepper{display:flex;align-items:stretch;gap:2px}
  .step{display:flex;align-items:center;gap:8px;padding:0 10px;min-height:44px;color:var(--on-chrome-mut);border-bottom:3px solid transparent;border-top:3px solid transparent;cursor:pointer;transition:color .15s,border-color .15s;white-space:nowrap}
  .step:hover{color:var(--on-chrome)}
  .step.active{color:var(--on-chrome);font-weight:700;border-bottom-color:var(--lamp)}
  .step-num{display:none}
  .step-label{font-size:15px}
  a.step{text-decoration:none}
  /* A screen that has no route yet (task 04N): not a link, shown as off. */
  .step.unavailable{opacity:.5;cursor:default}
  .step.unavailable:hover{color:var(--on-chrome-mut)}

  /* Screens */
  .screen{display: block;padding:18px 0 40px}
  
  .screen-head{display:flex;justify-content:space-between;gap:20px;align-items:flex-start;margin-bottom:18px}
  .kicker{margin:0 0 4px;font-size:14px;color:var(--on-chrome-mut)}
  .title{font-family:var(--serif);font-weight:500;font-size:30px;line-height:1.15;margin:0 0 8px;color:var(--on-chrome)}
  /* **No measure of its own.** This carried `max-width:52ch`, a sound reading
     measure and the wrong rule here: the card under a lead runs the full width
     of `.wrap`, so every screen showed its opening sentence bunched in a narrow
     column beside empty space, then ran edge to edge just below it (run-through
     finding F4, 10/12/2026; the deposition build fixed the same thing in its
     own app.css). `.wrap` is the measure for the head and the body alike, and
     the head text takes the row so the chips on the right do not narrow it. */
  .lead{margin:0;color:var(--on-chrome-mut)}
  .screen-head > div:first-child{flex:1 1 auto;min-width:0}
  .ac{display:flex;flex-direction:column;gap:5px;align-items:flex-end;flex-shrink:0}
  .ac span{font-size:11.5px;color:var(--on-chrome-mut);border:1px dashed var(--chrome-3);border-radius:6px;padding:3px 8px;white-space:nowrap}
  .ac b{color:var(--lamp-text);font-weight:600}

  /* Buttons */
  .btn{border:1px solid var(--chrome-3);background:var(--chrome-2);border-radius:12px;padding:12px 18px;cursor:pointer;font-weight:500;display:inline-flex;align-items:center;gap:10px;transition:background .15s}
  .btn:hover{background:var(--btn-hover)}
  .btn.primary{background:var(--lamp);border-color:var(--lamp);color:var(--ink)}
  .btn.primary:hover{background:var(--lamp-hover)}
  .btn[disabled]{opacity:.45;cursor:not-allowed}
  .btn.block{width:100%;justify-content:center}
  .hint{font-size:13.5px;color:var(--on-chrome-mut);margin:10px 0 0}
  /* A refusal that belongs to no one field (sign-in, the lock-out) is still a
     refusal: the error colour, not the muted note colour. */
  .card > .hint[role=alert]{color:var(--error)}
  /* What an action did (run-through findings F1 and F5): a box in the
     success colour, like .keystatus, with a check, a title and the next step;
     .neutral for news that is not a success (a removed key). Never the muted
     .hint, which is how both were missed. */
  .notice{margin:14px 0 0;padding:14px 16px;border-radius:10px;color:var(--on-chrome);border:1px solid var(--chrome-3);border-left-width:4px}
  .notice.ok{background:var(--ok-wash);border-color:var(--ok-edge);border-left-color:var(--ok)}
  .notice-title{margin:0 0 4px;font-family:var(--serif);font-weight:600;font-size:18px;display:flex;gap:8px;align-items:center}
  .notice.ok .notice-title::before{content:"\2713";color:var(--ok);font-family:var(--sans);font-weight:700}
  .notice-line{margin:0;color:var(--on-chrome-mut)}
  .notice .btn{margin-top:14px}

  /* Library */
  .lib{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:28px;align-items:start}
  .doclist{margin:0;padding:0;list-style:none;border-top:1px solid var(--chrome-3)}
  .doc{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 18px;padding:16px 4px 14px;border-bottom:1px solid var(--chrome-3);cursor:pointer;background:transparent;border-left:0;border-right:0;border-top:0;width:100%;text-align:left;color:inherit}
  .doc:hover .doc-title{color:var(--lamp-text)}
  .doc-title{font-family:var(--serif);font-size:19px;font-weight:500;margin:0;transition:color .15s;overflow-wrap:anywhere}
  .doc-meta{font-size:13.5px;color:var(--on-chrome-mut);margin:0}
  .doc-pct{font-size:14px;color:var(--on-chrome-mut);align-self:start;padding-top:3px;white-space:nowrap}
  .doc-pct.done{color:var(--ok)}
  .doc-bar{grid-column:1/-1;height:3px;background:var(--chrome-3);border-radius:2px;overflow:hidden}
  .doc-bar.slider{overflow:visible}
  .doc-bar.slider .knob{width:12px;height:12px;margin:-6px 0 0 -6px}
  .doc-bar i{display:block;height:100%;background:var(--lamp);border-radius:2px}
  .doc.current{background:linear-gradient(90deg,var(--lamp-wash),transparent 60%)}
  .addbox{background:var(--chrome-2);border:1px solid var(--chrome-3);border-radius:var(--r);padding:18px}
  .addbox h3{margin:0 0 6px;font-family:var(--serif);font-weight:500;font-size:20px}
  .addbox p{margin:0 0 14px;color:var(--on-chrome-mut);font-size:14.5px}
  .types{display:flex;gap:6px;flex-wrap:wrap;margin-top:12px}
  .types span{font-size:12.5px;border:1px solid var(--chrome-3);border-radius:6px;padding:3px 8px;color:var(--on-chrome-mut)}
  .empty{display:none;text-align:center;color:var(--on-chrome-mut);padding:40px 0}
  .empty.on{display:block}
  /* A Library row is a link to its document (buyer decision, 2026-10-09): it
     keeps the mockup row's look, its title takes the lamp colour on hover as
     the rail's do, it washes while pressed, and the focus ring sits inside
     the row so the list's rules do not cut it. */
  .doc .doc-meta{grid-column:1}
  a.doc:active{background:var(--lamp-wash)}
  #lib a.doc:focus-visible{outline-offset:-2px}
  /* Add a document: the file input stays focusable, drawn as its label. */
  .filepick{position:relative}
  .filepick input{position:absolute;width:1px;height:1px;opacity:0;overflow:hidden}
  .filepick input:focus-visible + label{outline:2px solid var(--lamp-text);outline-offset:2px}
  .filepick input:disabled + label{opacity:.55;cursor:not-allowed}
  .chosen-x:disabled{opacity:.4;cursor:not-allowed}
  .chosen:not([hidden]){display:flex;align-items:center;gap:8px;margin:10px 0 0;font-size:14px;color:var(--on-chrome);overflow-wrap:anywhere}
  .chosen-x{border:0;background:transparent;color:var(--on-chrome-mut);font-size:20px;line-height:1;padding:2px 6px;cursor:pointer;border-radius:6px}
  .chosen-x:hover{background:var(--btn-hover)}
  #addBtn{margin-top:12px}
  /* The drop zone round Choose a file (run-through finding F9): dashed, lit
     while a file is held over it; a refused drop says why under it, in the
     error colour. */
  .dropzone{border:1.5px dashed var(--chrome-3);border-radius:12px;padding:14px;text-align:center;transition:background .15s,border-color .15s}
  .dropzone.over{border-color:var(--lamp-text);background:var(--lamp-wash)}
  .addbox .dropzone-line{margin:0 0 10px;font-size:14px}
  .addbox .drop-error{margin:8px 0 0;font-size:13.5px;color:var(--error)}

  /* Reader */
  .reader{display:grid;grid-template-columns:250px minmax(0,1fr);gap:26px;align-items:start}
  /* Held beside the page as it scrolls. Taller than the window, reader.js
     lowers its top so it scrolls up until its last document is in view, and
     only then holds (PR #44: the page follows the reading). */
  .rail{position:sticky;top:78px}
  .rail h3{margin:0 0 6px;font-size:14px;font-weight:500;color:var(--on-chrome-mut)}
  .rail .doclist .doc{padding:11px 6px 10px}
  .rail .doc-title{font-size:16px}
  .rail .doc-meta{display:none}
  /* The document being read (run-through finding F8): not a link, so no
     pointer and no hover colour; the three moves sit under its bar, the same
     icons as the transport at rail size, each the transport button's state. */
  .rail .doc.current{cursor:default}
  .rail .doc.current .doc-bar i{transition:width .5s}
  .rail .doc.current .doc-title{grid-column:1/-1}
  /* Under the current entry's section bar: the transport's own words. */
  .rail .doc-cap{grid-column:1/-1;margin:2px 0 0;font-size:12.5px;line-height:1.35;color:var(--on-chrome-mut)}
  .rail .doc.current:hover .doc-title{color:inherit}
  .rail-ctrls{grid-column:1/-1;display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:4px;margin-top:8px}
  /* The speed, in the player group under the three moves (Tim's review-copy
     check, 10/12/2026): the rail stays in view, so the speed does too. */
  .rail-speed{position:relative;flex-basis:100%;display:flex;justify-content:space-between;align-items:center;margin-top:6px;font-size:13.5px;color:var(--on-chrome-mut)}
  .rb{width:36px;height:36px;border-radius:50%;border:1px solid var(--chrome-3);background:var(--chrome-2);color:var(--on-chrome);display:grid;place-items:center;cursor:pointer;padding:0}
  .rb:hover:not(:disabled){background:var(--btn-hover)}
  .rb:disabled{opacity:.4;cursor:not-allowed}
  .rb svg{width:18px;height:18px;fill:currentColor}
  .rb.play{width:42px;height:42px;background:var(--lamp);border-color:var(--lamp);color:var(--ink)}
  .rb.play .ico-pause,.rb.play.on .ico-play{display:none}
  .rb.play.on .ico-pause{display:block}
  .page-wrap{position:relative}
  .page-head{display:flex;justify-content:space-between;gap:16px;align-items:flex-end;margin-bottom:12px}
  .page-head .kicker{margin-bottom:2px}
  .doc-h1{font-family:var(--serif);font-weight:500;font-size:24px;line-height:1.2;margin:0;color:var(--on-chrome)}
  .pref{border:1px solid var(--chrome-3);background:transparent;border-radius:100px;padding:7px 14px;cursor:pointer;color:var(--on-chrome);font-size:14px;display:inline-flex;gap:8px;align-items:center;white-space:nowrap;text-decoration:none}
  .pref:hover{border-color:var(--hover-edge)}
  .pref b{color:var(--lamp-text);font-weight:600}
  /* The reader's voice-and-speed pill is two controls (run-through finding
     F6): the outline is the group's, the voice a link, the speed a button
     that opens .speed-menu under it, right-aligned so it stays on a 320px
     screen. */
  .pref-group{position:relative;display:inline-flex;align-items:center;flex-shrink:0;border:1px solid var(--chrome-3);border-radius:100px;font-size:14px;color:var(--on-chrome-mut)}
  .pref-group .pref{border:0;border-radius:100px}
  .pref-group > a.pref{padding-right:4px}
  .pref-group .pref-speed{padding-left:6px;gap:5px;font:inherit;color:var(--on-chrome)}
  .pref-group .pref-speed:hover,.pref-group > a.pref:hover{background:var(--btn-hover)}
  /* A speed button beside the player's controls (the rail, the transport). */
  .speed-btn{border:1px solid var(--chrome-3);background:var(--chrome-2);border-radius:100px;min-height:36px;padding:0 12px;display:inline-flex;gap:6px;align-items:center;cursor:pointer;color:var(--on-chrome);font-size:14px;white-space:nowrap}
  .speed-btn:hover{background:var(--btn-hover)}
  .speed-btn b{color:var(--lamp-text);font-weight:600}
  .speed-ctl{position:relative;flex-shrink:0}
  .speed-menu{position:absolute;top:calc(100% + 6px);right:0;z-index:20;list-style:none;margin:0;padding:6px;min-width:110px;background:var(--chrome-2);border:1px solid var(--chrome-3);border-radius:12px;box-shadow:0 14px 40px -12px var(--shadow-deep)}
  .speed-menu button{display:flex;width:100%;justify-content:space-between;align-items:center;gap:10px;border:0;background:transparent;color:var(--on-chrome);font:inherit;font-size:14.5px;padding:9px 12px;border-radius:8px;cursor:pointer}
  .speed-menu button:hover,.speed-menu button:focus-visible{background:var(--btn-hover)}
  .speed-menu button[aria-checked="true"]{color:var(--lamp-text);font-weight:600}
  .speed-menu button[aria-checked="true"]::after{content:"\2713"}
  .page{background:var(--page);color:var(--ink);border-radius:var(--r);padding:34px 36px 40px;box-shadow:0 30px 80px -30px var(--shadow-deep),0 0 0 1px var(--page-edge) inset;font-family:var(--serif);font-size:19px;line-height:1.7;position:relative;overflow:hidden;min-height:420px}
  .page p{margin:0 0 1.1em;max-width:64ch}
  .page p:last-child{margin-bottom:0}
  /* The sentence being read (PR #44): a class on its span, which Safari
     always repaints (the Highlight API left the old one painted on an iPhone). */
  .s{border-radius:4px;transition:background .3s,box-shadow .3s;-webkit-box-decoration-break:clone;box-decoration-break:clone}
  .s.now{background:var(--lamp-soft);box-shadow:0 0 0 3px var(--lamp-soft)}
  /* A tap on a sentence reads from it; no grey flash on a phone. */
  #pageText{-webkit-tap-highlight-color:transparent;cursor:pointer}
  /* An estimated page's break (PR #44): the label is generated, so it is not
     text (selection and copying see none). A paragraph that carries on after
     a break inside it keeps its flow. */
  .page-break{position:relative;margin:26px 0;height:14px;text-align:center;font-family:var(--sans);font-size:12.5px;line-height:14px;color:var(--ink-mut);letter-spacing:.04em;-webkit-user-select:none;user-select:none}
  .page-break::after{content:"";position:absolute;left:0;right:0;top:50%;border-top:1px dashed var(--page-edge)}
  .page-break::before{content:attr(data-page);position:relative;z-index:1;background:var(--page);padding:0 10px}
  .page p.cont{margin-top:0}
  .ribbon{position:absolute;top:-4px;left:26px;width:14px;height:52px;background:var(--ribbon);clip-path:polygon(0 0,100% 0,100% 100%,50% 82%,0 100%)}
  .ribbon-note{position:absolute;top:10px;left:50px;font-family:var(--sans);font-size:12px;color:var(--ink-mut)}
  /* The restored place (ac-03): reader.js puts the ribbon in the margin on the
     place's first line and the note just above it (their top and left are
     set there), and underlines the sentence playback restarts from. */
  .ribbon.at-place{left:14px;width:12px;height:34px}
  .ribbon-note.at-place{white-space:nowrap;background:var(--page);padding:0 6px;border-radius:4px;line-height:1.5}
  .page .place{text-decoration:underline 2px var(--ribbon);text-underline-offset:5px}
  /* Room for the note: the place's first line is made taller upward by an empty
     inline block, so the note never covers the line above. */
  .page .place-lead{white-space:nowrap}
  .page .place-room{display:inline-block;width:0;height:2.4em;vertical-align:baseline}
  .page ::selection{background:var(--ribbon-soft)}
  .selbtn{position:absolute;right:22px;top:16px;display:none;background:var(--ink);color:var(--page);border:0;border-radius:100px;padding:9px 16px;font-family:var(--sans);font-size:14px;font-weight:500;cursor:pointer;box-shadow:0 10px 30px -10px var(--shadow)}
  .selbtn.show{display:inline-flex;gap:8px;align-items:center}
  .selhint{font-family:var(--sans);font-size:12.5px;color:var(--ink-mut);margin:18px 0 0;padding-top:12px;border-top:1px solid var(--page-edge)}

  /* Transport */
  .transport{margin-top:16px;background:var(--chrome-2);border:1px solid var(--chrome-3);border-radius:var(--r);padding:14px 18px 16px}
  .prog{display:flex;align-items:center;gap:12px;font-size:13.5px;color:var(--on-chrome-mut);margin-bottom:12px}
  .prog .bar{flex:1;height:5px;background:var(--chrome-3);border-radius:3px}
  .prog .bar i{display:block;height:100%;background:var(--lamp);width:62%;border-radius:3px;transition:width .5s}
  /* The bars are sliders over the whole document (PR #44): a 44px touch area
     around the line, a knob at the place, a bubble while dragging. */
  .slider{position:relative;cursor:pointer;touch-action:none;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}
  .slider::before{content:"";position:absolute;left:-6px;right:-6px;top:50%;height:44px;margin-top:-22px}
  .slider .knob{position:absolute;top:50%;width:16px;height:16px;margin:-8px 0 0 -8px;border-radius:50%;background:var(--lamp);box-shadow:0 1px 4px var(--shadow);pointer-events:none;transition:left .5s}
  .slider.dragging .knob{width:24px;height:24px;margin:-12px 0 0 -12px;box-shadow:0 0 0 8px var(--lamp-soft);transition:none}
  .slider.dragging i{transition:none}
  .slider .bubble{position:absolute;bottom:20px;transform:translateX(-50%);background:var(--ink);color:var(--page);font-family:var(--sans);font-size:13px;padding:5px 10px;border-radius:8px;white-space:nowrap;pointer-events:none;z-index:2}
  .slider:focus-visible{outline:2px solid var(--lamp-text);outline-offset:6px}
  /* What the bar measures, above it: "Page 3 of 40 · 12% of document", and
     the listening time at the right. */
  .prog-line{margin:0 0 6px;font-size:13.5px;color:var(--on-chrome-mut);white-space:nowrap;display:flex;justify-content:space-between;gap:12px}
  .prog-line .where{min-width:0;overflow:hidden;text-overflow:ellipsis}
  .prog-line .time{flex-shrink:0;font-variant-numeric:tabular-nums;color:var(--on-chrome)}
  .prog-line .pct{color:var(--on-chrome);font-weight:500}
  /* Back to reading (PR #44): shown when the reader scrolled away from the
     lit sentence; reader.js places it above the player bar. */
  .back-to{position:fixed;left:50%;bottom:24px;transform:translateX(-50%);z-index:40;display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:0 18px;border-radius:22px;border:0;background:var(--lamp);color:#23262F;font-family:var(--sans);font-size:15px;font-weight:600;cursor:pointer;box-shadow:0 8px 24px -8px var(--shadow-deep)}
  .back-to{white-space:nowrap}
  .back-to:hover{background:var(--lamp-hover)}
  .back-to[hidden]{display:none}
  /* The transport sits at the foot of the page (held at the foot of a phone's
     screen), so its speed menu opens upward. */
  .transport .speed-menu{top:auto;bottom:calc(100% + 6px)}
  /* The pill's menu opens over the phone's player bar (z-index 25), not
     under it (Gate 1 walkthrough, PR #44: covered at 320 px and sideways). */
  .pref-group .speed-menu{z-index:30}
  .ctrls{display:flex;align-items:center;justify-content:center;gap:10px}
  .tb{border:1px solid var(--chrome-3);background:transparent;border-radius:100px;height:48px;min-width:48px;padding:0 12px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:5px;font-size:13.5px;font-weight:500;color:var(--on-chrome);transition:background .15s}
  .tb:hover{background:var(--btn-hover)}
  .tb[disabled]{opacity:.4;cursor:not-allowed}
  .tb svg{width:20px;height:20px;fill:currentColor}
  .tb.play{width:68px;height:68px;border-radius:50%;background:var(--lamp);border-color:var(--lamp);color:var(--ink);margin:0 6px;box-shadow:var(--lamp-glow)}
  .tb.play:hover{background:var(--lamp-hover)}
  .tb.play svg{width:28px;height:28px}
  .tb.play .ico-pause{display:none}
  .tb.play.on .ico-play{display:none}
  .tb.play.on .ico-pause{display:block}
  .tb.play.busy{animation:pulse 1.2s ease-in-out infinite}
  @keyframes pulse{50%{box-shadow:0 0 0 12px var(--lamp-wash)}}
  .status{text-align:center;font-size:13px;color:var(--on-chrome-mut);margin-top:10px;min-height:1.4em}
  /* The reader (ac-12): the rail's documents are links, and why reading stopped
     shows above the page, or on a phone in the player bar (.bar-msg), where it
     stays in view (the status line is hidden on phones). */
  a.doc{text-decoration:none}
  /* A long unbroken title or word (a file name, a URL) wraps instead of
     widening the page past a phone's screen. */
  .page-head>div{min-width:0}
  .doc-h1,.page{overflow-wrap:anywhere}
  .reader-msg{margin:0 0 12px;padding:8px 12px;border-left:3px solid var(--ribbon);font-size:14.5px;line-height:1.5;color:var(--on-chrome)}
  .bar-msg{display:none}
  /* Three taps on it copy the playback log (reader.js): no text selection. */
  .prog-line{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none;touch-action:manipulation}
  /* The playback details, when they could not be copied: select and copy. */
  .log-panel:not([hidden]){display:flex;gap:8px;align-items:flex-start;margin:0 0 10px}
  .log-panel textarea{flex:1;min-width:0;font:12px/1.4 ui-monospace,monospace;color:var(--on-chrome);background:var(--chrome);border:1px solid var(--chrome-3);border-radius:8px;padding:6px}
  .log-panel .btn{flex-shrink:0;min-height:44px}
  .prog-line.noted > span{display:none}
  .prog-line.noted::after{content:attr(data-note);color:var(--on-chrome)}

  /* Voice & speed */
  /* min(): at 320px a 300px floor left a 4px right gutter (Gate 1 walkthrough, 10/13/2026). */
  .prefs{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr));gap:22px}
  .card{background:var(--chrome-2);border:1px solid var(--chrome-3);border-radius:var(--r);padding:20px}

  /* Form fields (sign-in, first run, Change password): each field full width
     under its own label, so the inputs line up and nothing reflows when the
     Required tag inside the label hides. */
  .field-row + .field-row{margin-top:14px}
  .field-row > label{display:block;margin-bottom:6px}
  .field-row input.tin{display:block;width:100%;box-sizing:border-box}
  /* Required clears once a field is filled; a rejected value draws in the
     error colour with its reason under the field (BMA UX conventions II).
     passwords.js and settings.js set is-filled and is-rejected; without
     script, bma_ui.css's validity rules still prompt. */
  .field-row.is-filled .field-required-tag,.field-row.is-filled .field-hint{display:none}
  .is-rejected input.tin,.is-rejected input.tin:invalid{border-color:var(--error)}
  .is-rejected input.tin:focus,.is-rejected input.tin:invalid:focus{box-shadow:0 0 0 .2rem color-mix(in srgb,var(--error) 25%,transparent)}
  .field-error{display:none;margin:6px 0 0;font-size:12.5px;color:var(--error)}
  .is-rejected .field-error{display:block}
  .card h3{margin:0 0 4px;font-family:var(--serif);font-weight:500;font-size:20px}
  .card .sub{margin:0 0 14px;color:var(--on-chrome-mut);font-size:14.5px}
  .voices{display:grid;gap:8px}
  .voice{display:grid;grid-template-columns:22px minmax(0,1fr) auto;gap:12px;align-items:center;padding:12px 14px;border:1px solid var(--chrome-3);border-radius:12px;background:transparent;cursor:pointer;text-align:left;color:inherit}
  .voice:hover{border-color:var(--hover-edge)}
  .voice.on{border-color:var(--lamp);background:var(--lamp-wash)}
  .voice .dot{width:18px;height:18px;border-radius:50%;border:2px solid var(--chrome-3)}
  .voice.on .dot{border-color:var(--lamp);background:var(--lamp);box-shadow:inset 0 0 0 3px var(--chrome-2)}
  .voice .nm{font-family:var(--serif);font-size:18px;font-weight:500}
  .voice .ch{font-size:13.5px;color:var(--on-chrome-mut)}
  .speeds{display:grid;grid-template-columns:repeat(5,1fr);gap:6px}
  .speed{border:1px solid var(--chrome-3);background:transparent;border-radius:10px;padding:14px 0;cursor:pointer;font-size:16px;font-weight:500;color:var(--on-chrome-mut)}
  .speed:hover{color:var(--on-chrome)}
  .speed.on{background:var(--lamp);border-color:var(--lamp);color:var(--ink)}
  .remember{margin:14px 0 0;font-size:13.5px;color:var(--on-chrome-mut);display:flex;gap:8px;align-items:center}
  .remember i{width:8px;height:8px;border-radius:50%;background:var(--ok);display:inline-block}

  /* The Install card in Settings */
  .install-how{margin-top:16px}
  .install-status{margin:16px 0 0;color:var(--on-chrome);font-weight:500}
  .install-how[hidden],.install-action[hidden]{display:none}
  .install-how ol{margin:0;padding-left:20px;color:var(--on-chrome-mut);line-height:1.6}
  .install-how ol b,.install-line b{color:var(--on-chrome);font-weight:500}
  .install-line{color:var(--on-chrome-mut);line-height:1.6;margin:0 0 8px}
  .install-address{overflow-wrap:anywhere}
  .install-card .install-btn{margin-top:16px;min-height:44px}
  .offline{margin-top:14px;font-size:13.5px;color:var(--on-chrome-mut)}

  /* Settings (sign-in and key, mirroring the deposition build) */
  .provider{display:flex;gap:6px;flex-wrap:wrap;margin-top:6px}
  .provider button{border:1px solid var(--chrome-3);background:transparent;border-radius:10px;padding:10px 16px;cursor:pointer;font-weight:500;color:var(--on-chrome-mut);display:inline-flex;gap:8px;align-items:center}
  .provider button.on{background:var(--page);color:var(--ink);border-color:var(--page)}
  .provider button[disabled]{cursor:not-allowed;opacity:.55}
  .provider .v2{font-size:11px;border:1px solid currentColor;border-radius:5px;padding:1px 6px}
  .keystatus{margin:16px 0 0;font-size:14.5px;color:var(--on-chrome);padding:12px 14px;border-radius:10px;background:var(--ok-wash);border:1px solid var(--ok-edge)}
  .keystatus.none{background:var(--lamp-wash);border-color:var(--lamp-edge)}
  .keyrow{display:flex;gap:8px;margin-top:6px}
  .field-row .keyrow{margin-top:0}
  .keyrow .btn{flex:none}
  .keyrow .btn.reveal{min-width:5.5em;text-align:center}
  .tin{flex:1;min-width:0;border:1px solid var(--chrome-3);background:var(--chrome);color:var(--on-chrome);border-radius:10px;padding:12px 14px;font:inherit}
  .tin::placeholder{color:var(--on-chrome-mut)}
  .keyactions{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}
  .signin-line{margin:0 0 14px;font-size:14.5px;color:var(--on-chrome-mut)}
  .signin-line b{color:var(--on-chrome);font-weight:500}
  .costnote{margin-top:22px;padding:14px;border:1px dashed var(--chrome-3);border-radius:10px;font-size:14px;color:var(--on-chrome-mut)}
  .costnote b{color:var(--on-chrome);font-weight:500}

  /* The footer sits outside .wrap, so it takes the same side padding. */
  .colophon{border-top:1px solid var(--chrome-3);margin-top:20px;padding:22px max(20px,env(safe-area-inset-right,0px)) 36px max(20px,env(safe-area-inset-left,0px));font-size:12.5px;color:var(--on-chrome-mut);display:flex;justify-content:space-between;flex-wrap:wrap;gap:8px}
  /* REVIEW_INSTANCE=1 only (base.html): our review copy says so on every page, so it is never mistaken for the buyer's. */
  .review-banner{background:var(--lamp-text);color:var(--chrome);text-align:center;font-size:13px;font-weight:600;padding:6px max(16px,env(safe-area-inset-right,0px)) 6px max(16px,env(safe-area-inset-left,0px))}

  /* Phone layout */
  @media (max-width:760px){
    /* 16px side gutters on a phone (BMA UX conventions), footer included. */
    .wrap,.colophon{padding-left:max(16px,env(safe-area-inset-left,0px));padding-right:max(16px,env(safe-area-inset-right,0px))}
    .masthead .chip{display:none}
    /* The phone's top bar (Tim's review-copy check, 10/12/2026): brand, the
       current screen's name, Menu. The menu is a panel just under the bar:
       the four links, each a 48px row, the current one washed amber and bold,
       then Sign out. Without script (no .menu-ready) the links are simply
       listed under the brand. */
    .wrap > .masthead{gap:6px;flex-wrap:nowrap}
    .wrap > .masthead:not(.menu-ready){flex-wrap:wrap}
    .masthead .brand{order:0;margin-right:0}
    .masthead .site-menu{order:0;flex-basis:100%;flex-direction:column;align-self:auto;padding:4px 0 10px}
    /* No taller than the screen under the bar (a phone on its side is 360px
       tall), scrolling inside, so Sign out can always be reached: the 96px is
       the 60px bar, the review copy's banner and a margin; vh where dvh is
       not known. */
    .masthead.menu-ready .site-menu{display:none;position:absolute;top:100%;left:0;right:0;padding:8px;max-height:calc(100vh - 96px);max-height:calc(100dvh - 96px);overflow-y:auto;overscroll-behavior:contain;background:var(--chrome-2);border:1px solid var(--chrome-3);border-radius:0 0 var(--r) var(--r);box-shadow:0 18px 40px -16px var(--shadow-deep)}
    .masthead.menu-ready.menu-open .site-menu{display:flex}
    .masthead.menu-ready .site-menu > *{flex-shrink:0}
    .masthead .nav-here{display:block;flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13.5px;color:var(--on-chrome-mut)}
    .masthead .menu-btn{display:inline-flex;align-items:center;gap:8px;flex-shrink:0;min-height:44px;padding:8px 12px;font-size:15px;white-space:nowrap}
    .menu-btn .ico-close,.menu-btn[aria-expanded="true"] .ico-menu{display:none}
    .menu-btn[aria-expanded="true"] .ico-close{display:block}
    .stepper{flex-direction:column;gap:2px}
    .step{min-height:48px;padding:0 14px;border:0;border-radius:10px;color:var(--on-chrome)}
    .step-label{font-size:16px}
    .step.active{background:var(--lamp-wash);box-shadow:inset 3px 0 0 var(--lamp)}
    /* 16px either side of the rule, so a tap that misses Settings does not
       sign out. */
    .masthead .menu-signout{display:block;flex-shrink:0;margin-top:16px;padding-top:16px;border-top:1px solid var(--chrome-3)}
    .menu-signout .btn{display:flex;width:100%;min-height:48px;justify-content:center}
    .title{font-size:25px}
    .screen-head{flex-direction:column;gap:10px}
    .ac{flex-direction:row;flex-wrap:wrap;align-items:flex-start}
    .lib{grid-template-columns:1fr}
    .addbox{order:-1}
    .reader{grid-template-columns:1fr}
    /* The column may be narrower than the bar's controls row wants, so the
       in-flow bar never widens the page past a 320px screen. */
    .page-wrap{min-width:0}
    .rail{display:none}
    .page{padding:26px 20px 30px;font-size:18px;border-radius:12px}
    .ribbon{left:12px}
    .ribbon-note{left:34px}
    .ribbon.at-place{left:4px}
    /* The player bar stays at the foot of the screen while the page scrolls
       under it, edge to edge. Sticky to the bottom of the reading column, not
       fixed to the screen: on Tim's iPhone, in the installed app, a fixed bar
       rode up to mid-screen when he scrolled up (review copy, 10/13/2026).
       The negative margins are the .wrap gutters, so it still spans the
       screen; after the last line it simply follows the text. */
    .transport{position:sticky;bottom:0;margin:16px calc(-1 * max(16px,env(safe-area-inset-right,0px))) 0 calc(-1 * max(16px,env(safe-area-inset-left,0px)));border-radius:18px 18px 0 0;border-left:0;border-right:0;border-bottom:0;padding:12px max(16px,env(safe-area-inset-right,0px)) calc(12px + env(safe-area-inset-bottom,0px)) max(16px,env(safe-area-inset-left,0px));z-index:25;box-shadow:0 -20px 40px -20px var(--shadow)}
    .tb{min-width:44px;height:44px;padding:0 8px}
    .transport .speed-btn{min-height:44px}
    .tb.play{width:62px;height:62px}
    .status{display:none}
    /* Except while the audio is being prepared (PR #42): a Play tap can wait
       4-5 s for the first chunk, and the Pause icon alone says nothing then. */
    .status.waiting{display:block;margin-top:8px}
    /* Touch targets at least 44px (UX conventions I): the speed choices and
       the voice-and-speed pill by the title. */
    .speed-menu button{min-height:44px}
    .pref-group .pref{min-height:44px}
    .page-wrap > .reader-msg{display:none}
    .bar-msg:not([hidden]){display:block;margin:0 0 10px;padding:6px 10px}
  }
  /* A phone on its side (a short screen): the bar is compact, the three
     moves beside the progress row and the stop reason on one line, so the
     page keeps most of the 360px and the bar starts within the screen. */
  @media (max-width:760px) and (max-height:500px){
    .transport{display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:12px;align-items:center;padding-top:6px;padding-bottom:calc(6px + env(safe-area-inset-bottom,0px))}
    .transport > .bar-msg,.transport > .prog-line,.transport > .log-panel{grid-column:1/-1}
    .bar-msg:not([hidden]){margin:0 0 4px;padding:3px 10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
    .transport .prog{margin:0}
    .tb{min-width:44px;height:44px}
    .tb.play{width:48px;height:48px}
    .transport .speed-btn{min-height:44px}
    .ctrls{gap:6px}
  }
  /* Below 375px the Menu button is its icon alone (its aria-label and title
     name it), so the current screen's name fits beside it. */
  @media (max-width:374px){
    .masthead .menu-btn{min-width:44px;justify-content:center;padding:8px 10px}
    .masthead .menu-btn .menu-word{display:none}
  }
  /* The longest name, "Voice and speed", fits whole at 320px. */
  @media (max-width:349px){
    .wrap > .masthead{gap:4px}
    .masthead .nav-here{font-size:12.5px}
  }
  @media (prefers-reduced-motion:reduce){
    .s,.prog .bar i,.rail .doc.current .doc-bar i,.tb.play,.slider .knob{transition:none;animation:none}
  }


/* Anchor-button corrections (universal). Mockups use <button class="btn"> (default
   display:inline-block, centered, no underline), but builds render download/nav actions
   as <a class="btn"> -- an <a> defaults to display:inline + underlined, so padded or
   wrapping labels paint as overlapping line-boxes that clip the text and show an
   underline. These make every scaffolded build's anchor-buttons render like the mockup
   button. (Surfaced on the Malindi FP&A build, 2026-06-01.) */
.btn { display: inline-block; text-align: center; text-decoration: none; }

/* v2: a control shown in its final position but not yet wired (mockup drew it beyond AC scope). */
.is-v2 { opacity: 0.55; pointer-events: none; position: relative; }
.v2-badge {
  display: inline-block; font-family: 'JetBrains Mono', monospace; font-size: 9px;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--paper);
  background: var(--ink-faint); padding: 1px 6px; margin-left: 8px; vertical-align: middle;
}
