@font-face{
    font-family:"Rashi";
    src:url("fonts/PFTRashi.ttf") format("truetype");
    font-display:swap;
    unicode-range:U+0307-0308,U+0590-05FF,U+200C-2010,U+20AA,U+25CC,U+FB1D-FB4F;
  }
  @font-face{
    font-family:"Heilig";
    src:url("fonts/OT Heilig.ttf") format("truetype");
    font-display:swap;
    unicode-range:U+0307-0308,U+0590-05FF,U+200C-2010,U+20AA,U+25CC,U+FB1D-FB4F;
  }
  @font-face{
    font-family:"Siddur";
    src:url("fonts/OT Sid Hei.ttf") format("truetype");
    font-display:swap;
    unicode-range:U+0307-0308,U+0590-05FF,U+200C-2010,U+20AA,U+25CC,U+FB1D-FB4F;
  }
  @font-face{
    font-family:"Hadassa";
    src:url("fonts/OT_HadasahVF.ttf") format("truetype");
    font-weight:400 700;
    font-display:swap;
    unicode-range:U+0307-0308,U+0590-05FF,U+200C-2010,U+20AA,U+25CC,U+FB1D-FB4F;
  }
  @font-face{
    font-family:"SBL Hebrew";
    src:url("fonts/SBLHebrew.woff") format("woff");
    font-weight:400;
    font-style:normal;
    font-display:swap;
    unicode-range:U+0307-0308,U+0590-05FF,U+200C-2010,U+20AA,U+25CC,U+FB1D-FB4F;
  }
  @font-face{
    font-family:"Shofar";
    src:url("fonts/ShofarRegular.ttf") format("truetype");
    font-weight:400;
    font-style:normal;
    font-display:swap;
    unicode-range:U+0307-0308,U+0590-05FF,U+200C-2010,U+20AA,U+25CC,U+FB1D-FB4F;
  }
  @font-face{
    font-family:"Shofar";
    src:url("fonts/ShofarDemi-Bold.ttf") format("truetype");
    font-weight:600 700;
    font-style:normal;
    font-display:swap;
    unicode-range:U+0307-0308,U+0590-05FF,U+200C-2010,U+20AA,U+25CC,U+FB1D-FB4F;
  }
  :root{
    --ink:#2b2118;
    --parch:#f4ecdc;
    --gold:#9a7b3f;
    --line:#cdbd9a;
    --frame:#ffffff;
    /* Header height owned by CSS: .55rem×2 padding + 2.3rem buttons + 1px
       border + status-bar inset. The header pins its height to this and the
       panes pad by it, so they can never disagree — even if a stale cached
       app.js never runs (the old JS-published value left the panes padded
       60px under a ~103px header on notched iPhones). env() keeps it
       responsive to rotation without any JS. */
    --hdr-h:calc(3.4rem + 1px + env(safe-area-inset-top, 0px));
    /* Interface (chrome) font — home tiles, header, menus, settings, toasts
       and banners. Only the ENGLISH/Latin UI text changes to system sans-serif;
       Hebrew is deliberately left untouched. VilnaHebrew leads the stack and
       (via its Hebrew-only unicode-range) claims every Hebrew glyph, keeping it
       in the same serif as before, so Latin characters are the only ones that
       fall through to the sans-serif system fonts. */
    --ui-font:"VilnaHebrew",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  }
  html.theme-dark{
    --ink:#ece2cc;
    --parch:#1a1611;
    --gold:#c9a85f;
    --line:#3a3024;
    --frame:#0f0d09;
  }
  /* ---------- Curated palettes ----------
     A second axis on top of the Light/Dark toggle. Each palette just
     re-tints the same five tokens, so nothing downstream needs new styles.
     "Parchment" is the default and lives in :root / .theme-dark above (no
     data-palette attribute). Sky and Coral override the tokens when
     html[data-palette=…] is set; the .theme-dark pair supplies their dark
     variant. Keep the dark --ink values here in sync with PALETTE_INK_RANGE
     in app.js (and the FOUC map in index.html), which drives the dark-mode
     Text Brightness slider. */
  html[data-palette="sky"]{
    --ink:#16303f;
    --parch:#e6f2fb;
    --gold:#1878b0;
    --line:#c2ddef;
    --frame:#ffffff;
  }
  html[data-palette="sky"].theme-dark{
    --ink:#d4e9f6;
    --parch:#0d1922;
    --gold:#48b2e6;
    --line:#213340;
    --frame:#081119;
  }
  html[data-palette="coral"]{
    --ink:#3a2420;
    --parch:#fdeee7;
    --gold:#d64e2a;
    --line:#f6cdbc;
    --frame:#fffaf8;
  }
  html[data-palette="coral"].theme-dark{
    --ink:#f3ddd2;
    --parch:#201310;
    --gold:#f47e5c;
    --line:#40261f;
    --frame:#150b09;
  }
  html[data-palette="sage"]{
    --ink:#1f3226;
    --parch:#e9f2ea;
    --gold:#3f8c5c;
    --line:#c6ddc9;
    --frame:#fbfefb;
  }
  html[data-palette="sage"].theme-dark{
    --ink:#d6ecdb;
    --parch:#101a13;
    --gold:#5cb57e;
    --line:#23342a;
    --frame:#0a120d;
  }
  html[data-palette="lavender"]{
    --ink:#2d2440;
    --parch:#efeaf8;
    --gold:#7a5cc0;
    --line:#d8cdee;
    --frame:#fdfbff;
  }
  html[data-palette="lavender"].theme-dark{
    --ink:#e2d9f4;
    --parch:#16111f;
    --gold:#a488e0;
    --line:#2e2640;
    --frame:#0d0913;
  }
  html[data-palette="rose"]{
    --ink:#3d1f2c;
    --parch:#fdeaf1;
    --gold:#d64e83;
    --line:#f6c9da;
    --frame:#fff8fb;
  }
  html[data-palette="rose"].theme-dark{
    --ink:#f6d9e5;
    --parch:#1f1017;
    --gold:#ec6ea0;
    --line:#3c2530;
    --frame:#150a0f;
  }
  html.theme-dark .accordion-body img,
  html.theme-dark #pdfWrap img{ filter:invert(1) hue-rotate(180deg) brightness(var(--img-brightness,1)); }
  /* Custom scrollbars on the scrollable areas. The OS default scrollbar is
     near-invisible against the white reader/page background in light mode
     (it only showed up in dark mode), so paint a gold thumb that reads
     clearly in both themes. */
  .home,#frameWrap,.hayom,.chalukas{
    scrollbar-width:thin;
    scrollbar-color:var(--gold) transparent;
  }
  .home::-webkit-scrollbar,
  #frameWrap::-webkit-scrollbar,
  .hayom::-webkit-scrollbar,
  .chalukas::-webkit-scrollbar{ width:10px;height:10px; }
  .home::-webkit-scrollbar-track,
  #frameWrap::-webkit-scrollbar-track,
  .hayom::-webkit-scrollbar-track{ background:transparent; }
  .home::-webkit-scrollbar-thumb,
  #frameWrap::-webkit-scrollbar-thumb,
  .hayom::-webkit-scrollbar-thumb{
    background:var(--gold);
    border-radius:8px;
  }
  /* Shiur scans are licensed content — block long-press save/callout, drag,
     and text-selection on the rendered page images across all views. */
  #pdfWrap img,
  .accordion-body img{
    -webkit-touch-callout:none;
    -webkit-user-select:none;
    user-select:none;
    -webkit-user-drag:none;
    pointer-events:none;
  }
  *{box-sizing:border-box;margin:0;padding:0;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
  /* Controlled rem root — 1rem = 16px on every device.
     Reader sizes (heFontSize, enFontSize, …) are already stored as rem in
     localStorage and applied via --he-size / --en-size. Without a fixed root,
     phone OS text-size settings change what those rem values render as, so the
     same saved +/- preference looks small on one phone and large on another.
     Stored preferences stay valid on the existing 0.25rem step grid; only the
     absolute pixel mapping is stabilized. */
  html{
    font-size:16px;
    -webkit-text-size-adjust:100%;
    text-size-adjust:100%;
  }
  html,body{height:100%}
  body{timeline-scope:--shiur-scroll;
    font-family:var(--ui-font);
    background:var(--parch);
    color:var(--ink);
    height:100vh; height:100svh;
    overflow:hidden;
    display:flex;
    flex-direction:column;
  }
  /* wrapper that fills the space below the header; sections stack inside it */
  #screenWrap{
    flex:1;
    min-height:0;
    position:relative;
    overflow:hidden;
  }
  /* swappable body areas — absolutely stacked so home can sit behind reader
     during the swipe-back animation without a layout flash */
  .body{
    position:absolute;
    inset:0;
    display:none;
    flex-direction:column;
  }
  .body.active{display:flex}

  /* ---------- HOME ---------- */
  .home{
    overflow-y:auto;
    padding:calc(1.4rem + var(--hdr-h, 60px)) .8rem 2rem;
    align-items:center;
  }
  .tiles{
    width:100%;
    max-width:560px;
    display:flex;
    flex-direction:column;
    align-self:stretch;
    gap:.6rem;
    /* Center with auto margins — not justify-content:center on a flex-grown
       child. Centered flex overflow clips equally top/bottom under the
       absolute header. Auto margins collapse to 0 when the list is taller
       than the pane. Portrait phones switch to .home-fit (equal slots that
       fill the pane above Edit) via fitHomeTiles(). */
    margin-block:auto;
    margin-inline:auto;
  }
  .tile{
    font-family:var(--ui-font);
    background:var(--frame);
    color:var(--ink);
    border:1.5px solid var(--gold);
    border-radius:12px;
    padding:.7rem 1rem;
    flex:0 0 auto;
    min-height:3.1rem;
    display:flex;flex-direction:column;
    align-items:center;justify-content:center;
    gap:.25rem;
    cursor:pointer;
    box-shadow:0 4px 14px rgba(0,0,0,.18);
    transition:transform .12s, box-shadow .12s, background .12s;
    -webkit-tap-highlight-color:transparent;
  }
  .tile:active{transform:scale(.97)}
  .tile .main{
    font-size:1.55rem;
    line-height:1.1;
    font-weight:400;
  }
  .tile .sub{
    font-size:.82rem;
    color:var(--gold);
    line-height:1.1;
  }
  /* Two-column wrap on wider phones / tablets — tiles still flex-fit the row. */
  @media (min-width:520px){
    .tiles{
      flex-flow:row wrap;
    }
    .tile{
      flex:1 1 calc(50% - .5rem);
      max-width:calc(50% - .5rem);
    }
  }
  /* Portrait phone: equally divide the pane among visible buttons (same height
     with or without a subtitle) and size type via --home-* vars. Edit stays
     pinned under the stretchable tile list. */
  .home.home-fit{
    overflow:hidden;
    padding:calc(.55rem + var(--hdr-h, 60px)) .8rem .45rem;
  }
  .home.home-fit .tiles{
    flex:1 1 auto;
    min-height:0;
    margin-block:0;
    gap:var(--home-gap, .5rem);
  }
  .home.home-fit .tile{
    flex:1 1 0;
    min-height:0;
    max-height:none;
    /* Identical padding for every tile — subtitle must not grow the slot. */
    padding:var(--home-pad-y, .7rem) 1rem;
    border-radius:var(--home-radius, 12px);
    overflow:hidden;
  }
  .home.home-fit .tile .main{font-size:var(--home-main, 1.55rem)}
  .home.home-fit .tile .sub{font-size:var(--home-sub, .82rem)}
  .home.home-fit .home-edit-btn{
    margin-top:.4rem;
    margin-bottom:.1rem;
  }
  /* Edit mode adds side gutters so there's empty page to drag-scroll the list
     (edit-mode tiles use touch-action:none for dragging, so a scroll gesture
     can only start in the gutter). */
  @media (max-width:519px){
    body.editing-tiles .home{padding-left:2.75rem;padding-right:2.75rem}
    body.editing-tiles .tiles{gap:.6rem}
    body.editing-tiles .tile{
      padding:.7rem 1rem;min-height:3.1rem;border-radius:12px;
      flex:0 0 auto;max-height:none;overflow:visible;
    }
    body.editing-tiles .tile .main{font-size:1.55rem}
    body.editing-tiles .tile .sub{font-size:.82rem}
  }

  /* ---------- Home-button edit mode (iPhone-style) ---------- */
  .edit-title{
    order:2;
    font-weight:700;
    font-size:1.02rem;
    color:var(--ink);
  }
  .edit-title[hidden]{display:none}
  /* Hide the day navigator while editing so a stray day-change can't reflow
     the grid mid-drag. */
  body.editing-tiles .center-stack .date-nav{display:none}

  .tile-edit{
    position:relative;
    cursor:grab;
    animation:tile-wobble .32s ease-in-out infinite alternate;
  }
  /* touch-action must also sit on the hit-tested descendants (the big Hebrew
     text fills the tile) — otherwise a touch that lands on a child span is
     claimed by the browser for scrolling and our drag gets pointercancel'd. */
  .tile-edit, .tile-edit *{touch-action:none}
  .tile-edit:nth-child(2n){animation-delay:-.14s;animation-duration:.30s}
  .tile-edit:nth-child(3n){animation-delay:-.23s;animation-duration:.36s}
  .tile-edit.tile-off{opacity:.42}
  .tile-edit.dragging{
    animation:none;
    box-shadow:0 10px 28px rgba(0,0,0,.32);
    opacity:.96;z-index:3;cursor:grabbing;
    transition:box-shadow .1s;   /* no transform transition — it must track the finger 1:1 */
  }
  .tile-edit .tile-grip{
    position:absolute;left:.7rem;top:50%;transform:translateY(-50%);
    display:grid;place-items:center;color:var(--muted,#999);pointer-events:none;
  }
  .tile-grip .icon{width:1.15rem;height:1.15rem}
  /* Raised specificity so it wins over the later base `.switch{position:relative}`. */
  .tile-edit .tile-switch{
    position:absolute;right:.7rem;top:50%;transform:translateY(-50%);
  }
  @keyframes tile-wobble{
    from{transform:rotate(-.5deg)}
    to{transform:rotate(.5deg)}
  }
  @media (prefers-reduced-motion:reduce){
    .tile-edit{animation:none}
  }
  /* Faded entry point into home-button editing — always on the home list. */
  .home-edit-btn{
    order:2;flex:none;
    margin:.85rem auto 0;
    background:none;border:none;
    color:var(--ink);opacity:.36;
    font-family:inherit;font-size:.82rem;font-weight:600;
    cursor:pointer;padding:.4rem .7rem;
    display:inline-flex;align-items:center;justify-content:center;gap:.32rem;
    -webkit-tap-highlight-color:transparent;
    transition:opacity .15s;
  }
  .home-edit-btn .icon{width:.9rem;height:.9rem;display:block}
  .home-edit-btn:active{opacity:.55}
  .home-edit-btn[hidden],
  body.editing-tiles .home-edit-btn{display:none}
  .edit-reset{
    order:3;flex:none;
    margin:.5rem auto 0;
    background:none;border:none;
    color:var(--gold);font-family:inherit;font-size:.85rem;font-weight:600;
    cursor:pointer;padding:.4rem .8rem;
    -webkit-tap-highlight-color:transparent;
  }
  .edit-reset:active{opacity:.55}
  .edit-reset[hidden]{display:none}

  /* Native shells own Home chrome. The PWA is unchanged without these classes.
     Reader HTML header stays visible under html.native-shell-reader. */
  html.native-shell-home #home,
  html.native-shell-home #appHeader,
  html.native-shell-pending #home,
  html.native-shell-pending #appHeader{
    visibility:hidden !important;
  }

  /* Config opened from Native Home: HTML popover + existing backdrop over a
     transparent WebView so the live native buttons stay visible underneath. */
  html.native-shell-config,
  html.native-shell-config body{
    background:transparent !important;
  }
  html.native-shell-config body::before{display:none !important}
  html.native-shell-config #screenWrap,
  html.native-shell-config #resumeBanner,
  html.native-shell-config #updateToast{
    visibility:hidden !important;
  }
  html.native-shell-config #appHeader{
    background:transparent !important;
    border-color:transparent !important;
    box-shadow:none !important;
  }
  html.native-shell-config #appHeader > :not(#settingsPop){
    visibility:hidden !important;
  }
  /* Anchor to the viewport — absolute-under-header drifts when the rest of
     the header is visibility:hidden on a transparent overlay WebView. */
  html.native-shell-config #settingsPop{
    position:fixed;
    top:calc(env(safe-area-inset-top, 0px) + 3.4rem);
    right:.45rem;
    left:auto;
  }

  /* ---------- READER ---------- */
  header{
    display:flex;
    align-items:center;
    gap:.5rem;
    padding:.55rem .7rem;
    padding-top:calc(.55rem + env(safe-area-inset-top));
    border-bottom:1px solid var(--line);
    flex:none;
    height:var(--hdr-h);
    /* Smart header: overlays the panes and slides via transform so the
       motion is composited — animating layout (margin/height) reflows
       the scrolling content mid-gesture and feels janky. The panes pad
       their tops by var(--hdr-h) so content starts below the header.
       JS drives the translateY 1:1 with scroll deltas (no transition
       while tracking); .hdr-snap enables the transition only for the
       settle animation when a gesture ends. */
    position:absolute;
    top:0;left:0;right:0;
    z-index:1000;
    background:var(--parch);
    transform:translateY(calc(-1 * var(--hdr-off, 0px)));
    will-change:transform;
  }
  /* body.hdr-snap enables the settle transition on everything that follows
     the header offset (the header itself and the reading-progress bar). */
  .hdr-snap header,
  .hdr-snap #readingProgress{
    transition:transform .25s cubic-bezier(.4,0,.2,1);
  }
  /* In installed-PWA standalone mode the OS status bar overlays the page;
     this fixed strip stops content from showing through it while the header
     is hidden. Height collapses to 0 in a normal browser tab. */
  body::before{
    content:'';
    position:fixed;
    top:0;left:0;right:0;
    height:env(safe-area-inset-top, 0px);
    background:var(--parch);
    z-index:9;
    pointer-events:none;
  }
  @media (prefers-reduced-motion:reduce){
    .hdr-snap header,
    .hdr-snap #readingProgress{transition:none}
  }
  /* Home pinned to the visual LEFT, tools (classes + settings) to the visual
     RIGHT (RTL-safe). .hdr-tools carries the former .hdr-settings margin so
     the headphones and cog stay adjacent as a pair. */
  .hdr-menu{order:3; margin-inline-start:auto}
  .hdr-tools{
    order:1;
    margin-inline-end:auto;
    display:flex;
    align-items:center;
    gap:.1rem;
    flex:none;
  }
  .hdr-settings,.hdr-classes,.hdr-pin{/* order inherited from .hdr-tools */}
  .center-stack{
    order:2;
    display:flex;flex-direction:column;align-items:center;
    flex:1;min-width:0;
  }
  .date-nav{
    display:flex;
    align-items:center;
    gap:.5rem;
  }
  /* An author `display` beats the UA stylesheet's [hidden], so hiding the date
     nav from JS needs this. חלוקת הש״ס is the one view with no date to move. */
  .date-nav[hidden]{display:none}
  .date{
    font-size:1.3rem;
    font-weight:700;
    text-align:center;
    color:var(--ink);
    min-width:9.5ch;
    line-height:1.1;
    cursor:pointer;
    -webkit-tap-highlight-color:transparent;
    touch-action:manipulation;
  }
  /* Lock the date-nav arrows to their authored direction — without this,
     the RTL context mirrors «/» so they visually point the wrong way. */
  .date-nav button{
    display:grid;place-items:center;
    padding:0;
    direction:ltr;
    unicode-bidi:isolate;
  }
  /* subtle highlight when viewing a day other than today */
  .date.off-today{
    color:var(--gold);
    border-bottom:1px solid var(--gold);
  }
  header button{
    font-family:inherit;
    font-size:1.4rem;
    background:none;
    border:none;
    color:var(--gold);
    width:2.3rem;height:2.3rem;
    border-radius:0;
    cursor:pointer;
    line-height:1;
    transition:opacity .15s;
    flex:none;
    -webkit-tap-highlight-color:transparent;
    touch-action:manipulation;
  }
  header button:active{opacity:.5;background:none;color:var(--gold)}
  #settingsBtn,
  #menuBtn,
  #classesBtn,
  #pinBtn{display:inline-flex;align-items:center;justify-content:center}
  #settingsBtn[hidden],
  #menuBtn[hidden]{display:inline-flex;visibility:hidden}
  /* External classes link — styled like a header button; truly removed when
     hidden so it doesn't reserve a gap beside the cog. */
  #classesBtn{
    text-decoration:none;
    color:var(--gold);
    width:2.3rem;height:2.3rem;
    border-radius:0;
    -webkit-tap-highlight-color:transparent;
    touch-action:manipulation;
  }
  #classesBtn:active{opacity:.5}
  #classesBtn[hidden]{display:none}
  #classesBtn .icon{width:1.25rem;height:1.25rem}
  #pinBtn{
    color:var(--gold);
    width:2.3rem;height:2.3rem;
    -webkit-tap-highlight-color:transparent;
    touch-action:manipulation;
  }
  #pinBtn:active{opacity:.5}
  #pinBtn[hidden]{display:none}
  #pinBtn .icon{width:1.2rem;height:1.2rem}
  /* Reader/Hayom: replace the cog with a compact אA type badge (Vilna + Arial). */
  .settings-type-badge{
    display:none;
    align-items:baseline;
    justify-content:center;
    gap:.1em;
    box-sizing:border-box;
    padding:.12rem .3rem .1rem;
    border:1px solid currentColor;
    border-radius:6px;
    line-height:1;
    color:var(--gold);
    pointer-events:none;
  }
  #settingsBtn.show-type .settings-btn-svg{display:none}
  #settingsBtn.show-type .settings-type-badge{display:inline-flex}
  .settings-type-he{
    font-family:var(--ui-font);
    font-size:1.14rem;
    font-weight:400;
  }
  .settings-type-en{
    font-family:Helvetica,sans-serif;
    font-size:.92rem;
    font-weight:400;
    margin-left:-2px;
  }
  /* icon helper */
  .icon{display:block;flex:none;width:1.15rem;height:1.15rem}
  /* Home button: match אA badge optical size; stroke stays thin via SVG stroke-width */
  #menuBtn .icon{width:1.5rem;height:1.5rem}
  .icon-btn-sm .icon{width:.85rem;height:.85rem}
  .chev .icon{width:.85em;height:.85em;display:inline-block;vertical-align:-.1em}

  /* settings popover — anchored just below the header, near the gear button */
  .settings-pop{
    position:absolute;
    top:calc(100% + 6px);
    right:.45rem;
    width:min(320px,calc(100vw - 1rem));
    max-height:60dvh;
    z-index:9999;
    background:var(--frame);
    border:1px solid var(--line);
    border-radius:12px;
    box-shadow:0 8px 32px rgba(0,0,0,.28);
    display:flex;
    flex-direction:column;
    opacity:0;
    transform:translateY(-6px) scale(.97);
    transform-origin:top right;
    transition:opacity .18s ease,transform .18s ease;
    pointer-events:none;
  }
  .settings-pop.open{
    opacity:1;
    transform:none;
    pointer-events:auto;
  }
  .settings-pop[hidden]{display:none}
  .settings-sheet-scroll{
    flex:1;
    min-height:0;
    overflow-y:auto;
    padding:.6rem 1.2rem .9rem;
    scrollbar-width:thin;
    scrollbar-color:var(--gold) transparent;
  }
  .settings-sheet-scroll::-webkit-scrollbar{width:6px}
  .settings-sheet-scroll::-webkit-scrollbar-track{background:transparent}
  .settings-sheet-scroll::-webkit-scrollbar-thumb{background:var(--gold);border-radius:3px}
  .settings-sheet-fade{
    position:absolute;
    left:0;right:0;bottom:0;
    height:3.5rem;
    background:linear-gradient(to bottom,transparent,var(--frame));
    pointer-events:none;
    border-radius:0 0 12px 12px;
    opacity:1;
    transition:opacity .2s;
  }
  .settings-sheet-fade.hidden-fade{opacity:0}
  /* ---------- Settings popover tabs (per-view popover) ----------
     A two-up segmented tab bar pinned above the scroll area: the view's own
     name on the left, General on the right. Hidden on the home popover, which
     shows a single flat list. */
  .settings-tabs{
    display:flex;
    flex:none;
    margin:.6rem 1.2rem 0;
    border:1px solid var(--gold);
    border-radius:8px;
    overflow:hidden;
  }
  .settings-tabs[hidden]{display:none}
  .settings-tab{
    flex:1;
    min-width:0;
    border:none;
    background:var(--frame);
    color:var(--ink);
    font-family:inherit;
    font-size:.88rem;
    font-weight:700;
    line-height:1.2;
    padding:.5rem .55rem;
    cursor:pointer;
    white-space:nowrap;
    overflow:hidden;
    text-overflow:ellipsis;
    -webkit-tap-highlight-color:transparent;
    touch-action:manipulation;
    transition:.12s;
  }
  .settings-tab + .settings-tab{border-inline-start:1px solid var(--line)}
  .settings-tab.active{background:var(--gold);color:var(--parch)}
  /* Untabbed (home / view with no own settings): panels flow together. Tabbed:
     only the active tab's panel shows. */
  .settings-pop.tabbed .settings-panel{display:none}
  .settings-pop.tabbed[data-active-tab="view"] .settings-panel[data-panel="view"]{display:block}
  .settings-pop.tabbed[data-active-tab="general"] .settings-panel[data-panel="general"]{display:block}
  /* Invisible full-screen tap-catcher shown while the settings popover is open.
     A tap anywhere over the page content dismisses the popover — including empty
     areas that never emit a document `click` on iOS Safari. It sits just below
     the header (z-index 1000, which owns the popover's stacking context) so the
     popover and the gear toggle stay above it and remain tappable. */
  #settingsOverlay{position:fixed;inset:0;z-index:999;display:none}
  #settingsOverlay.open{display:block}
  .settings-row{margin-bottom:.7rem}
  .settings-row:last-child{margin-bottom:0}
  .settings-row[hidden]{display:none}
  .settings-row#settingsAccount{text-align:center}
  /* Compact Reset — bottom of each settings tab; not full-width. */
  .settings-reset-row{
    display:flex;justify-content:flex-end;
    margin-top:.85rem;padding-top:.65rem;border-top:1px solid var(--line);
  }
  .settings-reset-row[hidden]{display:none}
  .settings-reset{
    flex:none;width:auto;margin:0;
    font-family:inherit;font-size:.72rem;font-weight:700;
    padding:.32rem .8rem;
    background:transparent;color:var(--ink);
    border:1px solid color-mix(in srgb,var(--gold) 38%,var(--line));
    border-radius:6px;cursor:pointer;
    -webkit-tap-highlight-color:transparent;touch-action:manipulation;
  }
  .settings-reset:active{opacity:.55}
  /* .seg sets display:flex, which beats the UA [hidden] rule in some WebKits
     (notably iOS Safari). Keep every layout/seg control truly hidden when the
     attribute is set — otherwise a leftover Seg (e.g. Hayom Yom's) leaks into
     every other view's Layout popover. */
  .seg[hidden]{display:none}
  .settings-group[hidden]{display:none}
  /* English-language settings rows (Hayom: theme, toggles, birthday, family)
     read left-to-right in a plain UI sans-serif rather than the site's Hebrew serif. */
  #settingsPop [dir="ltr"],
  #bdayOverlay .picker{
    font-family:var(--ui-font);
  }
  [dir="ltr"] .switch input:checked + .switch-track .switch-thumb{transform:translateX(1.25rem)}
  .settings-label{
    font-size:.9rem;color:var(--ink);opacity:.8;margin-bottom:.4rem;text-align:center;
  }
  /* Each font-size stepper shows the letter it resizes: the small glyph
     shrinks, the large glyph grows. Hebrew rows carry א, English rows A, and
     the "All Text Size" stepper carries the paired אA of the header config
     badge (the one control that moves both scripts at once). Vilna claims the
     alef via its unicode-range; Helvetica gives the Latin A its own weight —
     mirroring .settings-type-he / .settings-type-en on the badge. */
  .sz-glyph{line-height:1;display:inline-block}
  .sz-he{font-family:var(--ui-font);font-weight:400}
  .sz-en{font-family:Helvetica,Arial,sans-serif;font-weight:400}
  /* Optical centering: Vilna reserves descent room the alef never uses, so a
     line-box-centered alef reads high — nudge the single Hebrew glyph down to
     the row's true middle (em-relative, so it tracks font-size). Helvetica's A
     is already balanced by the flex centering and needs no nudge. The paired
     אA of the global stepper aligns on its own baseline and is left alone. */
  .sz-glyph.sz-he{transform:translateY(.08em)}
  .sz-glyph.sz-he.sz-sm{font-size:1.02rem}
  .sz-glyph.sz-he.sz-lg{font-size:1.72rem}
  .sz-glyph.sz-en.sz-sm{font-size:.82rem}
  .sz-glyph.sz-en.sz-lg{font-size:1.42rem}
  .sz-pair{display:inline-flex;align-items:baseline;justify-content:center;gap:.08em;line-height:1}
  .sz-pair .sz-en{margin-left:-1px}
  .sz-pair.sz-sm .sz-he{font-size:.92rem}
  .sz-pair.sz-sm .sz-en{font-size:.72rem}
  .sz-pair.sz-lg .sz-he{font-size:1.42rem}
  .sz-pair.sz-lg .sz-en{font-size:1.06rem}
  .seg{
    display:flex;border:1px solid var(--gold);border-radius:8px;overflow:hidden;
  }
  .seg button{
    flex:1;width:auto;height:auto;border:none;border-radius:0;
    font-size:.95rem;font-weight:700;
    padding:.5rem .4rem;
    background:var(--frame);color:var(--ink);
    transition:.12s;
  }
  .seg button + button{border-inline-start:1px solid var(--line)}
  .seg button.active{background:var(--gold);color:var(--parch)}
  /* ---------- Palette picker (swatch chips) ----------
     A wrapping three-per-row chip grid in the home-screen settings popover.
     Each chip previews its palette's paper / ink / gold as a fixed mini colour
     bar (light-mode identity, set inline in the markup) so the choice reads
     the same whatever theme is active. */
  .pal-chips{display:flex;flex-wrap:wrap;gap:.5rem}
  .pal-chips button{
    flex:1 1 calc(33.333% - .5rem);height:40px;padding:3px;cursor:pointer;transition:.12s;
    background:var(--frame);border:1px solid var(--line);border-radius:9px;
  }
  .pal-chips .pal-sw{
    display:flex;width:100%;height:100%;border-radius:5px;overflow:hidden;
  }
  .pal-chips .pal-sw span{flex:1}
  .pal-chips button.active{border-color:var(--gold);box-shadow:inset 0 0 0 2px var(--gold)}
  /* ---------- READER ---------- */
  .reader{flex-direction:column}
  /* Small right-side gutter so reader content (text lines / page images)
     doesn't butt up against the native overlay scrollbar iOS draws at the
     right edge. */
  #frameWrap{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;padding-top:var(--hdr-h, 60px);padding-right:2px;background:var(--frame);scroll-timeline:--shiur-scroll block}
  /* Tanya mode pager: horizontal snap between Original / דבר מלכות / HE.
     Each pane scrolls vertically on its own. When pinch-zoomed, .zoom-locked
     freezes the horizontal axis so pan stays inside the active page. */
  #frameWrap.tanya-modes{
    overflow:hidden;
    padding-top:0;
    padding-right:0;
  }
  #frameWrap.tanya-modes #zoomSurface{display:none}
  .tanya-carousel{
    display:flex;
    flex-direction:row;
    width:100%;
    height:100%;
    overflow-x:auto;
    overflow-y:hidden;
    scroll-snap-type:x mandatory;
    scroll-padding:0;
    -webkit-overflow-scrolling:touch;
    overscroll-behavior-x:contain;
    background:var(--frame);
  }
  .tanya-carousel[hidden]{display:none}
  .tanya-carousel.zoom-locked{overflow-x:hidden}
  .tanya-pane{
    flex:0 0 100%;
    width:100%;
    height:100%;
    overflow-x:hidden;
    overflow-y:auto;
    scroll-snap-align:start;
    scroll-snap-stop:always;
    padding-top:var(--hdr-h, 60px);
    padding-right:2px;
    box-sizing:border-box;
    -webkit-overflow-scrolling:touch;
    overscroll-behavior-y:contain;
  }
  .tanya-zoom{width:100%;transform-origin:0 0;will-change:transform}
  .tanya-pdf{display:flex;flex-direction:column;align-items:stretch;min-height:100%;max-width:968px;width:100%;margin-inline:auto;position:relative}
  .tanya-pdf img{display:block;width:100%}
  .tanya-pdf img + img{border-top:1px solid var(--line)}
  .tanya-pane #textWrap{max-width:968px;width:100%;margin-inline:auto}
  #readingProgress{
    position:fixed;
    top:calc(var(--hdr-h, 60px) - 1px);
    left:0;right:0;
    height:2px;pointer-events:none;z-index:11;overflow:hidden;
    display:none;
    background:var(--frame);
    /* Follows the header's bottom edge 1:1, but the min() clamp stops it at
       the top of the screen (below the safe-area strip in standalone mode)
       so the progress bar stays visible while the header is hidden. */
    transform:translateY(calc(-1 * min(var(--hdr-off, 0px), var(--hdr-h, 60px) - env(safe-area-inset-top, 0px) - 1px)));
    will-change:transform;
  }
  body:has(#reader.active) #readingProgress{display:block}
  #readingProgress::after{
    content:'';position:absolute;inset:0;
    background:var(--gold);opacity:.55;
    transform-origin:left;transform:scaleX(0);
    animation:read-progress linear both;
    animation-duration:auto;
    animation-timeline:--shiur-scroll;
  }
  @keyframes read-progress{from{transform:scaleX(0)}to{transform:scaleX(1)}}
  /* Sync / content load indicator — top + bottom shimmer while day content,
     layout switches, or /api sync are in flight. */
  #syncLoader{
    position:fixed;
    left:0;right:0;
    top:0;bottom:0;
    z-index:40;
    pointer-events:none;
    overflow:visible;
    background:transparent;
    opacity:0;
    transition:opacity .2s ease;
    padding:0;
    box-sizing:border-box;
  }
  #syncLoader.is-on{opacity:1}
  #syncLoader::before,
  #syncLoader::after{
    content:'';
    position:absolute;
    left:0;right:0;
    height:3px;
    background:linear-gradient(
      90deg,
      transparent 0%,
      color-mix(in srgb, var(--gold) 35%, transparent) 35%,
      var(--gold) 50%,
      color-mix(in srgb, var(--gold) 35%, transparent) 65%,
      transparent 100%
    );
    background-size:40% 100%;
    background-repeat:no-repeat;
    animation:sync-loader-slide 1.1s ease-in-out infinite;
    opacity:.85;
  }
  #syncLoader::before{
    top:calc(var(--hdr-h, 60px) - 1px);
    transform:translateY(calc(-1 * min(var(--hdr-off, 0px), var(--hdr-h, 60px) - env(safe-area-inset-top, 0px) - 1px)));
  }
  #syncLoader::after{
    bottom:env(safe-area-inset-bottom, 0px);
  }
  @keyframes sync-loader-slide{
    from{background-position:-40% 0}
    to{background-position:140% 0}
  }
  @media (prefers-reduced-motion: reduce){
    #syncLoader::after{animation:none;background-position:50% 0;opacity:.45}
  }
  /* Sticky scroll breadcrumb — same slide-with-header behavior as
     #readingProgress (see comment above it), docked just below the progress
     line. Only shown once JS has determined there's a passed heading to show. */
  #textBreadcrumb{
    display:none;
    position:fixed;
    top:calc(var(--hdr-h, 60px) + 1px);
    left:0;right:0;z-index:10;
    padding:.3rem 1rem;
    font-family:var(--he-font, inherit);
    font-size:.72rem;
    background:var(--frame);
    border-bottom:1px solid var(--line);
    opacity:0;
    transition:opacity .18s ease;
    transform:translateY(calc(-1 * min(var(--hdr-off, 0px), var(--hdr-h, 60px) - env(safe-area-inset-top, 0px) - 1px)));
    will-change:transform;
    pointer-events:none;
  }
  body:has(#reader.active) #textBreadcrumb{display:flex}
  body:has(#reader.active) #textBreadcrumb.crumb-visible{opacity:1}
  /* Multi-body shiurim: bar is tappable for the quick-jump menu. */
  #textBreadcrumb.crumb-has-nav{
    pointer-events:auto;
    cursor:pointer;
    gap:.15rem .25rem;
  }
  #textBreadcrumb.crumb-has-nav:active{background:color-mix(in srgb, var(--ink) 4%, var(--frame))}
  .crumb-row{
    display:flex;flex-wrap:wrap;justify-content:center;align-items:baseline;
    row-gap:.1rem;
  }
  .crumb-seg{color:var(--gold);opacity:.75}
  .crumb-seg.crumb-current{color:var(--ink);opacity:1;font-weight:600}
  .crumb-sep{color:var(--gold);opacity:.4;margin:0 .35em;font-size:.85em}
  .crumb-nav-chev{
    display:inline-flex;align-items:center;justify-content:center;
    margin-inline-start:.15rem;
    color:var(--gold);
    opacity:.7;
    transition:transform .18s ease, opacity .18s ease;
  }
  .crumb-nav-chev .icon{width:.7rem;height:.7rem}
  #textBreadcrumb.crumb-menu-open .crumb-nav-chev{transform:rotate(180deg);opacity:1}
  .crumb-menu{
    position:fixed;
    left:50%;
    transform:translateX(-50%);
    z-index:12;
    box-sizing:border-box;
    min-width:min(16rem, 86vw);
    max-width:min(22rem, 92vw);
    max-height:min(16rem, 50vh);
    overflow-x:hidden;
    overflow-y:auto;
    background:var(--parch);
    border:1px solid var(--gold);
    border-radius:10px;
    box-shadow:0 8px 22px rgba(0,0,0,.22);
    scrollbar-width:thin;
    scrollbar-color:var(--gold) transparent;
  }
  .crumb-menu[hidden]{display:none}
  .crumb-menu-opt{
    display:flex;align-items:center;gap:.55rem;width:100%;
    background:none;border:none;border-bottom:1px solid var(--line);
    padding:.55rem .75rem;cursor:pointer;color:var(--ink);
    font-family:var(--he-font, inherit);font-size:.9rem;text-align:start;
  }
  .crumb-menu-opt:last-child{border-bottom:none}
  .crumb-menu-opt:hover,
  .crumb-menu-opt:focus-visible{background:color-mix(in srgb, var(--gold) 14%, transparent);outline:none}
  .crumb-menu-opt.active{background:color-mix(in srgb, var(--gold) 22%, transparent);font-weight:600}
  .crumb-menu-label{flex:1;min-width:0;line-height:1.3}
  .crumb-menu-check{
    flex:0 0 auto;display:inline-flex;color:var(--gold);
  }
  .crumb-menu-check .icon{width:.85rem;height:.85rem}
  @media(prefers-color-scheme:dark){
    .crumb-menu{background:var(--frame)}
  }
  /* #zoomSurface is a bare transform wrapper with no height of its own, so a
     percentage height inside it has nothing to resolve against and collapses —
     min-height on the surface doesn't help, since only a *definite* height
     makes a child's percentage resolve. The two children that need to fill the
     frame therefore size off the viewport directly (same expression
     #textWrap.biurim-mode uses). --hdr-h is a constant; the auto-hiding header
     slides via --hdr-off, so this doesn't move when the header retracts. */
  #zoomSurface{width:100%;transform-origin:0 0;will-change:transform}
  #pdfWrap{display:flex;flex-direction:column;align-items:stretch;min-height:calc(100dvh - var(--hdr-h, 60px));max-width:968px;width:100%;margin-inline:auto;position:relative}
  #pdfWrap[hidden]{display:none}
  #pdfWrap img{display:block;width:100%}
  #pdfWrap img + img{border-top:1px solid var(--line)}
  /* PDF fallback (Google viewer iframe) — an iframe with an unresolvable
     height:100% falls back to its 150px intrinsic size, not to the frame. */
  #viewer{display:block;width:100%;height:calc(100dvh - var(--hdr-h, 60px));border:none;background:var(--frame)}
  #viewer[hidden]{display:none}
  .pdf-error{padding:2.4rem 1.2rem;text-align:center;color:var(--ink);opacity:.7;font-size:1rem}

  /* animated placeholder shown while the shiur fetch is in-flight */
  .page-loader{
    flex:1;
    width:100%;
    background:var(--frame);
    position:relative;
    overflow:hidden;
  }
  .page-loader::after{
    content:'';
    position:absolute;
    inset:0;
    background:linear-gradient(
      90deg,
      transparent 0%,
      rgba(154,123,63,.18) 50%,
      transparent 100%
    );
    transform:translateX(-100%);
    animation:page-shimmer 1.6s ease-in-out infinite;
  }
  @keyframes page-shimmer{
    from{transform:translateX(-100%)}
    to{transform:translateX(100%)}
  }

  /* update-available toast */
  .update-toast{
    position:fixed;
    left:50%;
    bottom:1.1rem;
    transform:translateX(-50%);
    z-index:20;
    direction:ltr;
    display:flex;
    align-items:center;
    gap:.85rem;
    max-width:92vw;
    background:var(--frame);
    color:var(--ink);
    border:1px solid var(--gold);
    border-radius:12px;
    box-shadow:0 8px 26px rgba(0,0,0,.3);
    padding:.7rem .7rem .7rem 1rem;
    font-family:var(--ui-font);
    font-size:.92rem;
  }
  .update-toast[hidden]{display:none}
  .update-toast button{
    font-family:inherit;
    font-size:.88rem;
    font-weight:700;
    background:var(--gold);
    color:var(--parch);
    border:none;
    border-radius:8px;
    width:auto;height:auto;
    padding:.45rem 1rem;
    cursor:pointer;
    flex:none;
    line-height:1.1;
    -webkit-tap-highlight-color:transparent;
    touch-action:manipulation;
    transition:opacity .15s;
  }
  .update-toast button:active{opacity:.6}

  /* ---------- Toasts ----------
     A bottom-centred stack of floating notices, same theme as the update
     toast. Two flavours, both built by showToast() in app.js: self-dismissing
     ones count the wait down with a hairline progress bar; sticky ones carry a
     × to close. First user: the "what's new" notice on an installed app's
     refresh onto a newer version. */
  .toast-host{
    position:fixed;
    left:50%;
    bottom:calc(1.1rem + env(safe-area-inset-bottom, 0px));
    transform:translateX(-50%);
    z-index:21;
    display:flex;
    flex-direction:column;
    align-items:stretch;
    gap:.5rem;
    width:max-content;
    max-width:92vw;
    pointer-events:none;
  }
  .toast-host:empty{display:none}
  .toast{
    position:relative;
    overflow:hidden;
    direction:ltr;
    display:flex;
    align-items:flex-start;
    gap:.5rem;
    background:var(--frame);
    color:var(--ink);
    border:1px solid var(--gold);
    border-radius:12px;
    box-shadow:0 8px 26px rgba(0,0,0,.3);
    padding:.7rem .8rem .85rem 1rem;
    font-family:var(--ui-font);
    pointer-events:auto;
    opacity:0;
    transform:translateY(.5rem);
    transition:opacity .22s ease, transform .22s ease;
  }
  .toast.show{opacity:1;transform:translateY(0)}
  .toast.hide{opacity:0;transform:translateY(.5rem)}
  .toast-body{flex:1 1 auto;min-width:0;font-size:.92rem;line-height:1.34}
  .toast-line{margin:0}
  .toast-line + .toast-line{margin-top:.3rem}
  .toast-tag{font-weight:700;color:var(--gold)}
  .toast-group-title{margin:0 0 .3rem;font-weight:700;color:var(--gold);font-size:.9rem}
  .toast-item{margin:.28rem 0 0;padding-inline-start:.9rem;position:relative}
  .toast-item::before{
    content:"";position:absolute;inset-inline-start:.08rem;top:.6em;
    width:.3rem;height:.3rem;border-radius:50%;background:var(--gold);opacity:.75;
  }
  .toast-close{
    flex:none;
    display:inline-flex;align-items:center;justify-content:center;
    width:1.7rem;height:1.7rem;margin:-.15rem -.25rem 0 0;
    padding:0;background:transparent;color:var(--gold);
    border:none;border-radius:50%;cursor:pointer;
    -webkit-tap-highlight-color:transparent;touch-action:manipulation;
    transition:opacity .15s;
  }
  .toast-close:active{opacity:.5}
  .toast-close .icon{width:1.05rem;height:1.05rem}
  /* Countdown for self-dismissing toasts: the inner bar scales from full to
     empty over the toast's lifetime. */
  .toast-progress{position:absolute;left:0;right:0;bottom:0;height:3px;background:transparent}
  .toast-progress > i{display:block;height:100%;width:100%;background:var(--gold);opacity:.5;transform-origin:left center}
  @media (prefers-reduced-motion: reduce){
    .toast{transition:opacity .01s}
    .toast-progress > i{transition:none !important}
  }

  /* Resume-where-you-left-off banner (see showResumeBanner in app.js). A
     full-width bar flush to the bottom — "Today is" and the date button sit
     inline and centred; the × is on that same row, right-aligned, in the
     content box so home-indicator padding cannot drop it. Equal 1fr tracks
     keep the pair centred. No ellipsis. The chalukas offer reuses this class. */
  .resume-banner{
    position:fixed;
    left:0;
    right:0;
    bottom:0;
    top:auto;
    width:100%;
    max-width:none;
    transform:translateY(100%);
    z-index:19;
    display:grid;
    grid-template-columns:minmax(1.9rem, 1fr) auto auto minmax(1.9rem, 1fr);
    align-items:center;
    column-gap:.5rem;
    background:var(--frame);
    color:var(--ink);
    text-align:center;
    border:solid var(--gold);
    border-width:1px 0 0;
    border-radius:0;
    box-shadow:0 -6px 18px rgba(0,0,0,.18);
    padding:.55rem max(.15rem, env(safe-area-inset-right, 0px)) calc(.55rem + env(safe-area-inset-bottom, 0px)) max(.15rem, env(safe-area-inset-left, 0px));
    font-family:var(--ui-font);
    opacity:0;
    pointer-events:none;
    transition:opacity .2s ease, transform .2s ease;
  }
  .resume-banner.show{
    opacity:1;
    pointer-events:auto;
    transform:none;
  }
  .resume-banner[hidden]{display:none}
  .resume-text{
    grid-column:2;
    font-size:.95rem;
    line-height:1.3;
    text-align:center;
    white-space:normal;
    overflow:visible;
  }
  .resume-jump{
    grid-column:3;
    display:inline-flex;
    align-items:center;
    gap:.2rem;
    font-family:inherit;
    font-size:.95rem;
    font-weight:700;
    background:var(--gold);
    color:var(--parch);
    border:none;
    border-radius:999px;
    padding:.4rem .9rem;
    cursor:pointer;
    line-height:1.1;
    -webkit-tap-highlight-color:transparent;
    touch-action:manipulation;
    transition:opacity .15s;
  }
  .resume-jump:active{opacity:.6}
  .resume-jump .icon{width:1.05em;height:1.05em}
  .resume-close{
    grid-column:4;
    justify-self:end;
    display:inline-flex;
    align-items:center;
    justify-content:center;
    width:1.9rem;height:1.9rem;
    padding:0;
    background:transparent;
    color:var(--gold);
    border:none;
    border-radius:50%;
    cursor:pointer;
    -webkit-tap-highlight-color:transparent;
    touch-action:manipulation;
    transition:opacity .15s;
  }
  .resume-close:active{opacity:.5}
  .resume-close .icon{width:1.15rem;height:1.15rem}

  /* Install prompt — a bottom-centred banner shown to browser (non-installed)
     users only; see the install block in app.js. Same theme as the update
     toast, with an optional second row of manual Home-Screen steps for iOS. */
  .install-banner{
    position:fixed;
    left:50%;
    bottom:calc(1.1rem + env(safe-area-inset-bottom, 0px));
    transform:translateX(-50%) translateY(1rem);
    z-index:18;
    direction:ltr;
    display:flex;
    flex-direction:column;
    gap:.55rem;
    width:max-content;
    max-width:92vw;
    background:var(--frame);
    color:var(--ink);
    border:1px solid var(--gold);
    border-radius:12px;
    box-shadow:0 8px 26px rgba(0,0,0,.3);
    padding:.7rem .7rem .7rem 1rem;
    font-family:var(--ui-font);
    opacity:0;
    pointer-events:none;
    transition:opacity .2s ease, transform .2s ease;
  }
  .install-banner.show{
    opacity:1;
    pointer-events:auto;
    transform:translateX(-50%) translateY(0);
  }
  .install-banner[hidden]{display:none}
  .install-main{
    display:flex;
    align-items:center;
    gap:.85rem;
  }
  .install-text{
    font-size:.92rem;
    line-height:1.25;
    flex:0 1 auto;
    min-width:0;
  }
  .install-action{
    font-family:inherit;
    font-size:.88rem;
    font-weight:700;
    background:var(--gold);
    color:var(--parch);
    border:none;
    border-radius:8px;
    width:auto;height:auto;
    padding:.45rem 1rem;
    cursor:pointer;
    flex:none;
    line-height:1.1;
    white-space:nowrap;
    -webkit-tap-highlight-color:transparent;
    touch-action:manipulation;
    transition:opacity .15s;
  }
  .install-action:active{opacity:.6}
  .install-close{
    display:inline-flex;
    align-items:center;
    justify-content:center;
    flex:none;
    width:1.9rem;height:1.9rem;
    padding:0;
    background:transparent;
    color:var(--gold);
    border:none;
    border-radius:50%;
    cursor:pointer;
    -webkit-tap-highlight-color:transparent;
    touch-action:manipulation;
    transition:opacity .15s;
  }
  .install-close:active{opacity:.5}
  .install-close .icon{width:1.05rem;height:1.05rem}
  .install-steps{
    font-size:.86rem;
    line-height:1.35;
    color:var(--ink);
    opacity:.85;
    padding-inline-end:.3rem;
  }
  .install-steps[hidden]{display:none}
  .install-share{
    display:inline-block;
    width:1.05em;height:1.05em;
    vertical-align:-.18em;
    color:var(--gold);
  }

  /* picker */
  .overlay{
    position:fixed;inset:0;
    background:rgba(20,14,6,.55);
    display:none;
    align-items:center;justify-content:center;
    z-index:10000;
  }
  .overlay.open{display:flex}
  .picker{
    background:var(--parch);
    border:1px solid var(--gold);
    border-radius:10px;
    padding:1.2rem;
    width:min(92vw,360px);
    box-shadow:0 12px 40px rgba(0,0,0,.35);
  }
  .picker h2{
    font-size:1.2rem;font-weight:700;
    text-align:center;margin-bottom:1rem;color:var(--gold);
  }
  .picker label{
    display:block;font-size:.85rem;margin:.6rem 0 .25rem;color:var(--ink);
  }
  .picker select,.picker input[type="text"]{
    width:100%;
    font-family:inherit;font-size:1.1rem;
    padding:.5rem;
    background:var(--frame);
    border:1px solid var(--line);
    border-radius:6px;
    color:var(--ink);
    color-scheme:light dark;
  }
  .picker input[type="text"],#bdayDay{direction:rtl}
  .picker .actions{
    display:flex;gap:.6rem;margin-top:1.2rem;
  }
  .picker .actions button{
    flex:1;width:auto;height:auto;border-radius:6px;
    font-size:1rem;padding:.6rem;
  }
  .picker .actions #bdaySave{background:var(--gold);color:var(--parch);border:none}
  .picker .actions #bdaySave:active{opacity:.6}
  .picker .actions #bdayCancel{background:none;color:var(--ink);border:1px solid var(--line)}

  /* Quiet, and out of the way of the text: the download is background work and
     should read as background work. */
  /* Set apart, not shouted: the quoted Gemara reads as the heading of the
     comment the way the printed page has it. */
  .dibbur-hamaschil{font-weight:700}

  .chal-sync-status{
    position:fixed;
    left:50%;
    bottom:calc(.55rem + env(safe-area-inset-bottom));
    transform:translateX(-50%);
    z-index:14;
    width:min(60vw, 12rem);
    height:1.15rem;
    border:1px solid var(--gold);
    border-radius:999px;
    background:var(--frame);
    overflow:hidden;
    pointer-events:none;
    display:flex;
    align-items:center;
    justify-content:center;
  }
  .chal-sync-fill{
    position:absolute;
    inset:0 auto 0 0;
    background:var(--gold);
    opacity:.28;
    transition:width .3s ease;
  }
  .chal-sync-pct{
    position:relative;
    font-family:var(--ui-font);
    font-size:.72rem;
    font-variant-numeric:tabular-nums;
    color:var(--gold);
  }

  /* The header label is a control for חלוקת הש״ס — it opens the portion — so it
     is given the shape of one: a chevron that turns when the menu is open, and
     a surface that reads as tappable. */
  .date.chal-nav{
    display:inline-flex;
    align-items:center;
    gap:.3rem;
    padding:.1rem .5rem .1rem .35rem;
    border:1px solid var(--line);
    border-radius:999px;
    cursor:pointer;
    -webkit-tap-highlight-color:transparent;
  }
  .date.chal-nav:active{opacity:.6}
  .date.chal-nav.crumb-menu-open{border-color:var(--gold)}
  .chal-nav-text{unicode-bidi:isolate}
  .chal-nav-chev{
    width:.72em;height:.72em;
    color:var(--gold);
    transition:transform .15s;
    flex:none;
  }
  .date.chal-nav.crumb-menu-open .chal-nav-chev{transform:rotate(180deg)}

  /* The portion's dapim, dropped from the header. A long portion runs to 350
     amudim, so they tile rather than stack — a single column would be a scroll
     as long as the masechta. */
  .chal-jump{
    display:grid;
    grid-template-columns:repeat(auto-fill, minmax(3.6rem, 1fr));
    gap:.25rem;
    padding:.45rem;
    max-width:min(24rem, 94vw);
  }
  /* A perek's name spans the grid, so its dapim read as belonging to it. */
  .chal-jump-head{
    grid-column:1 / -1;
    padding:.45rem .3rem .2rem;
    color:var(--gold);
    font-size:.82rem;
    font-weight:700;
    border-top:1px solid var(--line);
  }
  .chal-jump-head:first-child{border-top:none;padding-top:.1rem}
  .chal-jump .chal-jump-item{
    border-bottom:none;
    border-radius:7px;
    padding:.4rem .2rem;
    font-size:.95rem;
    /* Laid out rather than text-aligned: the amud mark is a separate span so it
       always sits left of the numeral, and the pair centres as one. */
    display:flex;
    align-items:baseline;
    justify-content:center;
    gap:.12em;
    direction:ltr;
    unicode-bidi:isolate;
  }
  .chal-jump-amud{font-variant-numeric:tabular-nums;opacity:.85}
  .chal-jump-num{unicode-bidi:isolate}
  .chal-jump .chal-jump-item.is-current{
    background:var(--gold);
    color:var(--frame);
    font-weight:700;
  }

  /* An author display rule on .seg buttons would beat [hidden]; this keeps
     the taamim button genuinely gone for sources that have none. */
  .seg button[hidden]{display:none}

  /* מתני׳ / גמ׳ — the two halves of a daf, set apart the way a printed page
     does it: bolder, slightly larger, with air after so the eye catches the
     switch without a label having to say so. */
  .daf-opener{
    font-weight:700;
    font-size:1.08em;
    letter-spacing:.02em;
    color:var(--gold);
    margin-inline-end:.35em;
    unicode-bidi:isolate;
  }

  /* ---------- The masechta as one continuous scroll ---------- */
  /* Where the streamer watches for the reader reaching an edge. Never seen:
     one pixel so it has a box to intersect with, and out of the way of taps. */
  .chal-edge{display:block;height:1px;margin:0;pointer-events:none}

  /* Paragraph flow, tightened. The reader's default 1.2rem is set for segments
     that are whole thoughts — a Rambam halachah, a Tanya paragraph. Sefaria
     cuts a daf far finer than that, so at the shared spacing a sugya arrives as
     a column of widely spaced fragments rather than as an argument. */
  .chal-stream:not(.chal-flow-inline) .text-segment{margin-bottom:.5rem}
  .chal-stream:not(.chal-flow-inline) .text-segment.swipe-seg,
  .chal-stream:not(.chal-flow-inline) .text-segment.below-seg{margin-bottom:.45rem}

  /* Where a boundary marker parks. Zero, and deliberately so: a sticky offset
     is measured from its scrollport's *padding* box, and #frameWrap already
     carries padding-top:var(--hdr-h) to clear the header. Setting this to the
     header height as well parks the marker a full header down into the text,
     where its opaque background slices through the line above it. */
  .chal-stream{--chal-sticky-top:0px}
  /* Split Pane's top pane is its own scrollport, and two things differ there.
     It carries .7rem of its own top padding, which a zero offset would park the
     marker below — leaving a strip of daf scrolling past above it. And it sits
     *below* the header rather than under it: #frameWrap keeps its padding-top
     while locked, so a retracting header never moves this pane, and a marker
     that rode up on --hdr-off would slide off its own text. */
  #textWrap.biurim-mode .chal-stream{--chal-sticky-top:-.7rem}
  #textWrap.biurim-mode .chal-daf-head{transform:none}

  /* A perek is a real division of the masechta, so it breaks either flow with a
     header — it is the thing anyone actually navigates by. */
  .chal-perek-head{
    font-family:var(--he-font);
    font-size:1.15rem;
    font-weight:700;
    color:var(--gold);
    text-align:center;
    margin:1.8rem 0 .9rem;
    padding-bottom:.35rem;
    border-bottom:1px solid var(--line);
    /* Ends the paragraph it lands in, which is what "breaks the flow" means. */
    display:block;
    clear:both;
  }
  .chal-perek-head:first-child{margin-top:.2rem}

  /* Paragraph flow: the daf keeps a heading, and it sticks — with the whole
     masechta in one scroll it is a boundary marker you can still see from the
     middle of the daf, not a title printed once at the top of a render. */
  .chal-daf-head{
    position:sticky;
    top:var(--chal-sticky-top, 0px);
    z-index:4;
    font-family:var(--he-font);
    font-size:1rem;
    font-weight:700;
    color:var(--gold);
    text-align:center;
    margin:1.3rem 0 .8rem;
    padding:.3rem 0;
    background:var(--frame);
    border-bottom:1px solid color-mix(in srgb, var(--gold) 32%, transparent);
    /* Rides up with the header when it retracts, exactly as the breadcrumb
       does. Parked flush under a header that then slides away, it would
       otherwise leave a strip of the daf showing above it. */
    transform:translateY(calc(-1 * min(var(--hdr-off, 0px), var(--hdr-h, 60px) - env(safe-area-inset-top, 0px) - 1px)));
  }

  /* Continuous flow: the segments stop being blocks and run together as one
     paragraph, which is how a daf actually reads — Sefaria's segment breaks are
     an artefact of how the text is stored, not divisions of the sugya. */
  .chal-flow-inline{
    direction:rtl;
    text-align:justify;
  }
  .chal-flow-inline .chal-unit,
  .chal-flow-inline .text-segment,
  .chal-flow-inline .text-he,
  .chal-flow-inline .below-seg,
  .chal-flow-inline .below-src,
  .chal-flow-inline .biurim-src-seg,
  .chal-flow-inline .biurim-src-seg > .text-he{
    display:inline;
    margin:0;
  }
  /* An opened reveal is a block, so it breaks the paragraph exactly where it
     opens — which is right: the line you asked about stays above it. */
  /* The panel is hung out of flow, under the last line of the run it belongs
     to. In flow it would split the paragraph, and the fragment left above the
     split gets justified across the full measure — the spacing of a line the
     reader is still reading visibly changes. Out of flow, nothing moves: it
     covers the lines beneath it like a popover and gives them back on close.
     JS sets top and width; #chalStream is the positioning context.

     :not([hidden]) is load-bearing. A closed reveal is closed by the `hidden`
     attribute, which is only a UA rule — any author rule setting `display`
     beats it. Without the guard this one forces every card open, so the
     Meforshim sit permanently expanded in Tap for More. */
  .chal-flow-inline{position:relative}
  .chal-flow-inline .below-body:not([hidden]){
    display:block;
    position:absolute;
    left:0;
    z-index:6;
    box-sizing:border-box;
    text-align:start;
    direction:ltr;
    background:var(--frame);
    border:1px solid color-mix(in srgb, var(--gold) 30%, transparent);
    border-radius:10px;
    box-shadow:0 6px 20px rgba(0,0,0,.16), 0 1px 3px rgba(0,0,0,.1);
    padding:.15rem .7rem .6rem;
    margin-top:.3rem;
  }
  /* The hairline that separates an in-flow panel from its source is the
     popover's own border here. */
  .chal-flow-inline .below-body::before{display:none}
  .chal-flow-inline .below-body .text-he,
  .chal-flow-inline .below-body .biurim-cmt-body{
    display:block;
    direction:rtl;
    text-align:justify;
  }
  /* Marks the run whose reveal is open, so it is clear which part of the
     paragraph the panel below belongs to. */
  .chal-flow-inline .below-seg.below-open > .below-src{
    background:color-mix(in srgb, var(--gold) 12%, transparent);
    border-radius:.25em;
    box-decoration-break:clone;
    -webkit-box-decoration-break:clone;
  }

  /* The daf mark in continuous flow. A daf boundary is a fact about the
     printing, not about the sugya, so it is set the way a printed page sets it
     in the margin: small, shaded, and out of the sentence's way. */
  .chal-daf-mark{
    font-family:var(--he-font);
    font-size:.58em;
    line-height:1;
    font-weight:700;
    color:var(--gold);
    opacity:.75;
    background:color-mix(in srgb, var(--gold) 13%, transparent);
    border-radius:.4em;
    padding:.2em .45em;
    margin-inline:.3em;
    vertical-align:.15em;
    white-space:nowrap;
    unicode-bidi:isolate;
    -webkit-user-select:none;
    user-select:none;
  }
  /* In the bottom pane the mark opens its own line — the commentary either side
     of it belongs to different dafim and running them together would mislead. */
  .biurim-commentary .chal-daf-mark{
    display:block;
    width:fit-content;
    margin:1rem auto .5rem;
  }
  .biurim-commentary .chal-unit:first-child > .chal-daf-mark{margin-top:.2rem}

  /* ---------- חלוקת הש״ס — your portion ---------- */
  /* Shares the Hayom body's shape: a plain scrolling column rather than the
     reader's zoom surface, since nothing here is a page image. */
  .chalukas{
    overflow-y:auto;
    padding:calc(1rem + var(--hdr-h, 60px)) .8rem 2.6rem;
    max-width:968px;width:100%;margin:0 auto;
  }
  .chal-intro{color:var(--gold);font-size:.95rem;margin:0 0 .9rem;text-align:center}
  /* Quieter than the heading it sits above: a correction, not a title. */
  .chal-note{
    color:var(--ink);opacity:.7;font-size:.82rem;line-height:1.45;
    margin:0 auto .7rem;max-width:30rem;text-align:center;
  }

  /* The portion you took, once chosen. */
  .chal-summary{
    border:1px solid var(--gold);border-radius:14px;background:var(--frame);
    padding:1.6rem 1.1rem;text-align:center;
    display:flex;flex-direction:column;align-items:center;gap:.35rem;
  }
  /* Under the daf, quieter than it — the perek places you, the daf is where
     you are. */
  .chal-perek-name{
    display:block;
    font-size:.72em;
    font-weight:400;
    color:var(--gold);
    margin-top:.1rem;
  }
  .chal-summary-label{color:var(--gold);font-size:.85rem;letter-spacing:.04em}
  .chal-summary-masechta{font-size:2rem;font-weight:700;color:var(--ink);line-height:1.15}
  .chal-summary-portion{font-size:1.1rem;color:var(--ink);opacity:.85}
  .chal-summary-note{color:var(--gold);font-size:.85rem;margin-top:.5rem;opacity:.8}
  .chal-change{
    margin-top:1rem;padding:.55rem 1.2rem;
    border:1px solid var(--gold);border-radius:999px;
    background:none;color:var(--gold);font:inherit;font-size:.95rem;cursor:pointer;
    -webkit-tap-highlight-color:transparent;
  }
  .chal-change:active{opacity:.6}

  /* Portions already claimed under the signed-in address. */
  .chal-mine{margin-bottom:1.2rem}
  .chal-mine-label{color:var(--gold);font-size:.85rem;margin-bottom:.4rem}
  .chal-mine-btn{
    width:100%;display:flex;align-items:center;gap:.6rem;
    padding:.75rem .9rem;margin-bottom:.4rem;
    border:1px solid var(--gold);border-radius:12px;background:var(--frame);
    font:inherit;color:var(--ink);text-align:start;cursor:pointer;
    -webkit-tap-highlight-color:transparent;
  }
  .chal-mine-btn:active{opacity:.6}
  .chal-mine-masechta{font-weight:700;font-size:1.05rem}
  .chal-mine-portion{color:var(--ink);opacity:.75;font-size:.9rem}
  /* The full catalogue: seder → masechta → portion. */
  .chal-seder{margin-bottom:1.4rem}
  .chal-seder-title{
    color:var(--gold);font-size:1.05rem;font-weight:700;
    margin:0 0 .5rem;padding-bottom:.3rem;border-bottom:1px solid var(--line);
  }
  .chal-masechta-he{font-weight:700;font-size:1.05rem}
  /* Who already holds it — the fastest way for someone to spot their own. */
  .chal-masechta-btn{
    width:100%;display:flex;align-items:center;gap:.6rem;
    padding:.7rem .9rem;margin-bottom:.35rem;
    border:1px solid var(--line);border-radius:12px;background:var(--frame);
    font:inherit;color:var(--ink);text-align:start;cursor:pointer;
    -webkit-tap-highlight-color:transparent;
  }
  .chal-masechta-btn:active{opacity:.6}
  .chal-masechta-he{font-weight:700;font-size:1.05rem}
  .chal-masechta-perakim{margin-inline-start:auto;color:var(--gold);font-size:.85rem;white-space:nowrap}

  /* Step 2 — how much of the masechta. */
  .chal-range{
    border:1px solid var(--gold);border-radius:14px;background:var(--frame);
    padding:1.1rem;display:flex;flex-direction:column;gap:.9rem;
  }
  .chal-back{
    align-self:flex-start;padding:0;border:0;background:none;
    color:var(--gold);font:inherit;font-size:.9rem;cursor:pointer;
    -webkit-tap-highlight-color:transparent;
  }
  .chal-range-masechta{font-size:1.6rem;font-weight:700;color:var(--ink);text-align:center}
  /* The card's chrome is English, so it reads left to right; each Hebrew term
     inside is isolated so bidi can't reorder it against the sentence. */
  .chal-range-row{
    display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;
    font-size:1rem;color:var(--ink);cursor:pointer;
  }
  .chal-range-row span{unicode-bidi:isolate}
  .chal-range-row input[type=radio]{accent-color:var(--gold);width:1.1rem;height:1.1rem;flex:none}
  .chal-range-to{color:var(--gold);font-size:.9rem}
  .chal-select{
    font:inherit;font-size:1rem;padding:.3rem .5rem;
    border:1px solid var(--line);border-radius:8px;
    background:var(--paper, var(--frame));color:var(--ink);
  }
  /* Dimmed, not disabled — see renderChalukasRange(). */
  .chal-select.is-idle{opacity:.5}
  .chal-save{
    margin-top:.3rem;padding:.6rem 1.2rem;
    border:1px solid var(--gold);border-radius:999px;
    background:var(--gold);color:var(--frame);font:inherit;font-size:1rem;cursor:pointer;
    -webkit-tap-highlight-color:transparent;
  }
  .chal-save:active{opacity:.6}

  /* ---------- HAYOM (היום) body ---------- */
  .hayom{
    overflow-y:auto;
    padding:calc(1rem + var(--hdr-h, 60px)) .8rem 2.6rem;
    max-width:968px;width:100%;margin:0 auto;
  }
  .accordion{
    margin-bottom:.9rem;
    flex:none;
  }
  .accordion-head{
    display:flex;align-items:center;gap:.6rem;
    padding:.85rem .9rem;cursor:pointer;user-select:none;
    -webkit-tap-highlight-color:transparent;
    border:1px solid var(--gold);border-radius:12px;background:var(--frame);
  }
  .accordion-title{font-weight:700;font-size:1.08rem;color:var(--ink)}
  .accordion-sub{margin-inline-start:auto;color:var(--gold);font-size:.95rem;white-space:nowrap}
  .accordion-head .chev{color:var(--gold);transition:transform .15s;font-size:.9em;direction:ltr;unicode-bidi:isolate}
  .accordion-head.open .chev{transform:rotate(-180deg)}
  .accordion.dimmed .accordion-head{opacity:.42}
  .accordion-body{
    display:none;padding:0;margin:.6rem 0 0;
    background:var(--frame);border-radius:12px;overflow:hidden;
    margin-left: -.7rem;
    margin-right: -.7rem;
  }
  .accordion-body.open{display:block}
  .accordion-body img{margin-bottom:.5rem;width:100%}
  .accordion-empty{color:var(--ink);opacity:.75;font-size:.95rem;padding:.3rem 0 .6rem}
  .accordion-empty a{color:var(--gold);font-weight:700;text-decoration:underline;cursor:pointer}

  .hayom-section{margin-bottom:1rem}
  .hayom-divider{border:none;border-top:1px solid var(--line);margin:1.4rem 0}
  .hayom-empty{color:var(--ink);opacity:.7;font-size:.95rem}

  /* ---------- Hayom rows inside the settings popover ---------- */
  .settings-toggle{display:flex;align-items:center;justify-content:space-between;gap:.6rem}
  .settings-toggle .settings-label{margin-bottom:0;text-align:start}
  .settings-value{font-size:1rem;margin-bottom:.6rem;color:var(--ink);text-align:center}
  .settings-value.muted{opacity:.65}

  .switch{position:relative;display:inline-block;width:2.7rem;height:1.6rem;flex:none;-webkit-tap-highlight-color:transparent}
  .switch input{position:absolute;inset:0;opacity:0;margin:0;cursor:pointer;z-index:1}
  .switch-track{position:absolute;inset:0;border-radius:999px;background:var(--line);transition:background .15s}
  .switch-thumb{
    position:absolute;top:50%;margin-top:-.6rem;inset-inline-start:2px;
    width:1.2rem;height:1.2rem;border-radius:50%;
    background:var(--frame);box-shadow:0 1px 3px rgba(0,0,0,.3);
    transition:transform .15s;
  }
  .switch input:checked + .switch-track{background:var(--gold)}
  .switch input:checked + .switch-track .switch-thumb{transform:translateX(-1.25rem)}

  .btn-gold{
    display:block;width:100%;
    font-family:inherit;font-size:.92rem;font-weight:700;
    background:var(--gold);color:var(--parch);
    border:none;border-radius:8px;padding:.55rem 1rem;
    cursor:pointer;transition:opacity .15s;
    -webkit-tap-highlight-color:transparent;
  }
  .btn-gold:active{opacity:.6}
  .btn-gold-sm{display:inline-block;width:auto;font-size:.75rem;font-weight:600;padding:.25rem .7rem;border-radius:6px}
  .brightness-slider{
    width:100%;
    accent-color:var(--gold);
    cursor:pointer;
    margin:.45rem 0 .1rem;
    display:block;
    height:1.65rem;
    /* Larger hit target so the thumb is easy to drag on a phone. */
    touch-action:none;
  }
  .tg-layout-more-row{
    display:flex;
    justify-content:flex-end;
    padding:.35rem .05rem 0;
  }
  .tg-layout-more-row .tg-size-customize{margin:0}
  .ch-nikud .seg.seg-icononly button{
    display:flex;align-items:center;justify-content:center;
    padding:.35rem .55rem;
    min-width:2.4rem;
  }
  .ch-nikud .nikud-ic{
    width:1.25rem;height:1.25rem;
    display:block;margin-inline:auto;
  }
  .bday-row{display:flex;align-items:center;justify-content:center;gap:.5rem;margin-bottom:.3rem}
  .bday-row .settings-value{margin-bottom:0}
  .family-row{
    display:flex;align-items:center;gap:.6rem;
    padding:.5rem 0;border-bottom:1px solid var(--line);
  }
  .family-row:last-child{border-bottom:none}
  .family-row .info{flex:1;min-width:0}
  .family-row .name{font-weight:700;font-size:.92rem}
  .family-row .bday{font-size:.82rem;color:var(--gold)}
  .family-row .row-actions{display:flex;gap:.35rem;flex:none}
  .drag-handle{
    display:grid;place-items:center;
    width:1.4rem;height:2rem;flex:none;
    color:var(--muted,#aaa);cursor:grab;
    touch-action:none;-webkit-tap-highlight-color:transparent;
  }
  .drag-handle:active{cursor:grabbing}
  .family-row.dragging{
    transform:scale(1.04);
    box-shadow:0 6px 20px rgba(0,0,0,.28);
    border-radius:8px;
    position:relative;z-index:2;
    opacity:.92;
    transition:transform .1s,box-shadow .1s;
  }
  .family-drop-line{height:2px;background:var(--gold);border-radius:1px;margin:2px 0;pointer-events:none}
  .icon-btn-sm{
    display:grid;place-items:center;
    background:none;border:1px solid var(--line);border-radius:8px;
    width:2rem;height:2rem;color:var(--ink);
    font-size:.95rem;cursor:pointer;padding:0;
    -webkit-tap-highlight-color:transparent;
  }
  .icon-btn-sm:active{background:var(--line)}
  #addFamilyBtn{margin-top: .6rem;}

  /* ---- Text-mode reader ---- */
  #textWrap{
    display:block;
    position:relative;   /* positioning context for .col-divider */
    width:100%;
    max-width:968px;
    min-height:100%;
    padding:1rem .8rem calc(2rem + env(safe-area-inset-bottom));
    box-sizing:border-box;
    margin-inline:auto;
    --he-font:"VilnaHebrew","Frank Ruhl Libre",serif;
    --he-size:1.25rem;
    --en-font:"EB Garamond","Frank Ruhl Libre",serif;
    --en-size:1rem;
    /* English is the inherited default inside the reader so any translation
       apparatus that isn't wrapped in an English class (footnote bodies and
       markers, stray inline text) can never fall back to the Hebrew/Vilna
       stack. Every Hebrew element declares font-family:var(--he-font) itself,
       so Hebrew is unaffected. */
    font-family:var(--en-font);
    /* Override the global user-select:none so study text can be copied. */
    -webkit-user-select:text;
    user-select:text;
    -webkit-touch-callout:default;
  }
  #textWrap *{
    -webkit-user-select:text;
    user-select:text;
    -webkit-touch-callout:default;
  }
  #textWrap[hidden]{display:none}
  .text-offline{
    padding:2.4rem .8rem;
    text-align:center;
    color:var(--ink);
    opacity:.65;
    font-size:1rem;
    font-family:"EB Garamond","Frank Ruhl Libre",serif;
  }
  .text-retry-btn{
    display:block;
    margin:1rem auto 0;
    padding:.55rem 1.6rem;
    border:1px solid var(--line);
    border-radius:8px;
    background:transparent;
    color:var(--ink);
    font-family:inherit;
    font-size:1rem;
    cursor:pointer;
  }
  .text-loading{
    padding:1.4rem .8rem;
    max-width:968px;
    margin-inline:auto;
  }
  .skel-line{
    height:.9rem;
    border-radius:4px;
    background:var(--line);
    opacity:.35;
    margin-bottom:.75rem;
    position:relative;
    overflow:hidden;
  }
  .skel-line::after{
    content:'';
    position:absolute;
    inset:0;
    background:linear-gradient(90deg,transparent 0%,rgba(154,123,63,.25) 50%,transparent 100%);
    transform:translateX(-100%);
    animation:page-shimmer 1.6s ease-in-out infinite;
  }
  .skel-line:nth-child(2n){width:85%}
  .skel-line:nth-child(3n){width:70%}
  .skel-line:nth-child(5n){width:60%}
  .skel-line.skel-gap{height:0;margin-bottom:1.4rem}
  .text-segment{margin-bottom:1.2rem}
  .text-he{
    font-family:var(--he-font);
    font-size:var(--he-size);
    direction:rtl;
    color:var(--ink);
    text-align:justify;
  }
  /* Sefaria's texts embed <small> runs (parenthetical notes, source refs,
     nikud/te'amim remarks). Inside the justified reader (text-align:justify),
     the smaller inline run threw off the even inter-word spacing of its line:
     the browser stretches every space on the line, but the small run's own
     spaces start narrower, so they blew out to inconsistent gaps. Rendering
     the run as an inline-block takes its internal spaces out of the parent
     line's justification set, so the surrounding text justifies cleanly while
     the note stays visually small. Scoped to #textWrap so it only touches
     reader text (chumash, rashi, mikra, tanya, rambam, …), not chrome. */
  #textWrap small{
    display:inline-block;
  }
  .text-en{
    font-family:var(--en-font);
    font-size:var(--en-size);
    direction:ltr;
    color:var(--ink);
    opacity:.88;
    margin-top:.4rem;
  }
  .text-columns{
    display:grid;
    /* RTL: the first track renders on the right, so Hebrew takes --col-he. */
    grid-template-columns:minmax(0, var(--col-he, 1fr)) minmax(0, var(--col-en, 1fr));
    gap:.8rem;
    align-items:start;
    /* Hebrew is primary, so it takes the right column and the translation the
       left — matching reading direction and the Chumash side-by-side view. The
       .text-he/.text-en children set their own inner text direction, so only
       the column order flips here; the logical outer paddings below follow. */
    direction:rtl;
  }
  /* min-width:0 lets each column shrink below its longest word and wrap,
     instead of a long Hebrew word blowing the 1fr track out past the screen
     edge (the classic CSS-grid overflow). This keeps the two columns working
     even at narrow portrait-phone widths. */
  .text-columns .text-he,
  .text-columns .text-en{min-width:0;overflow-wrap:break-word}
  .text-columns .text-he{padding-inline-start:.5rem}
  .text-columns .text-en{padding-inline-end:.5rem;margin-top:0}
  .possuk-num{font-size:.72em;opacity:.55;margin-inline-end:.35em;white-space:nowrap}
  .publisher-diagram{
    display:block;
    width:100%;
    margin-block:.85em;
    text-align:center;
  }
  .publisher-diagram img{
    display:block;
    max-width:100%;
    height:auto;
    margin-inline:auto;
  }
  .publisher-diagram img[data-publisher-diagram-failed]{
    display:none;
  }
  .publisher-diagram-fallback{
    display:block;
    font-size:.85em;
    opacity:.55;
    color:var(--ink);
    padding:.6em 0;
  }
  .chumash-trans{
    grid-column:1 / -1;
    direction:ltr;
    text-align:justify;
    font-family:var(--en-font);
    font-size:var(--en-size);
    color:var(--ink);
    opacity:.88;
  }
  /* One frame around the whole verse — possuk, onkelos and translation — rather
     than a box around the English alone. Only bordered when a translation is
     present (Hebrew-only verses stay frameless, as before). */
  .chumash-verse-card{border-radius:7px}
  .chumash-verse-card:has(.chumash-trans){
    border:1px solid var(--line);
    padding:.5em .65em;
    margin:.4em -.65em;
  }
  /* The card supplies the frame now, so the translation drops its own border and
     sits close under the possuk. */
  .chumash-verse-card .chumash-trans{
    border:0;
    padding:0;
    margin:.3em 0 0;
  }
  .chumash-rashien{
    font-family:var(--rashien-font);
    font-size:var(--rashien-size);
    direction:ltr;
    color:var(--ink);
    opacity:.8;
    margin:.3em 0;
  }
  .rashi-entry{display:block;margin:.15em 0}
  /* Rashi "Columns" layout — English (left) beside the dibbur (right). */
  .rashi-entry--cols{
    display:grid;
    /* LTR: English left, dibbur right — Hebrew is the second track. */
    grid-template-columns:minmax(0, var(--col-en, 1fr)) minmax(0, var(--col-he, 1fr));
    gap:.8rem;
    align-items:start;
    direction:ltr;
  }
  .rashi-entry--cols .rashi-dibbur{display:block;text-align:justify}
  .rashi-entry--cols .chumash-rashien{margin:0}
  .rashi-entry:has(.chumash-rashien:not(.tap-rashien-hidden)){
    border:1px solid var(--line);
    border-radius:7px;
    padding:.4em .65em;
    margin: .4em -.65em;
  }
  .rashi-dibbur{display:inline}
  /* Shown before the Rashi text when it shares the possuk's font,
     so the reader can tell where the possuk ends and Rashi begins. */
  .rashi-heading{
    display:block;
    font-weight:700;
    font-size:.78em;
    opacity:.65;
    margin:.35em 0 .15em;
  }
  .rashi-has-en{cursor:pointer}
  .tap-rashien-hidden{display:none}
  /* ---- Swipe-to-reveal translation cards ----
     The Hebrew and its translation are two separate bordered cards sitting side
     by side. Only the Hebrew shows; the translation card waits just off the
     right edge with only its border peeking — its text stays hidden behind the
     card's own padding. Drag left (or tap) to bring the translation card fully
     into view, at which point the Hebrew card's border peeks back from the left.
     In this mode the cards run full-bleed to the right screen edge (and close
     to the left), so the peeking card is cut off by the edge / runs off-screen.
     A small gap (set from JS) keeps the two card borders visually distinct. */
  .swipe-seg{
    cursor:pointer;
    -webkit-user-select:none;
    user-select:none;
    touch-action:pan-y;      /* let vertical scroll pass; we own horizontal */
    /* Pull most of the reader's gutter back on both sides so the cards run wide,
       keeping a matching sliver (.3rem) of padding left and right so the possuk
       and Rashi don't hug the screen edge once the peek is gone. Tracks the
       reader's .8rem side gutter (#textWrap): .8rem − .5rem = the .3rem sliver. */
    margin-right:-.5rem;
    margin-left:-.5rem;
  }
  .text-segment.swipe-seg{margin-bottom:.9rem}

  /* ---------- Reveal, opened out beneath instead of over ----------
     Same tap as the swipe card, opposite direction: the source keeps its place
     and the translation unfolds under it, so you can still see the line you
     reached for the translation about. */
  .below-seg{
    cursor:pointer;
    -webkit-tap-highlight-color:transparent;
  }
  .text-segment.below-seg{margin-bottom:.9rem}
  /* Hidden until the card is open. A chevron under every segment is a row of
     furniture down the whole page, repeating an instruction the reader needs
     once — and the card is tappable anywhere, so it was never the way in. Open,
     it points up and becomes the way out. */
  .below-toggle{
    display:none;
    margin:.1rem auto 0;
    padding:0;
    width:2.2rem;
    height:1.1rem;
    border:0;
    background:none;
    color:var(--gold);
    opacity:.55;
    cursor:pointer;
    -webkit-tap-highlight-color:transparent;
  }
  .below-seg.below-open .below-toggle{display:block}
  /* Continuous flow keeps it hidden throughout: a block button inside a run of
     inline prose would break the line it sits on. */
  .chal-flow-inline .below-seg.below-open .below-toggle{display:none}
  .below-chev{
    display:block;
    margin:0 auto;
    width:1rem;
    height:1rem;
    transition:transform .22s ease;
  }
  .below-seg.below-open .below-chev{transform:rotate(180deg)}
  /* Animated by height in JS, so nothing here may add box trim the measurement
     would miss — the rule above the revealed text is a pseudo-element block,
     which is part of scrollHeight, rather than padding on this box. */
  .below-body{overflow:hidden}
  .below-body::before{
    content:"";
    display:block;
    height:.45rem;
    margin-bottom:.4rem;
    border-top:1px solid color-mix(in srgb, var(--gold) 28%, transparent);
  }

  /* ---------- Reveal, hung over the page instead of opening it ----------
     The same downward card, taken out of flow: the panel lies over the lines
     under it rather than pushing them down, so opening one moves nothing on the
     page and closing it hands the page back exactly as it was. The reader can
     keep their place in a column of text while sampling one line's translation.

     The segment is its own positioning context, so the panel lands square under
     its source at its source's width with nothing to measure — unlike the
     continuous-flow panel below, whose source is a run that ends mid-line and
     which JS therefore has to place by hand.

     :not([hidden]) is load-bearing: a closed card is closed by the `hidden`
     attribute, which is only a UA rule, so any author rule setting `display`
     beats it and would force every card permanently open. */
  .below-seg.below-float{position:relative}
  .below-seg.below-float > .below-body:not([hidden]){
    display:block;
    position:absolute;
    top:100%;
    inset-inline:0;
    z-index:6;
    box-sizing:border-box;
    background:var(--frame);
    border:1px solid color-mix(in srgb, var(--gold) 30%, transparent);
    border-radius:10px;
    box-shadow:0 6px 20px rgba(0,0,0,.16), 0 1px 3px rgba(0,0,0,.1);
    padding:.15rem .7rem .6rem;
    margin-top:.3rem;
  }
  .below-body.below-pop-fixed:not([hidden]){
    display:block;
    z-index:40;
    box-sizing:border-box;
    background:var(--frame);
    border:1px solid color-mix(in srgb, var(--gold) 35%, transparent);
    border-radius:12px;
    box-shadow:0 10px 28px rgba(0,0,0,.22), 0 1px 3px rgba(0,0,0,.12);
    padding:0 0 .55rem;
    margin:0;
    overflow:auto;
  }
  .below-body.below-pop-fixed::before{display:none}
  .below-pop-chrome{
    position:sticky;
    top:0;
    z-index:2;
    display:flex;
    align-items:center;
    gap:.35rem;
    padding:.35rem .55rem .3rem;
    background:color-mix(in srgb, var(--gold) 8%, var(--frame));
    border-bottom:1px solid color-mix(in srgb, var(--gold) 22%, transparent);
    border-radius:12px 12px 0 0;
  }
  .below-pop-drag{
    flex:1 1 auto;
    height:1.15rem;
    border-radius:999px;
    background:
      radial-gradient(circle, color-mix(in srgb, var(--ink) 28%, transparent) 1.4px, transparent 1.6px) 0 50% / 8px 100% repeat-x;
    cursor:grab;
    touch-action:none;
    -webkit-user-select:none;
    user-select:none;
  }
  .below-pop-drag:active{cursor:grabbing}
  .below-pop-close{
    flex:none;
    width:1.7rem;height:1.7rem;
    display:inline-flex;align-items:center;justify-content:center;
    border:none;border-radius:50%;
    background:transparent;color:var(--gold);
    cursor:pointer;padding:0;
    -webkit-tap-highlight-color:transparent;
  }
  .below-pop-close .icon{width:.95rem;height:.95rem}
  .below-pop-close:active{opacity:.55}
  .below-pop-resize{
    position:absolute;
    right:2px;bottom:2px;
    width:1.15rem;height:1.15rem;
    cursor:nwse-resize;
    touch-action:none;
    z-index:3;
    background:
      linear-gradient(135deg, transparent 45%, color-mix(in srgb, var(--gold) 55%, transparent) 46% 54%, transparent 55%),
      linear-gradient(135deg, transparent 60%, color-mix(in srgb, var(--gold) 45%, transparent) 61% 69%, transparent 70%);
  }
  .below-body.below-pop-fixed > .cmt-block,
  .below-body.below-pop-fixed > .text-en,
  .below-body.below-pop-fixed > .text-he,
  .below-body.below-pop-fixed > .biurim-cmt-body{
    padding:0 .7rem;
  }
  /* The hairline that separates an in-flow panel from its source is the
     popover's own border here. */
  .below-seg.below-float > .below-body::before{display:none}
  /* Which line the panel answers, marked on the line itself. The panel covers
     what follows rather than parting it, so the pairing isn't self-evident the
     way it is when the page opens to make room. */
  .below-seg.below-float.below-open > .below-src{
    background:color-mix(in srgb, var(--gold) 10%, transparent);
    border-radius:.3em;
  }
  /* No chevron. It is a block inside the source, so showing it on open would
     grow the source and push the page down — undoing the one thing this
     placement is for. The source stays tappable, and closes the panel. */
  .below-seg.below-float.below-open .below-toggle{display:none}

  .swipe-window{
    position:relative;
    overflow:hidden;
    /* 2px keeps the fully-swiped card's right border just inside the clip so it
       is never shaved off, without adding any visible right gutter. */
    padding-right:2px;
  }
  .swipe-track{
    display:flex;
    align-items:flex-start;
    will-change:transform;
    direction:ltr;           /* fix pane order even inside an RTL (Rashi) block */
    width:100%;
  }
  /* Each pane fills the window; its height is driven from JS and overflow is
     clipped so the hidden card stays fully off-screen until swiped/tapped in. */
  .swipe-pane{
    flex:0 0 auto;
    box-sizing:border-box;
    min-width:0;
    /* Fallback so the reveal is safe without JS: each pane fills the window,
       pushing the sibling (translation) pane fully off-screen so its text stays
       hidden until swiped. Without this, an un-initialised card (e.g. a stale
       cached build, or a render before the pane has layout) collapses to its
       content width and the English shows through beside the Hebrew. The
       SwipeCard JS overrides this with a precise px width once it measures. */
    width:100%;
    padding:0;
    overflow:hidden;
    position:relative;
  }
  .swipe-fit{margin:0}
  /* Neutralise inner text margins so each card's height tracks its content */
  .swipe-pane .text-he,
  .swipe-pane .text-en,
  .swipe-pane .chumash-trans,
  .swipe-pane .chumash-rashien{margin:0}
  /* Strip the standalone translation's own reveal border/padding so it sits
     flush inside the pane. */
  .swipe-en .chumash-trans{border:0;padding:0;margin:0}
  /* Accent stripe on the revealed translation. Because the Hebrew and its
     English swap in place, readers who tapped/swiped can mistake the English
     for a stray verse that slipped into the Hebrew. This coloured left border
     (the theme's --gold accent, so it adapts across every theme and dark mode)
     marks the content as the deliberately-revealed translation.

     The stripe lives on the inner .swipe-fit — not the pane edge — for two
     reasons. (1) At rest the hidden English pane sits flush against the Hebrew
     pane's right edge, just inside the window's clip; a stripe on the pane
     border would peek a sub-pixel sliver there. The margin-left insets it well
     past the clip so nothing shows until the card is actually swiped in.
     (2) During the reveal the pane's left edge butts against the Hebrew card,
     so the same margin-left opens a gap between the Hebrew and the stripe.
     padding-left then holds the English text off the stripe. The pane keeps its
     JS-driven width and padding:0, so card geometry is untouched — and the
     Hebrew's own right padding is not affected. */
  /* Accent stripe on the revealed translation. Use a continuous ::before bar
     (not border-left) so the top/bottom don't grow corner ticks that look like
     a broken accent. Inset via left so the bar stays clipped while the English
     pane is parked off-screen, and so a gap opens beside the Hebrew on reveal. */
  .swipe-en .swipe-fit{
    position:relative;
    margin-left:.5rem;
    padding-left:.75rem;
    border-left:0;
  }
  .swipe-en .swipe-fit::before{
    content:"";
    position:absolute;
    left:0;
    top:0;
    bottom:0;
    width:3px;
    background:var(--gold);
    border-radius:1px;
    pointer-events:none;
  }
  /* Instructional overlay: after a hidden card has lingered on screen for a
     couple of seconds, JS drops this low-opacity scrim over the Hebrew text with
     a "tap to reveal" pill, teaching the affordance in place of a peeking
     border. It's pointer-events:none so the tap still lands on the card, and it
     is retired for good once any translation has been revealed. */
  .swipe-hint{
    position:absolute;
    inset:0;
    z-index:20;
    display:flex;
    align-items:center;
    justify-content:center;
    pointer-events:none;
    background:rgba(255,255,255,.55);
    opacity:0;
    transition:opacity .4s ease;
  }
  html.theme-dark .swipe-hint{background:rgba(0,0,0,.5)}
  .swipe-hint.swipe-hint-in{opacity:1}
  .swipe-hint-label{
    font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
    font-size:.8rem;
    font-weight:600;
    letter-spacing:.02em;
    color:var(--frame);
    background:var(--gold);
    padding:.3em .85em;
    border-radius:999px;
    box-shadow:0 1px 4px rgba(0,0,0,.18);
  }
  /* Frozen reading pin — parked in the margin, never in the text measure. */
  .is-pinned{position:relative}
  .place-pin{
    position:absolute;
    top:.12rem;
    inset-inline-start:.02rem;
    z-index:7;
    width:1.15rem;
    height:1.15rem;
    color:var(--gold);
    pointer-events:none;
    display:grid;
    place-items:center;
    filter:drop-shadow(0 0 1px var(--frame, #fff));
  }
  .place-pin .icon{width:1.05rem;height:1.05rem}
  .place-pin-float{inset:auto}
  /* ---- Rambam commentary tabs (Reveal / Stacked / Columns) ----
     Same strip as Split Pane (.biurim-tabs / .biurim-tab), sitting above the
     active commentary, trimmed a little tighter. Only the active .cmt-panel is
     in the flow, so the block is exactly as tall as whichever tab is showing —
     which is what lets a Reveal card measure to its active tab. The block is
     emitted only when there are 2+ tabs; a lone English tab stays bare
     .text-en, so Stacked and Columns keep the DOM shape they were built for.
     The strip owns horizontal drags (touch-action:pan-x) — SwipeCard declines
     to track from it — so many commentaries scroll sideways instead of
     swiping the card shut. */
  .cmt-block{display:flex;flex-direction:column;min-width:0}
  .cmt-tabs{
    padding:0 0 .35rem;
    gap:.3rem;
    /* pan-x so the strip scrolls sideways rather than swiping the card shut;
       pan-y so a scroll that happens to start on the strip still moves the page. */
    touch-action:pan-x pan-y;
    /* The strip is chrome, not text — never let it swallow the card's own
       margin collapse or pick up the justified text rhythm. */
    margin:0 0 .1rem;
  }
  .cmt-tabs .biurim-tab{
    font-size:.82rem;
    padding:.14rem .68rem;
  }
  .cmt-tabs .biurim-tab[dir="rtl"]{font-size:.86rem}
  .cmt-panel[hidden]{display:none}
  .cmt-panel > .text-en,
  .cmt-panel > .biurim-cmt-body{margin:0}
  /* Stacked: the block takes the place the bare translation had under the
     Hebrew, so it needs that same breathing room above it. */
  .text-segment > .cmt-block{margin-top:.4rem}
  /* Columns: the block is the second grid track, matching .text-en's edge
     padding — and inside a track it must be free to wrap long words. */
  .text-columns > .cmt-block{
    margin-top:0;
    padding-inline-end:.5rem;
    overflow-wrap:break-word;
  }
  /* Half a phone's width fits barely one pill, so a scrolling strip would hide
     most of the commentaries behind a sideways drag. Wrap instead — the grid is
     align-items:start, so a taller strip doesn't disturb the Hebrew track — and
     shrink the pills so they pack two to a row rather than one, keeping the
     strip from towering over a short commentary. */
  .text-columns > .cmt-block > .cmt-tabs{
    flex-wrap:wrap;
    overflow-x:visible;
    gap:.2rem;
  }
  .text-columns > .cmt-block > .cmt-tabs .biurim-tab{
    font-size:.72rem;
    padding:.1rem .48rem;
  }
  .text-columns > .cmt-block > .cmt-tabs .biurim-tab[dir="rtl"]{font-size:.76rem}
  /* Each Rashi is its own pair of cards; give the rows room to breathe apart. */
  .chumash-rashi .swipe-seg{margin-block:.4em}
  .swipe-he .rashi-dibbur{display:block;margin:0}
  .swipe-he .rashi-dibbur b{font-weight:600}
  /* The Hebrew possuk/onkelos grid keeps its two-column layout inside the pane */
  .swipe-he .text-columns-chumash{margin:0}
  /* In swipe mode the Rashi block lives beside the frame rather than inside the
     possuk grid, so restate the styling it used to inherit from that grid. */
  .text-columns-chumash-outer{direction:ltr}
  .text-columns-chumash-outer .chumash-rashi{
    text-align:justify;
    direction:rtl;
    margin-top:.4rem;
  }
  .text-columns-chumash-outer .chumash-rashi .text-he{
    display:inline;
    margin-left:10px;
  }
  .text-columns-chumash-outer .chumash-rashi .text-he b{font-weight:600}
  /* Chumash layout: possuk right (70%) | onkelos left (30%); rashi spans full width.
     Always two columns — no responsive collapse. */
  .text-columns-chumash{
    display:grid;
    grid-template-columns:3fr 7fr;
    gap:.8rem;
    align-items:start;
    direction:ltr;
  }
  /* Onkelos toggled to Reveal (closed) or Columns off — collapse to a single
     full-width possuk column. Columns mode and an open Reveal both use the
     default 3fr/7fr above. */
  .text-columns-chumash--no-onk{
    grid-template-columns:1fr;
  }
  /* Pull-to-reveal Onkelos: the Onkelos rides in a fixed-width panel parked
     off-screen to the left (its final column width, laid out once — no reflow).
     Pulling slides it in while the possuk shrinks to 70% and shifts right to
     make room (JS drives the transform + the possuk's margin-left). The gold
     accent sits on the panel's right edge, so it only comes into view once the
     panel is pulled out — nothing peeks at rest. */
  .onk-reveal{
    touch-action:pan-y;
    -webkit-user-select:none;
    user-select:none;
  }
  .onk-reveal-win{
    position:relative;
    overflow:hidden;
  }
  .onk-reveal-win .chumash-possuk{
    text-align:justify;
  }
  .onk-reveal-win .chumash-possuk .footnote,
  .onk-reveal-win .chumash-possuk .footnote-marker{
    display:none;
  }
  .onk-reveal-panel{
    position:absolute;
    top:0;
    left:0;
    width:30%; /* matches the always-on Columns 3fr/7fr ratio */
    box-sizing:border-box;
    transform:translateX(-101%); /* off-screen left (accent hidden) until JS/drag */
  }
  .onk-reveal-panel .chumash-onkelos{
    width:100%;
    box-sizing:border-box;
    min-width:0;
    text-align:justify;
    padding-top:.35rem;
    /* Accent on the right edge (toward the possuk), with room to its right so
       the Targum never crowds the divider. Padding sits inside the off-screen
       panel, so it can't nudge the accent into view before the pull. */
    border-right:3px solid var(--gold);
    padding-right:.7rem;
  }
  /* Stacked / separate Targum — a little air above the block. Columns keeps
     Targum flush with the possuk's first line (padding there misaligns them). */
  .chumash-verse > .chumash-onkelos,
  .text-segment > .chumash-onkelos{
    padding-top:.35rem;
  }
  .text-columns-chumash .chumash-onkelos{
    text-align:justify;
  }
  .text-columns-chumash .chumash-possuk{
    text-align:justify;
  }
  .text-columns-chumash .chumash-possuk .footnote,
  .text-columns-chumash .chumash-possuk .footnote-marker{
    display: none;
  }
  .text-columns-chumash .chumash-rashi{
    grid-column:1 / -1;
    text-align:justify;
    direction: rtl;
  }
  .text-columns-chumash .chumash-rashi .text-he{
    display: inline;
    margin-left: 10px;
  }
  .text-columns-chumash .chumash-rashi .text-he b{
    font-weight: 600;
  }
  /* Side-by-side layout: translation left | possuk right, verse-aligned.
     Rashi (rendered outside this grid) spans the full card width below. */
  .text-sbs-chumash{
    display:grid;
    /* LTR: translation left, possuk right — so Hebrew is the second track. */
    grid-template-columns:minmax(0, var(--col-en, 1fr)) minmax(0, var(--col-he, 1fr));
    gap:.8rem;
    align-items:start;
    direction:ltr;
  }
  /* Nothing to sit beside: one track, full width. Without this the possuk
     keeps its half of a two-track grid and reads at 46% of the card with dead
     space where the translation would have been. */
  .text-sbs-chumash--solo{grid-template-columns:minmax(0, 1fr)}
  /* Same guard .text-columns carries: without it a single long word sets the
     track's min-content floor, the grid outgrows its container and the whole
     page becomes draggable sideways. Narrowing a column with the divider makes
     a far shorter word enough to trigger it. */
  .text-sbs-chumash > *,
  .rashi-entry--cols > *{min-width:0;overflow-wrap:break-word}
  .text-sbs-chumash .chumash-possuk{text-align:justify}
  .text-sbs-chumash .chumash-sbs-trans{margin-top:0;padding-inline-end:.5rem}

  /* ---- Columns divider ----
     A full-height strip sitting on the column boundary, but only the grip
     inside it takes pointer events: a live hit target running the whole height
     of the page would swallow taps on footnotes and block text selection along
     the gutter. The grip is sticky so it stays reachable however far down the
     reader has scrolled, and the hairline only appears during a drag so an
     unrelated grid (a verse with no second column) never has a stray rule
     drawn through it. */
  .col-divider{
    position:absolute;
    top:0;
    bottom:0;
    width:2.6rem;
    margin-left:-1.3rem;
    pointer-events:none;
    z-index:2;
    /* The grip's static position has to be the *bottom* of this strip: sticky
       `bottom` only ever pulls a box up into view, it never pushes a
       top-anchored one down. Anchored at the end, it rides up off the bottom
       edge on every screen but the last, then settles with the text. */
    display:flex;
    flex-direction:column;
    justify-content:flex-end;
  }
  .col-divider[hidden]{display:none}
  .col-divider::before{
    content:'';
    position:absolute;
    top:0;bottom:0;left:50%;
    width:1px;
    margin-left:-.5px;
    background:var(--gold);
    opacity:0;
    transition:opacity .15s;
  }
  body.col-dragging .col-divider::before{opacity:.5}
  /* Parked at the bottom of the screen, in thumb reach, rather than floating
     mid-page. Sticky (not fixed) so it stays inside the column boundary it
     belongs to and rides up when the content runs short.
     The visible pill is drawn by ::before so the element itself can be a
     proper touch target — the pill alone is ~4px wide, far under the ~44px a
     thumb needs. A soft chip behind it keeps it legible over body text. */
  .col-divider-grip{
    position:sticky;
    bottom:calc(1rem + env(safe-area-inset-bottom));
    display:flex;
    align-items:center;
    justify-content:center;
    width:2.6rem;
    height:2.9rem;
    margin-inline:auto;
    padding:0;
    border:0;
    border-radius:999px;
    background:color-mix(in srgb, var(--frame) 90%, transparent);
    box-shadow:0 1px 4px color-mix(in srgb, var(--ink) 18%, transparent);
    pointer-events:auto;
    cursor:col-resize;
    touch-action:none;
    -webkit-tap-highlight-color:transparent;
  }
  .col-divider-grip::before{
    content:'';
    width:.28rem;
    height:1.5rem;
    border-radius:999px;
    background:color-mix(in srgb, var(--ink) 34%, transparent);
  }
  .col-divider-grip:active::before,
  body.col-dragging .col-divider-grip::before{background:var(--gold)}
  .col-divider-grip:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
  body.col-dragging{cursor:col-resize;user-select:none}
  body.col-dragging *{cursor:col-resize !important}
  @media (prefers-reduced-motion: reduce){
    .col-divider::before{transition:none}
  }
  .rambam-sefer-header{
    font-family:var(--he-font);
    font-size:calc(var(--he-size) * 1.2);
    font-weight:700;
    text-align:center;
    color:var(--gold);
    margin:1.6rem 0 0;
    padding:.3rem 0;
    border-top:1px solid var(--line);
    border-bottom:1px solid var(--line);
  }
  .rambam-sefer-header:first-child{margin-top:0;border-top:none}
  .rambam-treatise-header{
    font-family:var(--he-font);
    font-size:calc(var(--he-size) * 1.1);
    font-weight:700;
    text-align:center;
    color:var(--gold);
    margin:.5rem 0 .3rem;
  }
  .rambam-treatise-header:first-child{margin-top:0}
  /* Split Pane (biurim) renders its source into .biurim-src-seg rather than
     .text-segment, so its footnotes need the same rules re-scoped to the panes
     — the same way headers are shared just below. Both panes are covered:
     the top pane's Rambam text and any Hebrew commentary in the bottom pane
     can carry footnote markers. */
  .text-segment .footnote-marker,
  .biurim-source .footnote-marker,
  .biurim-commentary .footnote-marker{
    color:var(--gold);
    cursor:pointer;
    font-size:.7em;
    vertical-align:super;
    font-weight:700;
    /* Enlarge the touch target so a tap opens the note instead of slipping onto
       the card (which would toggle the swipe). Padding grows the hit area; the
       equal negative margin pulls the surrounding text back so nothing shifts.
       position/z-index keep the marker on top of neighbouring text for hits. */
    padding:.5rem;
    margin:-.5rem;
    position:relative;
    z-index:2;
  }
  .text-segment i.footnote,
  .biurim-source i.footnote,
  .biurim-commentary i.footnote{
    display:none;
    font-style:normal;
    font-size:.85em;
    color:var(--ink);
    opacity:.8;
    background:var(--frame);
    border:1px solid var(--line);
    border-radius:6px;
    padding:.4em .65em;
    margin:.35em 0;
    /* Isolate so open/close cannot change the parent paragraph's bidi.
       Direction comes from dir="auto" (first-strong), not forced RTL. */
    unicode-bidi:isolate;
    text-align:justify;
    text-align-last:auto;
    box-sizing:border-box;
  }
  /* Open note is a real block BETWEEN .fn-flow-before / .fn-flow-after —
     never a display:block mid-IFC (that reflows the preceding anonymous
     block's justification). */
  .text-segment i.footnote.fn-visible,
  .biurim-source i.footnote.fn-visible,
  .biurim-commentary i.footnote.fn-visible{
    display:block;
    width:100%;
  }
  .fn-split-active > .fn-flow-before,
  .fn-split-active > .fn-flow-after{
    display:block;
    text-align:justify;
    text-align-last:auto;
    direction:inherit;
    unicode-bidi:isolate;
  }
  /* Last line before the note ends at the marker — do not stretch it. */
  .fn-split-active > .fn-flow-before{
    text-align-last:start;
  }
  .rambam-intro-block{
    font-family:var(--he-font);
    font-size:calc(var(--he-size) * .85);
    color:var(--ink);
    opacity:.75;
    text-align:justify;
    direction:rtl;
    margin:.5rem 0 .8rem;
    padding:.6rem .8rem;
    background:var(--frame);
    border:1px solid var(--line);
    border-radius:6px;
  }
  .rambam-sefer-summary{
    opacity:.85;
    border-color:color-mix(in srgb, var(--gold) 35%, var(--line));
    background:color-mix(in srgb, var(--gold) 6%, var(--frame));
  }
  .rambam-possuk-quote{
    color:var(--gold);
  }
  .rambam-perek-header{
    font-family:var(--he-font);
    font-size:calc(var(--he-size) * .9);
    font-weight:600;
    text-align:center;
    color:var(--ink);
    opacity:.7;
    margin:.5rem 0 .8rem;
  }
  .text-attribution{
    font-size:.75rem;
    opacity:.55;
    margin-top:.6rem;
    direction:ltr;
    font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  }
  .text-commentary{
    margin:.35rem 0 0;
    padding:.38rem .65rem;
    background:var(--frame);
    border:1px solid var(--line);
    border-radius:5px;
    font-size:.93em;
  }

  /* ---- Optional reader sources (settings) ---- */
  .biurim-mef-hint{
    margin:0 0 .55rem;
    font-size:.78rem;
    opacity:.55;
    line-height:1.35;
  }
  .biurim-mef-list{
    display:flex;
    flex-direction:column;
    gap:.15rem;
  }
  .biurim-mef-row{
    padding:.35rem 0;
    border-bottom:1px solid color-mix(in srgb, var(--line) 70%, transparent);
  }
  .biurim-mef-row:last-child{border-bottom:0}
  .biurim-mef-name{
    font-family:var(--he-font, "VilnaHebrew","Frank Ruhl Libre",serif);
    font-size:1rem;
  }
  .biurim-mef-row[dir="ltr"] .biurim-mef-name{
    font-family:"EB Garamond","Frank Ruhl Libre",Georgia,serif;
  }
  .reader-source-row{
    display:flex;
    align-items:center;
    gap:.45rem;
    /* Reorder only from the grip. Capturing pans on the whole row was
       eating vertical scrolling, so a long מפרשים list could not move. */
    touch-action:pan-y;
  }
  .reader-source-row .reader-source-name{flex:1 1 auto;min-width:0}
  .reader-source-row[data-available-today="0"] .reader-source-name{opacity:.45}
  .reader-source-handle{
    flex:none;
    touch-action:none;
  }
  .reader-source-row.dragging{
    position:relative;z-index:2;
    background:var(--frame);
    box-shadow:0 6px 20px rgba(0,0,0,.28);
    border-radius:8px;
    opacity:.92;
  }

  /* ---- Rambam Split Pane study drawer ---- */
  #frameWrap.biurim-scroll-lock{
    overflow:hidden;
    /* Shrink top padding as the header auto-hides so the breadcrumb doesn’t
       leave an empty band above the Split Pane. */
    padding-top:calc(var(--hdr-h, 60px) - var(--hdr-off, 0px));
    /* #frameWrap normally provides --shiur-scroll for the reading-progress bar,
       but in Split Pane it doesn't scroll at all — the top pane does. Only one
       element may provide a given timeline name in scope, so hand it over
       rather than leaving two candidates (which resolves to no timeline, and
       the bar sits dead at zero). Progress tracks the Rambam itself; the
       commentary pane deliberately has none. */
    scroll-timeline:none;
  }
  #textWrap.biurim-mode{
    display:flex;
    flex-direction:column;
    width:100%;
    max-width:none;
    height:calc(100dvh - var(--hdr-h, 60px) + var(--hdr-off, 0px));
    max-height:calc(100dvh - var(--hdr-h, 60px) + var(--hdr-off, 0px));
    min-height:0;
    padding:0;
    margin:0;
    overflow:hidden;
    /* Fallback only — JS writes the saved (or first-run 50/50) share as an
       inline var before paint. Kept in step with SPLIT_DEFAULT. */
    --biurim-split:50%;
  }
  .biurim-drawer{
    display:flex;
    flex-direction:column;
    flex:1;
    min-height:0;
    width:100%;
    max-width:968px;
    margin-inline:auto;
  }
  .biurim-source{
    flex:0 0 var(--biurim-split);
    min-height:4.5rem;
    overflow-y:auto;
    -webkit-overflow-scrolling:touch;
    padding:.7rem .85rem .5rem;
    background:var(--bg, var(--frame));
    box-sizing:border-box;
    /* Drives the reading-progress bar while Split Pane is up — see
       #frameWrap.biurim-scroll-lock, which gives the name up for us. */
    scroll-timeline:--shiur-scroll block;
  }
  .biurim-src-seg{
    padding:.35rem 0 .7rem;
    border-bottom:1px solid color-mix(in srgb, var(--line) 70%, transparent);
  }
  .biurim-src-seg:last-child{border-bottom:0}
  /* ---------- The pair you are on ----------
     The linkage between the panes is otherwise invisible: the bottom pane
     moves, but nothing says which block down there answers the line being
     read. Both halves of the current pair carry the same faint gold, so the
     eye can pair them without being told.

     Only the active pair is touched — an earlier version dimmed everything
     else to .55, which read as a focus mode and made the rest of the daf feel
     switched off.

     Nothing here may occupy space. The mark moves from segment to segment as
     the reader scrolls, so anything that changes a content width re-wraps the
     text underneath them — words jumping between lines while they read, which
     is far more distracting than the mark is useful. The bleed past the text
     edge is therefore painted with a spread shadow, which has no layout effect
     at all, rather than with the padding it used to use. */
  .biurim-src-seg.is-active,
  .biurim-cmt-seg.is-active{
    --seg-tint:color-mix(in srgb, var(--gold) 7%, transparent);
    background:var(--seg-tint);
    border-radius:6px;
    box-shadow:0 0 0 .35rem var(--seg-tint);
    transition:background .22s ease, box-shadow .22s ease;
  }
  .biurim-cmt-seg.is-active{--seg-tint:color-mix(in srgb, var(--gold) 6%, transparent)}
  /* Continuous flow makes the source segments inline runs inside one
     paragraph, where the constraint is tighter still. Inline padding shifts
     every word after it along, re-breaking the lines; and a spread shadow
     would bleed into the lines above and below, which here are the same
     paragraph rather than a neighbouring block. So the tint simply hugs the
     glyphs, cloned onto each line box the run wraps to. */
  .chal-flow-inline .biurim-src-seg.is-active{
    box-shadow:none;
    border-radius:.25em;
    box-decoration-break:clone;
    -webkit-box-decoration-break:clone;
  }
  /* Treatise / perek headers inside Split Pane reuse regular Rambam styles. */
  .biurim-source .rambam-treatise-header,
  .biurim-commentary .rambam-treatise-header{
    margin-top:.85rem;
  }
  .biurim-source .rambam-treatise-header:first-child,
  .biurim-commentary .rambam-treatise-header:first-child{
    margin-top:.15rem;
  }
  /* Sparse נושאי כלים: note when the stream jumps over a whole perek. */
  .biurim-cmt-skip{
    font-family:var(--ui-font);
    font-size:.78rem;
    text-align:center;
    opacity:.45;
    margin:.65rem 0 .25rem;
    direction:rtl;
  }
  .biurim-divider{
    flex:0 0 auto;
    background:var(--bg, var(--frame));
    border-top:1px solid var(--line);
    border-bottom:1px solid var(--line);
    z-index:2;
  }
  /* Bottom-pane breadcrumb — independent of #textBreadcrumb; sits under the
     tab strip and tracks #biurimCommentary scroll only. */
  .biurim-cmt-crumb{
    flex:0 0 auto;
    display:none;
    padding:.3rem 1rem;
    font-family:var(--he-font, inherit);
    font-size:.72rem;
    background:var(--bg, var(--frame));
    border-bottom:1px solid var(--line);
    z-index:2;
    pointer-events:none;
  }
  .biurim-cmt-crumb.crumb-visible{display:flex}
  .biurim-cmt-crumb.crumb-has-nav{
    pointer-events:auto;
    cursor:pointer;
    gap:.15rem .25rem;
  }
  .biurim-cmt-crumb.crumb-has-nav:active{
    background:color-mix(in srgb, var(--ink) 4%, var(--bg, var(--frame)));
  }
  .biurim-cmt-crumb.crumb-menu-open .crumb-nav-chev{transform:rotate(180deg);opacity:1}
  .biurim-cmt-crumb-menu{z-index:13}
  /* Full-width drag strip — grip is just a visual cue; the whole bar is the hit target. */
  .biurim-handle{
    display:flex;
    align-items:center;
    justify-content:center;
    width:100%;
    min-height:1.35rem;
    padding:.35rem 0 .2rem;
    cursor:ns-resize;
    touch-action:none;
    -webkit-user-select:none;
    user-select:none;
  }
  .biurim-handle-grip{
    width:2.4rem;
    height:.28rem;
    border-radius:999px;
    background:color-mix(in srgb, var(--ink) 28%, transparent);
    pointer-events:none;
  }
  body.biurim-dragging{cursor:ns-resize; user-select:none}
  body.biurim-dragging *{cursor:ns-resize !important}
  /* English-only bottom pane: handle alone, no tab strip padding. */
  .biurim-divider-notabs .biurim-handle{
    padding-bottom:.35rem;
  }
  .biurim-tabs{
    display:flex;
    flex-direction:row;
    direction:rtl;
    gap:.35rem;
    overflow-x:auto;
    -webkit-overflow-scrolling:touch;
    padding:.15rem .7rem .55rem;
    scrollbar-width:none;
  }
  .biurim-tabs::-webkit-scrollbar{display:none}
  .biurim-tab{
    flex:0 0 auto;
    border:0;
    background:transparent;
    color:var(--ink);
    opacity:.62;
    font-size:.88rem;
    font-family:"EB Garamond","Frank Ruhl Libre",serif;
    padding:.28rem .75rem;
    border-radius:999px;
    white-space:nowrap;
    cursor:pointer;
  }
  .biurim-tab[dir="rtl"]{
    font-family:var(--he-font);
    font-size:.92rem;
  }
  .biurim-tab.is-active{
    background:var(--gold);
    color:var(--parch);
    opacity:1;
    font-weight:600;
  }
  .biurim-commentary{
    flex:1 1 auto;
    min-height:0;
    overflow-y:auto;
    -webkit-overflow-scrolling:touch;
    padding:.75rem .9rem calc(.45rem + env(safe-area-inset-bottom));
    background:var(--bg, var(--frame));
    box-sizing:border-box;
  }
  .biurim-cmt-seg{
    padding:.15rem 0 .85rem;
    border-bottom:1px solid color-mix(in srgb, var(--line) 55%, transparent);
  }
  .biurim-cmt-seg:last-child{border-bottom:0}
  .biurim-cmt-head{
    font-size:.78rem;
    font-weight:700;
    opacity:.55;
    margin-bottom:.25rem;
    font-family:var(--he-font);
  }
  .biurim-cmt-seg .text-en .biurim-cmt-head,
  .biurim-cmt-head[dir="ltr"]{
    font-family:var(--en-font);
  }
  .biurim-cmt-body{
    font-family:var(--mefarshim-font, var(--he-font));
    font-size:var(--mefarshim-size, calc(var(--he-size) * .92));
    text-align:justify;
    line-height:1.55;
  }
  /* First paint: carriers must never show under a system fallback while the
     private face is still loading. JS adds .protected-font-ready only after
     FontFace.load proves the exact package face. Prefer visibility so layout
     is reserved (no jump). Failure keeps hidden via .protected-v2-font-failed.
     :not(.ready)+!important must win before the first paint — do not rely on
     JS to add a hidden class after insert. */
  .protected-v2-text:not(.protected-font-ready){
    visibility:hidden !important;
  }
  .protected-v2-text.protected-font-ready{
    visibility:visible;
  }
  .protected-v2-text.protected-v2-font-failed{
    visibility:hidden !important;
  }
  /* Publisher semantics only: bold = weight, headings = class.
     Do NOT recreate print lemma boxes / gray shading / gold centered titles. */
  .protected-v2-text b,
  .biurim-cmt-body b,
  .protected-v2-text span.lead-in,
  .biurim-cmt-body span.lead-in{
    font-weight:700;
    font-synthesis:none;
    font-synthesis-weight:none;
    background:none;
    border:none;
    box-shadow:none;
    padding:0;
    border-radius:0;
    -webkit-text-stroke:0;
  }
  .protected-v2-text[data-protected-role="base"],
  .protected-v2-text[data-protected-work="rambam-mevuar-nusach"]{
    display:inline;
    font-weight:inherit;
    background:none;
    border:none;
    box-shadow:none;
    padding:0;
    border-radius:0;
    -webkit-text-stroke:0;
  }
  .protected-v2-text i.footnote b,
  .protected-v2-text i.footnote span.lead-in{
    background:none;
    padding:0;
    border-radius:0;
    -webkit-text-stroke:0;
  }
  /* Publisher topic lines (@02 / @36 / iyun titles). Semantic class only —
     restrained Kavua-native block, no print shading. */
  .biurim-cmt-body span.publisher-heading,
  .protected-v2-text span.publisher-heading,
  .text-he span.publisher-heading,
  .biurim-cmt-body span.header,
  .protected-v2-text span.header,
  .text-he span.header{
    display:block;
    font-weight:700;
    font-size:inherit;
    text-align:inherit;
    color:inherit;
    margin-top:.65em;
    margin-bottom:.25em;
    padding:0;
    background:none;
    border:none;
    box-shadow:none;
    font-synthesis:none;
    font-synthesis-weight:none;
    -webkit-text-stroke:0;
  }
  .biurim-cmt-body span.publisher-heading:first-child,
  .protected-v2-text > span.publisher-heading:first-child,
  .text-he > span.publisher-heading:first-child,
  .biurim-cmt-body span.header:first-child,
  .protected-v2-text > span.header:first-child,
  .text-he > span.header:first-child{
    margin-top:0;
  }
  .biurim-cmt-seg .text-en{
    font-family:var(--en-font);
    font-size:var(--en-size);
  }
  .biurim-source .text-he{
    font-family:var(--he-font);
    font-size:var(--he-size);
  }
  .biurim-empty{
    padding:1.4rem .4rem;
    text-align:center;
    opacity:.55;
    font-size:.95rem;
  }
  /* Under a protected pane.
     A native rectangle covers this element whenever the engine can draw, so
     what is styled here is only ever the cases where it cannot: not signed in,
     not entitled, not yet downloaded. It is centred rather than laid out as
     text because it is a state, not a commentary. */
  .biurim-protected-state{
    display:flex;
    flex-direction:column;
    align-items:center;
    justify-content:center;
    gap:.9rem;
    min-height:100%;
    padding:1.4rem .8rem;
  }
  .biurim-protected-action{
    font:inherit;
    font-size:.95rem;
    padding:.5rem 1.5rem;
    border-radius:999px;
    border:1px solid currentColor;
    background:transparent;
    color:inherit;
    opacity:.8;
    cursor:pointer;
  }
  .biurim-protected-action:active{ opacity:1; }
  /* The stand-in shown in Reveal / Stacked / Columns, where a protected work
     cannot render: those layouts scatter commentary through the DOM and the
     engine draws into one rectangle. Tapping the tab moves the session to
     Split Pane; this is what sits there for the instant before it does. */
  .biurim-protected-hint{
    text-align:center;
    opacity:.5;
    font-size:.9rem;
    padding:.8rem .4rem;
  }
  /* Empty commentary tab while sync is pulling that kind — shimmer, not "אין". */
  .biurim-cmt-loading{
    padding:1.1rem .35rem .4rem;
    display:flex;
    flex-direction:column;
    gap:.55rem;
  }
  .biurim-cmt-loading-shimmer{display:flex;flex-direction:column;gap:.55rem}
  .biurim-cmt-loading-shimmer .skel-line{margin-bottom:0;opacity:.4}
  .biurim-cmt-loading-label{
    text-align:center;
    font-size:.82rem;
    opacity:.5;
    margin-top:.35rem;
    font-family:var(--he-font);
  }
  .biurim-tab.is-loading{
    position:relative;
    padding-inline-end:1.15rem;
  }
  .biurim-tab-pulse{
    position:absolute;
    inset-inline-end:.4rem;
    top:50%;
    width:.42rem;
    height:.42rem;
    margin-top:-.21rem;
    border-radius:50%;
    background:var(--gold);
    opacity:.75;
    animation:biurim-tab-pulse 1s ease-in-out infinite;
  }
  .biurim-tab.is-active .biurim-tab-pulse{
    background:var(--parch);
  }
  @keyframes biurim-tab-pulse{
    0%,100%{opacity:.35;transform:scale(.85)}
    50%{opacity:1;transform:scale(1)}
  }
  @media (prefers-reduced-motion: reduce){
    .biurim-tab-pulse{animation:none;opacity:.7}
  }
  /* Bottom pane tucked away — Rambam fills the screen; handle stays to reopen. */
  #textWrap.biurim-mode.biurim-collapsed .biurim-source{
    flex:1 1 auto;
    min-height:0;
  }
  #textWrap.biurim-mode.biurim-collapsed .biurim-tabs,
  #textWrap.biurim-mode.biurim-collapsed .biurim-commentary,
  #textWrap.biurim-mode.biurim-collapsed .biurim-cmt-crumb,
  #textWrap.biurim-mode.biurim-collapsed .biurim-cmt-crumb-menu{
    display:none;
  }
  #textWrap.biurim-mode.biurim-collapsed .biurim-divider{
    border-bottom:0;
  }
  #textWrap.biurim-mode.biurim-collapsed .biurim-handle{
    padding-bottom:calc(.35rem + env(safe-area-inset-bottom));
  }

  /* ---- Chumash Split Pane ----
     Same drawer as Rambam's; what differs is that a verse contributes several
     linked blocks instead of one — the possuk, then each Rashi. Each is its own
     .biurim-src-seg, so they need to read as a group under the possuk while
     staying visibly separable (that separation is what the linked scroll is
     tracking). */
  .biurim-src-possuk{
    padding-bottom:.5rem;
  }
  .biurim-src-possuk .text-columns-chumash{margin:0}
  .biurim-source .chumash-possuk{text-align:justify}
  /* Rashi hangs off the possuk above it: no border of its own, a gold rule on
     the start edge tying its blocks together. */
  .biurim-rashi-group{
    font-family:var(--rashi-font);
    font-size:var(--rashi-size);
    direction:rtl;
    text-align:justify;
    border-inline-start:2px solid color-mix(in srgb, var(--gold) 55%, transparent);
    padding-inline-start:.7rem;
    margin:0 0 .7rem;
  }
  .biurim-src-seg.biurim-src-rashi{
    padding:.3rem 0;
    border-bottom:1px dotted color-mix(in srgb, var(--ink) 18%, transparent);
  }
  .biurim-src-seg.biurim-src-rashi:last-child{border-bottom:0}
  .biurim-src-rashi .rashi-dibbur{display:block;margin:0}
  .biurim-src-rashi .rashi-dibbur b{font-weight:600}
  .biurim-rashi-group .rashi-heading{margin-top:0}
  .biurim-rashi-note{
    font-size:.8rem;
    opacity:.6;
    margin-bottom:.3rem;
  }
  /* Bottom pane: the verse's translation, then one block per Rashi, each headed
     by its dibbur hamaschil so it's obvious which Rashi is being read. */
  .biurim-cmt-possuk .text-en{
    font-family:var(--en-font);
    font-size:var(--en-size);
    text-align:justify;
  }
  .biurim-cmt-seg.biurim-cmt-rashi{
    border-bottom:1px dotted color-mix(in srgb, var(--ink) 18%, transparent);
    border-inline-start:2px solid color-mix(in srgb, var(--gold) 55%, transparent);
    padding-inline-start:.7rem;
    margin-inline-start:.15rem;
  }
  .biurim-cmt-rashi .chumash-rashien{margin:0;opacity:1}
  .biurim-cmt-head-rashi{
    font-family:var(--rashi-font);
    font-weight:600;
    opacity:.7;
  }

  /* ---- Tanya Split Pane ----
     Tanya's refs are already one per paragraph, so each paragraph is its own
     linked block. It still reads as one continuous passage of a chapter, so
     the blocks take no heads and no dividing rules — a rule every paragraph
     would chop the passage up. Spacing alone separates them; the linked scroll
     (not a label) shows what matches what. */
  .biurim-src-seg.biurim-src-prose,
  .biurim-cmt-seg.biurim-cmt-prose{
    padding:.1rem 0 .7rem;
    border-bottom:0;
  }
  .biurim-src-prose:last-child,
  .biurim-cmt-prose:last-child{padding-bottom:0}
  .biurim-src-prose .text-he{text-align:justify}
  .biurim-cmt-prose .text-en{
    font-family:var(--en-font);
    font-size:var(--en-size);
    text-align:justify;
    margin:0;
  }

  /* Shnayim Mikra layout */
  .mikra-parsha-header{
    font-family:var(--he-font);
    font-size:calc(var(--he-size) * 1.1);
    font-weight:700;
    text-align:center;
    color:var(--gold);
    margin-bottom:.5rem;
    padding-bottom:.3rem;
    border-bottom:1px solid var(--line);
  }
  .mikra-aliyah-header{
    font-family:var(--he-font);
    font-size:calc(var(--he-size) * .9);
    font-weight:600;
    text-align:center;
    color:var(--ink);
    opacity:.6;
    margin:.8rem 0 .5rem;
  }
  .mikra-aliyah-header:first-of-type{margin-top:0}
  .mikra-haftorah-header{
    font-family:var(--he-font);
    font-size:calc(var(--he-size) * 1.1);
    font-weight:700;
    text-align:center;
    color:var(--gold);
    margin:1.5rem 0 .5rem;
    padding-bottom:.3rem;
    border-bottom:1px solid var(--line);
  }
  .mam-spi-pe, .mam-spi-samekh{opacity:.15}
  /* Petuchah / setumah — server emits classed spans (never bare פ/ס alone).
     Already-synced HTML still nests those spans inside mam-spi-pe/samekh;
     don't fade or hide the classed break. */
  .parasha-break{
    font-weight:700;
    color:var(--gold);
    margin-inline:.15em;
    unicode-bidi:isolate;
  }
  .parasha-break--setumah{opacity:.85}
  .mam-spi-pe:has(.parasha-break),
  .mam-spi-samekh:has(.parasha-break){opacity:1}
  .mikra-verse .mam-spi-pe:has(.parasha-break),
  .mikra-verse .mam-spi-samekh:has(.parasha-break),
  .mikra-haf-block .mam-spi-pe:has(.parasha-break),
  .mikra-haf-block .mam-spi-samekh:has(.parasha-break){display:inline}
  /* Sefaria placement tags stay in the HTML for a later feature; hide for now. */
  i[data-overlay],
  i[data-commentator]{display:none}
  .rashi-block-note[hidden]{display:none}
  .mikra-verse .mam-spi-pe,.mikra-verse .mam-spi-samekh,.mikra-verse br,.mikra-verse .footnote,
  .mikra-haf-block .mam-spi-pe,.mikra-haf-block .mam-spi-samekh,.mikra-haf-block br{display:none}
  .mikra-haf-block{
    font-family:var(--he-font);
    font-size:var(--he-size);
    color:var(--ink);
    text-align:justify;
    direction:rtl;
  }
  .mikra-verse{margin-bottom:1.4rem;direction:rtl;text-align:justify}
  .mikra-inline .mikra-verse>div{display:inline}
  .mikra-he1{
    font-family:var(--he-font);
    font-size:var(--he-size);
    color:var(--ink);
    text-align:justify;
    padding-left: 10px;
  }
  .mikra-he2{
    font-family:var(--he-font2);
    font-size:var(--he-size2);
    color:var(--ink);
    opacity:.85;
    text-align:justify;
    padding-left: 10px;
  }
  .mikra-onkelos{
    font-family:var(--onkelos-font);
    font-size:var(--onkelos-size);
    color:var(--ink);
    font-weight:bold;
    opacity:.8;
    text-align:justify;
    padding-left: 10px;
    padding-top:.4rem;
  }
  /* settings groups */
  .settings-group{
    border-top:1px solid var(--line);
    padding:.5rem 0 .15rem;
    margin-top:.2rem;
  }
  /* First view-panel group under the tabs — skip the extra top rule. */
  .settings-panel[data-panel="view"] > .settings-group:first-child{
    border-top:none;
    margin-top:0;
    padding-top:.15rem;
  }
  .ch-rule-lbl{font-size:.62rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;opacity:.72;margin:.9rem .1rem .45rem;border-top:1px solid var(--line);padding-top:.7rem}
  /* When Fonts & Sizes is the only content in a group, the head's own rule
     is the separator — drop the duplicate group border / head margin. */
  .settings-group > .ch-acc-head:first-child{
    margin-top:0;
    border-top:none;
    padding-top:.35rem;
  }
  /* Typography section collapses into an accordion. The rule label doubles as
     the tap target; a chevron flips when open, the font rows are the body. */
  .ch-acc-head{display:flex;align-items:center;justify-content:space-between;gap:.5rem;width:100%;background:none;border:none;border-top:1px solid var(--line);cursor:pointer;font-family:inherit;color:inherit;text-align:start;-webkit-tap-highlight-color:transparent}
  .ch-acc-chev{width:.85rem;height:.85rem;flex:none;opacity:.85;transition:transform .18s}
  .ch-acc-head[aria-expanded="true"] .ch-acc-chev{transform:rotate(180deg)}
  .ch-acc-body:not(.open){display:none}
  .ch-types{display:flex;flex-direction:column}
  .ch-trow{display:grid;grid-template-columns:minmax(3.4rem,max-content) 1fr;align-items:center;gap:.3rem .5rem;padding:.42rem 0}
  .ch-trow[hidden]{display:none}
  .ch-trow + .ch-trow{border-top:1px solid var(--line)}
  .ch-tname{display:flex;flex-direction:column;line-height:1.05;font-size:1.02rem;font-weight:400}
  .ch-tname:not(.he){text-transform:uppercase;letter-spacing:.04em;font-size:.78rem}
  .ch-tsub{font-size:.54rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;opacity:.62}
  .ch-tname > .ch-tsub:only-child{margin-top:0}
  .ch-tctl{min-width:0}
  /* Fonts accordion — font-family picker fills the row; nikud sits under it. */
  .ch-acc-body .ch-tctl .font-picker{width:100%}
  .ch-acc-body .ch-tctl .font-picker-btn{width:100%}
  .ch-nikud{grid-column:1 / -1;justify-self:end;margin-top:.35rem}
  .ch-nikud .seg{display:inline-flex}
  .ch-nikud .seg button{font-family:"VilnaHebrew",serif;font-size:1rem;padding:.22rem .75rem;min-width:2.5rem}
  /* Independent nikkud/taamim toggles — not a radio. Both can be on. */
  .nikud-toggles{display:inline-flex;gap:.4rem;align-items:center}
  .nikud-toggles button{
    display:flex;align-items:center;justify-content:center;
    padding:.35rem .55rem;min-width:2.4rem;
    background:var(--frame);color:var(--gold);
    border:1px solid color-mix(in srgb,var(--gold) 38%,var(--line));
    border-radius:8px;cursor:pointer;line-height:1;
    -webkit-tap-highlight-color:transparent;touch-action:manipulation;
  }
  .nikud-toggles button.active{background:var(--gold);color:var(--parch)}
  .nikud-toggles .nikud-ic{width:1.25rem;height:1.25rem;display:block}
  /* Chumash layout picker — abstract icon stacked above a one-word label.
     Icon parts carry three weights: bold = possuk, mid = Targum, faint =
     translation, and flip to parchment on the active (gold) segment. */
  .seg.seg-layout button{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.28rem;padding:.5rem .3rem;line-height:1}
  .seg.seg-layout button svg{width:22px;height:22px;display:block}
  .seg.seg-layout .seg-lbl{font-size:.78rem;font-weight:700}
  /* Icon-only variant (the generic Reveal/Stacked/Columns Layout picker) —
     no labels, slightly larger glyphs, matching the Chumash accordion icons. */
  .seg.seg-icononly button{
    display:flex;align-items:center;justify-content:center;
    padding:.6rem .3rem;
  }
  .seg.seg-icononly button svg{width:24px;height:24px;display:block;flex:none}
  .nikud-ic{display:block;margin-inline:auto}
  /* Shared icon shades — bold = possuk/Hebrew, mid = Targum, faint = translation */
  .seg svg .ic-bold,.tg-layout-btn svg .ic-bold{fill:currentColor}
  .seg svg .ic-mid,.tg-layout-btn svg .ic-mid{fill:currentColor;opacity:.6}
  .seg svg .ic-faint,.tg-layout-btn svg .ic-faint{fill:currentColor;opacity:.32}
  .seg svg .ic-stroke,.tg-layout-btn svg .ic-stroke{stroke:currentColor;stroke-width:1.7;fill:none;stroke-linecap:round;stroke-linejoin:round}
  /* ---------- Typography: Layout section + Font Size matrix ----------
     Layout and Font Size are separate always-open sections. Font families
     live in the collapsed Fonts accordion below. */
  .tg-section{margin-top:.15rem}
  .tg-section-lbl{
    font-size:.62rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;
    opacity:.72;margin:.15rem .1rem .4rem;
  }
  /* Border only when a prior Layout/Order section is actually visible. */
  .tg-section:not([hidden]) ~ .tg-section .tg-section-lbl{
    border-top:1px solid var(--line);padding-top:.7rem;margin-top:.55rem;
  }
  .tg-section[hidden]{display:none}

  /* Layout — shared group + Customize (Chumash); per-type rows when expanded. */
  .tg-layout-head{
    display:flex;align-items:stretch;gap:.45rem;
    padding-inline:.05rem;
  }
  .tg-layout-head[hidden]{display:none}
  .tg-layout-head .tg-c-layout{flex:1 1 0;min-width:0}
  .tg-layout-head .tg-size-customize{align-self:center}
  .tg-layout-rows{
    display:flex;flex-direction:column;gap:.55rem;
    padding-inline:.05rem;
  }
  .tg-layout-rows[hidden]{display:none}
  /* Label on its own line above the button strip so חומש / רש״י (and similar)
     don't steal width from the layout choices. */
  .tg-layout-row{
    display:flex;flex-direction:column;align-items:stretch;gap:.28rem;
    min-width:0;
  }
  /* display:flex above outranks the UA [hidden] rule, so hiding a row from JS
     (Chumash drops the רש״י row in Split Pane) needs saying out loud. */
  .tg-layout-row[hidden]{display:none}
  .tg-layout-row .tg-name{
    flex:none;align-items:flex-start;text-align:start;
  }
  .tg-layout-row .tg-c-layout{flex:none;width:100%;min-width:0}
  /* Single-type sources (Tanya, Rambam, …): section label is enough — drop the
     redundant per-row name so the button group uses the full width. */
  .tg-layout-rows:has(> .tg-layout-row:only-child) > .tg-layout-row .tg-name{display:none}
  .tg-layout-rows:has(> .tg-layout-row:only-child) > .tg-layout-row{gap:0}
  /* Air above Reveal placement (In Place / Beneath / Popover) so it doesn't
     read as part of the Rashi/layout strip above. */
  #genRevealRow,
  #chRevealRow{
    margin-top:.95rem;
  }
  .tg-size-cols.hide-onk .tg-onk{display:none}
  /* Chumash bottom rows (under Fonts accordion) */
  #settingsChumashAccordion > .tg-src{
    margin-top:.75rem;padding-top:.65rem;border-top:1px solid var(--line);
  }
  #chOnkelosToggleRow{
    margin-top:.35rem;padding-inline:.05rem;
  }
  #chOnkelosToggleRow[hidden]{display:none}

  .tg-layout-wrap{
    display:flex;flex-direction:row;flex-wrap:wrap;align-items:stretch;
    width:100%;max-width:100%;gap:0;
  }
  .tg-layout-btn{
    box-sizing:border-box;
    /* Prefer content-sized buttons so 1–2 options don’t stretch across the row;
       a full strip of options still shares space via flex-grow. */
    flex:1 1 0;min-width:3.6rem;
    /* Tall enough for icon + 2-line .7rem label; padding (not min-height) sets air. */
    height:auto;min-height:0;padding:.85rem .15rem .7rem;
    background:var(--frame);
    border:1px solid color-mix(in srgb,var(--gold) 38%,var(--line));
    border-radius:0;
    color:var(--ink);cursor:pointer;
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.35rem;
    -webkit-tap-highlight-color:transparent;touch-action:manipulation;
  }
  .tg-layout-btn:first-child{border-radius:7px 0 0 7px}
  .tg-layout-btn:last-child{border-radius:0 7px 7px 0}
  .tg-layout-btn:only-child{border-radius:7px}
  .tg-layout-btn + .tg-layout-btn{border-inline-start:none}
  .tg-layout-btn:active{opacity:.65}
  .tg-layout-btn svg{width:22px;height:22px;display:block;flex:none;margin:0}
  .tg-layout-lbl{
    display:block;font-size:.7rem;font-weight:700;letter-spacing:.01em;line-height:1.2;
    text-align:center;white-space:normal;max-width:100%;
    margin:0;padding:0;
  }
  .tg-layout-btn.active{background:var(--gold);color:var(--parch);border-color:var(--gold)}
  /* Five or more options (Tanya: two PDF modes + three text layouts + Split
     Pane) can't share one row on a phone — flex:1 1 0 would just squeeze every
     button until single-word labels like "Original" clip. Wrap into an even
     grid instead. The joined-strip look doesn't survive wrapping (the end caps
     and the shared inner borders both assume one row), so the wrapped variant
     uses separated, individually rounded buttons. */
  .tg-layout-wrap.tg-layout-grid{
    display:grid;
    grid-template-columns:repeat(3, minmax(0, 1fr));
    gap:.3rem;
  }
  .tg-layout-grid .tg-layout-btn{
    border-radius:7px;
    border-inline-start:1px solid color-mix(in srgb,var(--gold) 38%,var(--line));
    padding-inline:.3rem;
    /* A <button> grid item doesn't stretch to its track the way a div does
       (justify-self:normal resolves to start for form controls), so it would
       shrink-to-fit and clip its label inside a full-width cell. */
    width:100%;
    justify-self:stretch;
  }

  /* Font Size — label on its own line; next row is global steppers + a small
     right-aligned Customize. Per-type columns appear after Customize is tapped. */
  .tg-size-head{
    display:flex;align-items:center;gap:.5rem;
    margin:.05rem 0 .2rem;
  }
  .tg-size-head[hidden]{display:none}
  .tg-size-head .tg-global{flex:none}
  .tg-size-customize{
    flex:none;width:auto;margin:0;margin-inline-start:auto;
    padding:.28rem .55rem;
    background:var(--gold);color:var(--parch);
    border:none;border-radius:6px;
    font-family:inherit;font-size:.68rem;font-weight:700;
    cursor:pointer;text-align:center;transition:opacity .15s;white-space:nowrap;
    display:inline-flex;align-items:center;justify-content:center;gap:.28rem;
    -webkit-tap-highlight-color:transparent;
  }
  .tg-size-customize:active{opacity:.6}
  .tg-size-customize[hidden]{display:none}
  .tg-size-customize .tg-more-ic{width:12px;height:12px;display:block;flex:none}
  .tg-size-cols{
    display:flex;flex-wrap:nowrap;align-items:flex-start;gap:.25rem;
    width:100%;padding:0;margin-top:.2rem;
  }
  .tg-size-cols[hidden]{display:none}
  .tg-size-col{
    flex:1 1 0;min-width:0;
    display:flex;flex-direction:column;align-items:center;gap:.2rem;
  }
  .tg-size-col[hidden]{display:none}
  /* Fixed label-slot height so 1-line names (אונקלוס) and 2-line names
     (קריאה + א׳/ב׳) share one baseline — steppers line up in a single row. */
  .tg-size-col > .tg-name:first-child{
    box-sizing:border-box;
    height:2.15rem;min-height:2.15rem;
    justify-content:flex-end;
    align-items:center;text-align:center;
    font-size:.95rem;
    line-height:1.15;
  }
  /* Longer Hebrew labels (e.g. נושאי כלים) need a slightly smaller size. */
  #genMefSizeCol > .tg-name:first-child{font-size:.82rem}
  .tg-size-col > .tg-name:not(.he):first-child{
    text-transform:uppercase;letter-spacing:.04em;font-size:.72rem;
  }
  .tg-size-col .tg-size-en{
    margin-top:.12rem;min-height:1.1rem;
    justify-content:flex-end;align-items:center;text-align:center;
    font-size:.72rem;
    text-transform:uppercase;letter-spacing:.04em;
  }
  .tg-size-col .tg-size-mef{
    margin-top:.12rem;min-height:1.1rem;
    justify-content:flex-end;align-items:center;text-align:center;
    font-size:.82rem;
  }
  .chumash-mef{
    direction:rtl;
    color:var(--ink);
    text-align:justify;
  }
  .chumash-mef.possuk-mef{
    font-family:var(--possuk-mef-font);
    font-size:var(--possuk-mef-size);
  }
  .chumash-mef.rashi-mef{
    font-family:var(--rashi-mef-font);
    font-size:var(--rashi-mef-size);
  }
  .tg-size-col .tg-size{width:100%;justify-content:center}
  .tg-size-col .tg-size button{flex:1 1 0;min-width:0;padding:.38rem .12rem}

  /* .tg-src/.tg-global/.ch-nikud/.ch-trow set display, which beats the UA
     [hidden] rule; restore it so JS .hidden actually hides those rows. */
  .tg-src[hidden],.tg-global[hidden],.ch-nikud[hidden]{display:none}

  .tg-name{display:flex;flex-direction:column;line-height:1.02;font-size:.9rem;font-weight:400}
  .tg-name.he{font-size:1.04rem}
  .tg-sub{font-size:.5rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;opacity:.62;margin-top:.05rem}
  .tg-name > .tg-sub:only-child{margin-top:0}
  .tg-size,.tg-global{display:inline-flex}
  .tg-size button,.tg-global button{
    flex:none;min-width:1.85rem;padding:.42rem .35rem;
    background:var(--frame);border:1px solid color-mix(in srgb,var(--gold) 38%,var(--line));color:var(--gold);
    cursor:pointer;line-height:1;
    display:inline-flex;align-items:center;justify-content:center;gap:.14rem;
    -webkit-tap-highlight-color:transparent;touch-action:manipulation;
  }
  .tg-size button:active,.tg-global button:active{opacity:.5}
  .tg-size button:disabled,.tg-global button:disabled{opacity:.22;cursor:default}
  .tg-size .step-minus,.tg-global .step-minus{border-radius:7px 0 0 7px;border-inline-end:none}
  .tg-size .step-plus,.tg-global .step-plus{border-radius:0 7px 7px 0}
  /* − / + sit next to the letter glyph (א− · א+ / A− · A+). */
  .tg-size .step-minus::after,.tg-global .step-minus::after,
  .tg-size .step-plus::after,.tg-global .step-plus::after{
    font-size:.72rem;font-weight:800;line-height:1;opacity:.9;
  }
  .tg-size .step-minus::after,.tg-global .step-minus::after{content:"−"}
  .tg-size .step-plus::after,.tg-global .step-plus::after{content:"+"}
  .tg-global button{min-width:2.8rem}
  .tg-size .sz-glyph{display:block;line-height:1;transform:none}
  .tg-size .sz-he.sz-sm{font-size:1rem}
  .tg-size .sz-he.sz-lg{font-size:1.34rem}
  .tg-size .sz-en.sz-sm{font-size:.82rem}
  .tg-size .sz-en.sz-lg{font-size:1.18rem}

  /* English source selector — a quiet full-width control below the sections */
  .tg-src{display:flex;align-items:center;gap:.5rem;margin-top:.6rem;padding-inline:.05rem}
  .tg-src-lbl{font-size:.55rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;opacity:.72;white-space:nowrap}
  .tg-src .settings-select{flex:1;min-width:0}
  /* font-picker custom dropdown */
  .font-picker{position:relative}
  .font-picker-btn{
    display:flex;align-items:center;gap:.5rem;width:100%;
    background:var(--frame);border:1px solid var(--line);border-radius:8px;
    padding:.4rem .6rem;cursor:pointer;color:var(--ink);
    font-family:inherit;font-size:.86rem;
  }
  .font-picker-btn:hover{border-color:var(--gold)}
  .font-picker-label{flex:1;min-width:0;font-weight:600;font-size:1rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .font-picker-chevron{width:.7rem;height:.7rem;flex-shrink:0;opacity:.5;transition:transform .18s}
  .font-picker.open .font-picker-chevron{transform:rotate(180deg)}
  .font-picker-menu{
    /* Fixed + centered on the trigger (JS sets --fp-x / --fp-y / --fp-w on open)
       so the menu matches the button width and isn't clipped by the settings sheet. */
    position:fixed;
    left:var(--fp-x, 50%);
    top:var(--fp-y, 50%);
    transform:translate(-50%, -50%);
    z-index:10001;
    box-sizing:border-box;
    /* Open menu sizes to its widest option (max-content), never to the
       collapsed trigger — but never narrower than the trigger either. */
    width:max-content;
    min-width:var(--fp-w, 6rem);
    max-width:min(90vw, 22rem);
    background:var(--parch);border:1px solid var(--gold);border-radius:8px;
    box-shadow:0 6px 18px rgba(0,0,0,.25);overflow:hidden;
    max-height:min(16rem,70vh);overflow-y:auto;
    scrollbar-width:thin;scrollbar-color:var(--gold) transparent;
  }
  .font-picker-menu[hidden]{display:none}
  .font-picker-opt{
    display:flex;align-items:center;gap:.5rem;width:100%;
    background:none;border:none;border-bottom:1px solid var(--line);
    padding:.45rem .6rem;cursor:pointer;color:var(--ink);
    font-family:inherit;font-size:.86rem;text-align:left;
  }
  .font-picker-opt:last-child{border-bottom:none}
  .font-picker-opt:hover{background:rgba(154,123,63,.12)}
  .font-picker-opt.active{background:var(--gold);color:var(--parch)}
  .font-picker-opt-label{flex:1;min-width:0;font-weight:600;font-size:1rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  @media(prefers-color-scheme:dark){
    .font-picker-menu{background:var(--frame)}
  }
  /* translation <select> inside settings */
  .settings-select{
    width:100%;
    font-family:inherit;
    font-size:.86rem;
    padding:.4rem .5rem;
    background:var(--frame);
    border:1px solid var(--line);
    border-radius:6px;
    color:var(--ink);
    color-scheme:light dark;
  }
/* Frank Ruhl Libre — self-hosted (no external HTTP dependency) */
@font-face{font-family:'Frank Ruhl Libre';font-style:normal;font-weight:400;font-display:swap;
  src:url("fonts/j8_w6_fAw7jrcalD7oKYNX0QfAnPW7Ll4ajn.woff2") format("woff2");
  unicode-range:U+0307-0308,U+0590-05FF,U+200C-2010,U+20AA,U+25CC,U+FB1D-FB4F}
@font-face{font-family:'Frank Ruhl Libre';font-style:normal;font-weight:400;font-display:swap;
  src:url("fonts/j8_w6_fAw7jrcalD7oKYNX0QfAnPW77l4ajn.woff2") format("woff2");
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'Frank Ruhl Libre';font-style:normal;font-weight:400;font-display:swap;
  src:url("fonts/j8_w6_fAw7jrcalD7oKYNX0QfAnPW7Dl4Q.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:'Frank Ruhl Libre';font-style:normal;font-weight:700;font-display:swap;
  src:url("fonts/j8_w6_fAw7jrcalD7oKYNX0QfAnPW7Ll4ajn.woff2") format("woff2");
  unicode-range:U+0307-0308,U+0590-05FF,U+200C-2010,U+20AA,U+25CC,U+FB1D-FB4F}
@font-face{font-family:'Frank Ruhl Libre';font-style:normal;font-weight:700;font-display:swap;
  src:url("fonts/j8_w6_fAw7jrcalD7oKYNX0QfAnPW77l4ajn.woff2") format("woff2");
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:'Frank Ruhl Libre';font-style:normal;font-weight:700;font-display:swap;
  src:url("fonts/j8_w6_fAw7jrcalD7oKYNX0QfAnPW7Dl4Q.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
  /* ---- Standalone PWA: full-height layout + safe-area insets ----
     Two forms of the same rules: the media query for true manifest installs,
     and html.standalone (set by JS from navigator.standalone) for iOS
     home-screen installs that run fullscreen without matching the query. */
  @media (display-mode: standalone) {
    /* Must be 100vh (the LARGE viewport): on iOS standalone the layout
       viewport / ICB / svh / dvh are all 47pt short of the screen (measured
       on-device: 797 vs 844 on an iPhone 14), so percentages and small or
       dynamic units leave a page-background band along the bottom. Only
       vh/lvh resolve to the full screen height there. */
    body { height:100vh; }
    .home  { padding-bottom: calc(2rem   + env(safe-area-inset-bottom)); }
    .hayom { padding-bottom: calc(2.6rem + env(safe-area-inset-bottom)); }
    #frameWrap { padding-bottom: env(safe-area-inset-bottom); }
    .update-toast { bottom: calc(1.1rem  + env(safe-area-inset-bottom)); }
    /* Flush to the screen bottom; safe-area is padding on the bar itself. */
    .resume-banner { bottom: 0; }
    .install-banner { bottom: calc(1.1rem  + env(safe-area-inset-bottom)); }
    .settings-sheet-scroll { padding-bottom: calc(.9rem + env(safe-area-inset-bottom)); }
  }
  html.standalone body { height:100vh; }
  html.standalone .home  { padding-bottom: calc(2rem   + env(safe-area-inset-bottom)); }
  html.standalone .hayom { padding-bottom: calc(2.6rem + env(safe-area-inset-bottom)); }
  html.standalone #frameWrap { padding-bottom: env(safe-area-inset-bottom); }
  html.standalone .update-toast { bottom: calc(1.1rem  + env(safe-area-inset-bottom)); }
  html.standalone .resume-banner { bottom: 0; }
  html.standalone .install-banner { bottom: calc(1.1rem  + env(safe-area-inset-bottom)); }
  html.standalone .settings-sheet-scroll { padding-bottom: calc(.9rem + env(safe-area-inset-bottom)); }

  /* ---------- Likkutei Torah / Torah Ohr ---------- */
  /* Sefer → Parsha → Maamar hierarchy, mirroring the Rambam reader. */
  .lk-sefer-header{
    font-family:var(--he-font);
    font-size:calc(var(--he-size) * 1.2);
    font-weight:700;
    text-align:center;
    color:var(--gold);
    margin:1.8rem 0 0;
    padding:.3rem 0;
    border-top:1px solid var(--line);
    border-bottom:1px solid var(--line);
  }
  .lk-sefer-header:first-child{margin-top:0;border-top:none}
  .lk-toc-sefer{
    font-family:var(--he-font);
    font-size:calc(var(--he-size) * .9);
    font-weight:700;
    color:var(--gold);
    text-align:center;
    margin:.4rem .25rem .3rem;
    padding-bottom:.25rem;
    border-bottom:1px solid var(--line);
  }
  .lk-toc-sefer ~ .lk-toc-sefer,
  .lk-toc-item + .lk-toc-sefer{margin-top:.7rem}
  .lk-toc{
    background:var(--frame);
    border:1px solid var(--line);
    border-radius:8px;
    padding:.5rem .35rem;
    margin:0 0 1.4rem;
  }
  .lk-toc-heading{
    font-family:var(--he-font);
    font-size:calc(var(--he-size) * .8);
    font-weight:700;
    color:var(--ink);
    opacity:.7;
    text-align:center;
    margin:0 .25rem .35rem;
  }
  .lk-toc-group{
    font-family:var(--he-font);
    font-size:calc(var(--he-size) * .8);
    font-weight:700;
    color:var(--gold);
    text-align:center;
    margin:.5rem .25rem .25rem;
  }
  .lk-toc-item{
    display:flex;
    align-items:center;
    gap:.5rem;
    width:100%;
    text-align:right;
    background:none;
    border:none;
    border-radius:6px;
    padding:.4rem .5rem;
    color:var(--ink);
    cursor:pointer;
    font-family:var(--he-font);
  }
  .lk-toc-item:active{background:rgba(127,127,127,.12)}
  .lk-toc-num{
    flex:0 0 auto;
    min-width:1.6em;
    font-weight:700;
    color:var(--gold);
    font-size:calc(var(--he-size) * .85);
  }
  .lk-toc-label{
    flex:1 1 auto;
    font-size:calc(var(--he-size) * .85);
    line-height:1.4;
    text-align:right;
  }
  /* Trailing "go to maamar" chevron — visual left in RTL, gold like other chrome. */
  .lk-toc-go{
    flex:0 0 auto;
    display:inline-flex;
    align-items:center;
    color:var(--gold);
    opacity:.75;
  }
  .lk-toc-go .icon{width:1em;height:1em;display:block}
  .lk-parsha-header{
    font-family:var(--he-font);
    font-size:calc(var(--he-size) * 1.1);
    font-weight:700;
    text-align:center;
    color:var(--ink);
    margin:.9rem 0 .5rem;
  }
  .lk-maamar-header{
    font-family:var(--he-font);
    font-size:calc(var(--he-size) * .95);
    font-weight:700;
    color:var(--ink);
    text-align:right;
    direction:rtl;
    margin:1.5rem 0 .6rem;
    padding-bottom:.25rem;
    border-bottom:1px dashed var(--line);
    scroll-margin-top:4rem;
  }
  .lk-maamar-header:first-of-type{margin-top:.3rem}
  .lk-maamar-num{color:var(--gold);font-weight:700}
  .lk-maamar{
    font-family:var(--he-font);
    font-size:var(--he-size);
    color:var(--ink);
    direction:rtl;
  }
  .lk-para{
    direction:rtl;
    text-align:justify;
    line-height:1.35;
    margin:0 0 .45rem;
  }
  .lk-para b{font-weight:700}
  .lk-para.lk-pending{opacity:.35;text-align:center}

/* ---- Hayom Yom / Sefer Hamitzvos body (from Hamesivta HTML) ----
   The date chrome (.hayom-day) is split out of the body into
   .hayom-date-header so Reveal only swaps the essay. Keep the same
   row/cell layout rules on both hosts — otherwise the header collapses
   to an unstyled stack once it leaves .hayom-body. */
.hayom-date-header{
  margin:0 0 1rem;
  padding:.85rem 1rem;
  border-radius:12px;
  background:color-mix(in srgb, var(--gold) 10%, var(--frame));
  border:1px solid color-mix(in srgb, var(--gold) 28%, var(--line));
  box-shadow:0 1px 0 color-mix(in srgb, var(--ink) 4%, transparent);
}
.hayom-body .hayom-p,
.hayom-body .hayom-eng-p{text-align:justify;margin-top:0;margin-bottom:.65rem}
.hayom-body .hayom-day-in-adar-caption,
.hayom-body .hayom-center,
.hayom-date-header .hayom-day-in-adar-caption,
.hayom-date-header .hayom-center{text-align:center;font-weight:600}
.hayom-body .hayom-mevorchim,
.hayom-body .hayom-haftora,
.hayom-body .hayom-mevorchim-y,
.hayom-body .hayom-haftora-y{display:none}
.hayom-body .shiurim,
.hayom-date-header .shiurim{
  border:1px dotted color-mix(in srgb, var(--ink) 25%, transparent);
  border-radius:.75rem;
  background:color-mix(in srgb, var(--ink) 4%, transparent);
  padding:.45rem .65rem;
  margin:.55rem 0;
}
.hayom-body .hayom-day,
.hayom-date-header .hayom-day{
  display:flex;
  flex-direction:column;
  gap:.4rem;
  font-size:.9em;
  width:100%;
  direction:rtl;
  margin:0 0 .85rem;
}
.hayom-date-header .hayom-day{margin:0}
.hayom-body .hayom-day-row,
.hayom-date-header .hayom-day-row{
  display:grid;
  grid-template-columns:minmax(4.25rem,1fr) minmax(0,2.2fr) minmax(4.25rem,1fr);
  gap:.2rem .55rem;
  align-items:start;
}
.hayom-body .hayom-day-row-span,
.hayom-date-header .hayom-day-row-span{grid-template-columns:1fr}
.hayom-body .hayom-shiurim-row,
.hayom-date-header .hayom-shiurim-row{grid-template-columns:auto minmax(0,1fr)}
.hayom-body .hayom-cell,
.hayom-date-header .hayom-cell{min-width:0}
.hayom-body .hayom-cell.hayom-center,
.hayom-date-header .hayom-cell.hayom-center{text-align:center;font-weight:600}
.hayom-body .hayom-cell.hayom-right,
.hayom-date-header .hayom-cell.hayom-right{text-align:start}
.hayom-body .hayom-cell.hayom-left,
.hayom-date-header .hayom-cell.hayom-left{text-align:end}
.hayom-body .hayom-cell.hayom-w-20,
.hayom-date-header .hayom-cell.hayom-w-20{white-space:nowrap}
.hayom-body .hayom-shiurim,
.hayom-date-header .hayom-shiurim{
  display:flex;
  flex-direction:column;
  gap:.25rem;
  font-size:.85em;
  width:100%;
}
.hayom-body .before-moreh{
  font-size:1em;
  color:var(--gold);
  padding:0;
  display:flex;
  flex-direction:column;
  gap:.35rem;
}
.hayom-body .hayom-list{
  display:flex;
  flex-direction:column;
  gap:.45rem;
  margin:.35rem 0 .75rem;
  padding:0;
}
.hayom-body .hayom-item{
  display:flex;
  gap:.55rem;
  align-items:flex-start;
}
.hayom-body .hayom-item-num{
  flex:0 0 auto;
  min-width:1.35em;
  font-weight:700;
  color:var(--gold);
  line-height:1.45;
}
.hayom-body .hayom-item-body{
  flex:1;
  min-width:0;
  text-align:justify;
}
.hayom-body .hayom-item-body > p,
.hayom-body .hayom-item-body .hayom-eng-p{margin:0}
.hayom-body .hayom-hr-172,
.hayom-body .hayom-hr-210{height:1px;border:0;background:color-mix(in srgb, var(--ink) 35%, transparent);margin:1rem 0}

.sehm-body .sehm-heb-title{display:none} /* renderer prints שיעור N */
.sehm-body .sehm-heb-h,
.sehm-body .sehm-title,
.sehm-body .sehm-h,
.sehm-body .sehm-h3,
.sehm-body .sehm-h4{
  text-align:center;
  font-weight:700;
  margin:.45rem 0 .7rem;
  color:var(--gold);
}
.sehm-body .sehm-heb-mitzvah,
.sehm-body .sehm-heb-mitzvah-positive,
.sehm-body .sehm-heb-mitzvah-negative{
  text-align:center;
  font-weight:700;
  margin:.55rem 0 .45rem;
  color:var(--ink);
}
.sehm-body .sehm-mitzvah-label,
.sehm-body .sehm-mitzvah-positive,
.sehm-body .sehm-mitzvah-negative{color:var(--gold);font-weight:700}
.sehm-body .sehm-heb-caption,
.sehm-body .sehm-heb-positive-caption,
.sehm-body .sehm-heb-negative-caption{font-weight:700;color:var(--gold)}
.sehm-body .sehm-heb-body,
.sehm-body .sehm-heb-positive,
.sehm-body .sehm-heb-negative,
.sehm-body .sehm-heb-p,
.sehm-body .sehm-p{text-align:justify;margin:0 0 .65rem;color:var(--ink)}
.sehm-body .sehm-heb-blsi,
.sehm-body .sehm-blsi,
.sehm-body .sehm-csip,
.sehm-body .sehm-b{font-size:.85em;font-style:italic;text-align:center;margin:.35rem 0;color:var(--ink);opacity:.85}
.sehm-body .sehm-reference{
  color:var(--gold);
  font-size:.92em;
  margin:.15rem 0 .55rem;
  text-align:start;
}
.sehm-body .sehm-mitzvah{margin-top:.55rem}
.sehm-body .sehm-hrsp{height:1px;border:0;background:color-mix(in srgb, var(--ink) 35%, transparent);margin:.85rem 10%}
.sehm-body sehm-eng,
.sehm-body sehm-heb{font-weight:600}

/* Account deletion link in the settings popover. Deliberately quiet — it is
   required to be present and easy to find, not to compete with signing in. */
.account-delete-link{
  display:block;margin-top:.6rem;font-size:.8rem;
  color:var(--muted,#8a8a8a);text-decoration:underline;text-underline-offset:2px;
}
.account-delete-link:hover{color:var(--gold)}
.account-delete-link[hidden]{display:none}

/* ---------- protected blocks ----------
   The element a native pane is drawn over, in every layout. It is empty and
   stays empty: nothing is written into it, so there is no protected text in the
   DOM. Its height is set inline by syncProtectedBlocks() from what the engine
   measured, which is what lets it sit in the flow and reflow like anything
   else.

   Nothing here should make it *look* like a special element. It has no border,
   no background of its own and no marker — the whole point is that a reader
   cannot pick it out of the page. */
.protected-block{
  display:block;
  width:100%;
  height:0;
  overflow:hidden;
  /* The pane is painted over this by the OS, not by the page. A background
     would show for one frame before it arrives and read as a flash. */
  background:transparent;
  /* Geometry host only — publisher plaintext is not here. `#textWrap *`
     forces user-select:text; without this !important a long-press on the
     empty host still opens Copy / Look Up / Translate over the native ink. */
  -webkit-user-select:none !important;
  user-select:none !important;
  -webkit-touch-callout:none !important;
}
/* A ref the licensed edition does not hold. Zero height, so the free text
   behind it closes the gap — but still laid out, so a later change of font or
   width re-measures it instead of it vanishing from the page for good. */
.protected-block.is-empty{ height:0; }

/* The free text, shown until a licensed height actually lands. Blocks start
   as `.is-empty` so a slow or failed measurement cannot hide the Rambam. */
.protected-block:not(.is-empty) + .protected-free{ display:none; }

/* A protected block standing in for the source keeps the source's own rhythm:
   it is the body of a halachah, and the halachah number sits beside it. */
.protected-block-source{
  margin-block:0;
}
/* A seif the licensed edition does not hold collapses; hide its web chrome
   so an empty הלכה heading does not sit above a hole. */
.biurim-cmt-seg:has(.protected-block.is-empty){ display:none; }
