/* speak-easy-main.css — 042026.1.68 */
/* [g68 Session 64 — Batch 8 Part A] L10-2 Phase 3 HC token-bridge.
   Speak-Easy owns a bespoke navy palette (--bg1/bg2/bg3/text1/text2/
   border/accent/accent1/accent2/accent3/bg-editor). Migrating 217 hex
   literals across 2690 lines would need file-by-file surgical review
   that exceeds Phase 3 scope; instead we add a body.jhacal-high-contrast
   bridge at the bottom that flips the local brand tokens to HC-safe
   values. Rules consuming var(--bg1/bg2/bg3/text1/text2/border/accent*/
   bg-editor) then flip automatically without !important. The shared-ui.
   css L10-1 !important layer remains in place for the remaining element-
   level literals. A deeper Phase 4+ pass could swap the navy surfaces
   for shared --bg-* tokens, but the brand palette is important product
   identity — preserving it in default mode is intentional. */
/* [g67 Session 63 — Batch 7 Part C] L11-3 §6 closure: seven TEXT rules
   swapped from `color: var(--accent)` → `color: var(--accent-text)`:
   `.debug-title`, `.debug-section-title`, `.debug-stat-value`,
   `.stat-count`, `.kn-group-header`, `.kn-lib-head h4`, `.kn-lib-row`.
   Fills/strokes/borders that use `var(--accent)` are untouched (they
   only need the 3:1 UI gate, which --accent satisfies). */
/* speak-easy-main.css — 042026.1.63 [g155 hardcoded stage width] */
/* [g56 Session 53] Tablet mode CSS overlay added after line 488 alongside existing Whole/Create/Announce mode overlays. body[data-mode="Tablet"] applies grid-template-columns:1fr minmax(280px,360px) to .compose, pins .sentence/.sub-controls/.pred-words to the left column and .keyword-search-bar/.pred-phr to the right column. ≤900px viewport falls back to single column (Speak-Easy targets tablets/iPads/PCs only — this is just a safety net). Paired with Part A wiring in speak-easy-app.js (fillPredRows pager on phrase predictions) so the right-column phrase rail has dot-and-arrow scroll through 30+ keyword matches. No change to Full Board or Compose layouts. Rapid Response tab retired in index.html — migrated to header icon button #rapidBtn. */
/* [g55 Session 52] HOT-FIX regression from g54. Pete reported on tablet: "screen jumps up a little showing three of the matched 30 phrases but doesn't allow me to scroll through them." Root cause: g54 bumped .list max-height to min(62dvh,560px), pushing the right-column content (h4 + search + status + add row + 560px list + counter + footer ≈ 800px) over the parent .modal 80dvh budget on iPad landscape and on portrait with keyboard up. Once .modal's own overflow:auto kicked in, iOS Safari treated it as a nested scroll container and .list's internal scroll lost the gesture competition — the modal scrolled up to reveal ~3 rows and the list became un-scrollable. Fix: tightened the clamp to min(50dvh,440px) so total right-column content stays within .modal's 80dvh budget across orientations → no outer modal overflow → no nested-scroll conflict → .list's internal overflow:auto works as designed. Kept scrollbar-gutter:stable + -webkit-overflow-scrolling:touch + the #libCount counter (all innocent of the regression). Permanent solution LANDED in g56 Tablet mode which inlines search into a right rail with the phrase-prediction pager — eliminating the modal entirely for tablet search. */
/* [g54 Session 51] SUPERSEDED by g55 — kept for history: min(62dvh,560px) ceiling was the regression trigger. */
/* =====================================================
   speak-easy-main.css — Consolidated Speak-Easy V27 Styles

   [L12-7 Deploy A, g33] Layout + modal height constraints migrated from `vh`
   (visual viewport height — pre-keyboard-aware) to `dvh` (dynamic viewport
   height — shrinks when iOS/Android virtual keyboard rises). `.stage` and
   `.main` already used `dvh` from earlier work; this pass completes the
   migration across `.left` / `.right` panels and all modal `max-height`
   constraints. Browser support: iOS Safari 15.4+, Android Chrome 108+
   (graceful fallback to `vh` on older browsers — no regression). Speak-Easy
   first; other apps follow in a later deploy if on-device iPad testing
   confirms the fix.
   
   Sources merged:
   1. Inline <style> from HTML (base app styles, layout, tiles, modes)
   2. speak-easy-v27-modal-visibility.css (modal overlay fixes)
   3. prediction-button-fix.css (prediction pill overflow fixes)
   
   NOT included (kept separate by responsibility):
   - speak-easy-v27-settings.css (V27 settings modal — DELETED 2026-03-30 [A14]; replaced by jhacal-settings-modal.css)
   - jhacal-lexicon-ui.css (lexicon manager modal — different component)
   ===================================================== */

  :root{
    /* Width presets keep header/tiles/text aligned */
    --content-width: 1120px;
    --content-width-narrow: 960px;
    --content-width-tiny: 820px;

    /* Palette — JHACAL dark navy (Full Board redesign) */
    --bg1:#1a1a2e;--bg2:#16213e;--bg3:#0f3460;--text1:#e0e0e0;--text2:#a0a8b8;--border:#1e3a5f;--accent:#f5a623;
    /* Accent colours */
    --accent1:#e94560;    /* red — speak / alert */
    --accent2:#f5a623;    /* orange — JHACAL brand / match highlight */
    --accent3:#1a7fbf;    /* blue — SVO next-word row */
    /* Editor */
    --bg-editor:#1e3a20;  /* dark green tinted — sentence editor */
    --radius:12px;--shadow:0 8px 24px rgba(0,0,0,.35);

    /* Tiles (compact) - REDUCED font sizes to fit more text */
    --tile-min-h:54px;
    --tile-min-h-sm:40px;
    --tile-font:1.05rem;
    --tile-font-sm:0.92rem;

    /* Prediction pills - REDUCED font sizes to fit more text */
    --pill-pad:7px 9px;
    --pill-font:0.78rem;

    /* Keyboard */
    --key-h:36px; --key-radius:6px; --key-font:13px; --kbd-gap:3px;

    /* Hairline separators */
    --sep: 1px solid color-mix(in oklab, var(--border) 80%, transparent);

    /* Primary tiles font scaling (wired in below) */
    --tile-font-scale:1;
  }
  
  /* Prevent overflow when display size is increased */
  * { box-sizing: border-box; }
  body { overflow-x: hidden; }
  .main { max-width: 100vw; overflow-x: hidden; }
  .left, .right { max-width: 100%; overflow-x: hidden; }
  .tabs { flex-wrap: wrap; }
  .grid-perm, .grid-phr { 
    display: grid; 
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 6px;
  }
  @media (max-width: 768px) {
    .grid-perm, .grid-phr {
      grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    }
  }

  [data-theme="light"]{
    --bg1:#f7f8fa;--bg2:#eef1f4;--bg3:#e8ecef;--text1:#121417;--text2:#5b6570;--border:#cfd6dd;--accent:#ffb74d;
  }
  /* Light earthy green sentence area in light theme too */
  [data-theme="light"] .sentence{
    background:#e8f5e9;
    border:1px solid #a5d6a7;
  }
  html,body{height:100%;margin:0;font-family:Arial,Helvetica,sans-serif;background:var(--bg1);color:var(--text1);overflow:hidden}

  /* [g155] Defensive --content-width definition. The line-47 :root rule
     wasn't propagating this variable (cause TBD; possibly a syntax-error
     interaction with the later :root blocks at lines 1942/2644). Pin the
     value on html so any rule using var(--content-width) gets a working
     number. The .stage rule below also hardcodes 1120px so it works even
     if this html block is somehow ignored too. */
  html { --content-width: 1120px; --content-width-narrow: 960px; --content-width-tiny: 820px; }

  /* Layout frame -- consistent width across all modes.
     [g121 revert] g120 edge-to-edge change reverted -- caused mode tabs to
     vanish. Investigation deferred (filed F40-future-25). Restoring original
     centred-grid layout pending proper diagnosis with browser dev tools. */
  .stage{display:grid;grid-template-columns:1fr min(1120px, calc(100vw - 16px)) 1fr;height:100dvh;padding-top:8px;opacity:0;transition:opacity 0.3s ease}  /* [g155] hardcoded 1120px (was var(--content-width) which wasn't being applied — see investigation in CONTRACT 2 ledger). Three columns: 1fr | min(1120,100vw-16) | 1fr. At desktop 1920vw → 400 | 1120 | 400 px, .app stays centered + fixed-width regardless of content. */
  .stage.ready{opacity:1}
  .app{grid-column:2;display:grid;grid-template-rows:auto 1fr;gap:8px;padding:8px;padding-top:40px}
  /* Removed narrow/tiny stage resizing - all modes use same width now */

  /* ===== FACADE HEADER DESIGN ===== */
  .header {
    background: linear-gradient(180deg, #272b31 0%, #242830 100%);
    border: 1px solid #3d444d;
    border-radius: 10px;
    overflow: hidden;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  }

  .header-top {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 16px 22px;
    border-bottom: 1px solid rgba(61, 68, 77, 0.4);
  }

  .brand-container {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-right: auto;
  }

  .brand-logo-wrapper {
    position: relative;
    cursor: pointer;
    transition: all 0.3s ease;
  }

  .brand-logo {
    height: 38px;
    width: auto;
    display: block;
    transition: transform 0.3s ease;
    border-radius: 4px;
  }

  .brand-logo-wrapper.expanded .brand-logo {
    transform: scale(1.15);
  }

  .brand-tagline {
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    margin-top: 8px;
    background: rgba(0, 0, 0, 0.9);
    color: #f6c177;
    padding: 6px 12px;
    border-radius: 6px;
    font-size: 0.85rem;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
    font-style: italic;
    z-index: 1000;
  }

  .brand-logo-wrapper.expanded .brand-tagline {
    opacity: 1;
  }

.brand {
  /* Font: Modern, professional */
  font-family: 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  font-weight: 700;
  font-size: 1.6rem;
  letter-spacing: 0.5px;
  
  /* Color: Match JHACAL gold gradient */
  background: linear-gradient(135deg, #f6c177 0%, #ff9800 50%, #f6c177 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  
  /* Effects: Subtle shadow */
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2));
  transition: all 0.3s ease;
}

  .utilities {
    display: flex;
    gap: 10px;
    align-items: center;
  }

  /* .icon-btn inherits shape + interaction from .jhacal-icon-btn (shared-ui.css) */
  .icon-btn {
    width: 44px;
    height: 44px;
    border-radius: 10px;
    border: 1px solid rgba(245, 166, 35, 0.50);
    background: rgba(49, 55, 64, 0.4);
    color: #f6f7f9;
    font-size: 1.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.2s ease;
    position: relative;
  }

  .icon-btn:hover {
    background: #313740;
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
  }

  .icon-btn.tutorial {
    background: #ff9800;
    border-color: #ff9800;
    color: white;
    font-weight: bold;
    font-size: 1.3rem;
  }

  .icon-btn.tutorial:hover {
    background: #ffb74d;
    box-shadow: 0 4px 12px rgba(255, 152, 0, 0.4);
  }

  /* .icon-btn.edit colour handled by jib-gold in jhacal-shared-ui.css */
  .icon-btn.edit[aria-pressed="true"] {
    background: #ffc107;
    border-color: #ffc107;
    color: #000;
  }

  .icon-btn::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: -36px;
    left: 50%;
    transform: translateX(-50%);
    background: rgba(0, 0, 0, 0.95);
    color: white;
    padding: 8px 14px;
    border-radius: 6px;
    font-size: 0.8rem;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
    z-index: 1000;
    box-shadow: 0 4px 12px rgba(0,0,0,0.3);
  }

  .icon-btn:hover::after {
    opacity: 1;
  }
  
  /* Prevent right-side tooltips from going off screen */
  .utilities .icon-btn:nth-last-child(-n+3)::after {
    left: auto;
    right: 0;
    transform: none;
  }

  /* Mode Tabs */
  .tabs {
    display: flex;
    gap: 0;
    padding: 0 20px;
  }

  .tab {
    background: transparent;
    border: none;
    border-bottom: 3px solid transparent;
    color: #7d8590;
    padding: 14px 24px;
    font-size: 0.88rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    cursor: pointer;
    transition: all 0.2s ease;
    display: flex;
    align-items: center;
    gap: 8px;
    white-space: nowrap;
  }

  .tab:hover {
    color: #b9c0c7;
    background: rgba(61, 68, 77, 0.2);
  }

  .tab.active {
    color: #f6c177;
    border-bottom-color: #f6c177;
  }

  .tab.home-tab {
    color: #ff9800;
    border-right: 1px solid rgba(61, 68, 77, 0.4);
    margin-right: 8px;
  }

  .tab.home-tab:hover {
    color: #ffb74d;
    background: rgba(255, 152, 0, 0.1);
  }

  .tab-icon {
    font-size: 1.1rem;
  }

  /* Button styles */
  .btn{border:1px solid var(--border);background:var(--bg3);color:var(--text1);border-radius:8px;padding:4px 10px;cursor:pointer;font-weight:800;font-size:.9rem}
  .primary{background:var(--accent);color:#fff;border-color:var(--accent)}

  /* Edit toggle button styling — base colour from jib-gold; only position:relative needed here */
  #editToggle{position:relative}
  #editToggle[aria-pressed="true"]{background:#ffc107;color:#000;border-color:#ffc107}
  #editToggle[aria-pressed="true"]::after{content:"Done editing? Click me!";position:absolute;top:-10px;left:50%;transform:translateX(-50%);background:#ffc107;color:#000;padding:2px 6px;border-radius:6px;font-size:0.45rem;white-space:nowrap;box-shadow:0 2px 6px rgba(0,0,0,0.3);animation:pulse-reminder 2s infinite}
  #editToggle[aria-pressed="true"]::before{content:"";position:absolute;top:-8px;left:50%;transform:translateX(-50%);width:0;height:0;border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #ffc107}
  @keyframes pulse-reminder{0%,100%{opacity:1}50%{opacity:0.7}}

  /* [g52] Word Library trigger button restored — see index.html header next to #libBtn.
     Pre-g52 a dead `#wordLibBtn, #openWordLibBtn{display:none !important;}` rule lived
     here, hiding selectors that did not exist in markup; rule removed so the button
     renders. Modal #wordLibModal at index.html:555, openWL handler at
     speak-easy-custom-vocab.js:134. */


  /* Main 2-col */
  .main{display:grid;grid-template-columns:400px 1fr;gap:8px;height:calc(100dvh - 116px);min-width:0}  /* [g154] min-width:0 stops content from forcing the grid wider than its track sizes */
  .left,.right{background:var(--bg2);border:1px solid var(--border);border-radius:10px;padding:8px;overflow:hidden;min-width:0}  /* [g154] min-width:0 forces grid items to honour their 400px/1fr tracks instead of growing to fit content (was making the whole app card shift right as long phrase tiles populated .pred-phr) */
  .left{display:flex;flex-direction:column}

  /* Tablet breakpoint */
  @media (max-width: 1024px) {
    .main{grid-template-columns:320px 1fr}
  }

  /* Small tablet / large phone landscape */
  @media (max-width: 768px) {
    .main{grid-template-columns:1fr;height:auto;overflow-y:auto}
    .left{max-height:40dvh;overflow-y:auto}
    .right{min-height:60dvh}
    .app{padding-top:8px}
    .header-top{padding:10px 14px}
    .brand{font-size:1.2rem}
    .brand-logo{height:30px}
    .utilities{gap:6px}
    .icon-btn{width:38px;height:38px;font-size:1.1rem}
    .tab{padding:10px 14px;font-size:0.78rem}
    .compose{grid-template-rows:90px 56px 70px 70px 1fr}  /* [g153] pinned rows — see default rule for rationale */
  }

  /* Phone portrait */
  @media (max-width: 480px) {
    .main{gap:4px}
    .left{max-height:35dvh}
    .stage{padding-top:4px}
    .app{padding:4px;gap:4px}
    .header-top{padding:8px 10px;flex-wrap:wrap}
    .brand{font-size:1rem}
    .brand-logo{height:24px}
    .utilities{gap:4px;flex-wrap:wrap}
    .icon-btn{width:34px;height:34px;font-size:1rem}
    .tab{padding:8px 10px;font-size:0.72rem}
    .tab-icon{font-size:0.9rem}
    .grid-perm{grid-template-columns:repeat(2,1fr)}
    .grid-quick{grid-template-columns:repeat(2,1fr)}
    .grid-phr{grid-template-columns:repeat(1,1fr)}
    .compose{grid-template-rows:76px 48px 64px 70px 1fr}  /* [g153] pinned rows — see default rule */
    /* V27.4: honour --se-compose-font-scale on phone-portrait too (was hard-coded to 1rem, ignoring slider) */
    .sentence{min-height:56px;font-size:calc(1rem * var(--se-compose-font-scale, 1));padding:8px 10px}
    /* Hide third phrase row on small phones — only 2 fit comfortably */
    .pred-row3{display:none}
  }

  /* Section headers use same width rhythm as tiles */
  .section{margin-bottom:6px}
  .section:last-child{margin-bottom:0}

  /* Enhanced Section Headers from Facade */
  .section h4 {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: #7d8590;
    padding-bottom: 6px;
    border-bottom: 1px solid rgba(61, 68, 77, 0.4);
  }

  .section h4{margin:0 0 6px;background:var(--bg3);border:1px solid var(--border);border-radius:8px;padding:6px 8px;text-align:center;color:var(--text2);font-size:.92rem;font-weight:800}

  /* Grids */
  .grid{display:grid;gap:6px}
  .grid-perm{grid-template-columns:repeat(2,1fr)}
  .grid-quick{grid-template-columns:repeat(3,1fr)}
  .grid-phr{grid-template-columns:repeat(2,1fr)}

  /* Tiles */
  .tile{
    background:var(--bg3);border:1px solid var(--border);border-radius:10px;padding:6px 8px;text-align:center;
    font-size:calc(var(--tile-font) * var(--tile-font-scale));
   font-weight:700;font-family:Georgia,'Times New Roman',Times,serif;cursor:pointer;display:flex;align-items:center;justify-content:center;min-height:var(--tile-min-h);
    color:var(--text1);max-width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;transition:box-shadow .12s,border-color .12s
  }
  .tile.small{
    font-size:calc(var(--tile-font-sm) * var(--tile-font-scale));
    min-height:var(--tile-min-h-sm);white-space:normal;line-height:1.12;padding:6px 8px
  }
  .tile:hover{box-shadow:0 6px 16px rgba(13, 110, 253, 0.3);border-color:color-mix(in oklab, var(--accent) 40%, var(--border));transform:translateY(-3px)}
  [aria-pressed="true"] ~ .main .tile{outline:2px dashed color-mix(in oklab, var(--accent) 40%, transparent);outline-offset:2px}
  [aria-pressed="true"] ~ .main .tile:hover{outline-color:var(--accent)}

  .sectionRow{display:flex;justify-content:space-between;align-items:center;margin:0 0 4px}
  .pager{display:flex;gap:6px;align-items:center}
  .dot{width:8px;height:8px;border-radius:50%;background:#2c3138;box-shadow:inset 0 0 0 1px rgba(255,255,255,.06)}
  .dot.on{background:#f6c177}
  /* Prediction dot pager — inline with row1 */
  .pred-row1-bar{display:flex;align-items:center;gap:6px}
  .pred-row1-bar .pred-row{flex:1;min-width:0}
  .pred-dots{display:flex;gap:4px;align-items:center;flex-shrink:0;padding:0}
  /* pred-dot sizing is defined at top level below — not inside this media query */

  /* Right column composition
     Grid rows: sentence | controls | word-preds | keyword-search | phrase-preds
     No keyboard row — hardware/soft keyboard used instead.
     The phrase-preds row is flex (1fr) so it fills remaining space. */
/* [g122] .compose width pinned to VIEWPORT, not parent.
   Original min(1000px, 96%) tracked the parent (.right) which varies per
   mode (720px in FullBoard, 1120px in Compose). Viewport-based math keeps
   width consistent across mode switches -- Pete: "speak-easy is back to
   different screen widths" 2026-04-26. */
.compose{width:min(1000px, calc(100vw - 80px));margin:0 auto;display:grid;gap:8px;height:100%;min-width:0;  /* [g154] min-width:0 — stops .compose grandchildren (phrase tiles) from forcing intrinsic width up through .right -> .main */
  /* [g153 screen-jump fix] Pinned grid rows so the compose area stops
     reflowing as predictions expand/contract. Sentence pinned to 100px
     with overflow-y:auto inside (long messages scroll, box doesn't grow);
     sub-controls 60px; pred-words 75px (fits 2 chip rows comfortably);
     keyword-search-bar 75px; pred-phr eats remaining via 1fr. .compose.kbd-open
     uses a tighter rail (below) to keep predictions visible above the
     soft keyboard. */
  grid-template-rows: 100px 60px 75px 75px 1fr;
}
.compose.kbd-open{
  /* Soft-keyboard variant: shrink sentence + drop pred-words height a touch */
  grid-template-rows: 60px 56px 70px 73px 1fr;
}

  /* Sentence editor: taller, wraps long text */
  /* D-SE-2: compose block font scale — controlled by appDisplaySettings slider via --se-compose-font-scale */
  .sentence{background:var(--bg-editor);border:1px solid #2a5a2a;border-radius:10px;padding:12px 14px;
    min-height:80px;max-height:160px;height:100%;overflow-y:auto;font-size:calc(1.18rem * var(--se-compose-font-scale, 1));line-height:1.45;  /* [g153] height:100% fills the pinned grid row; overflow-y:auto scrolls long messages internally instead of growing the row */
    overflow-y:auto;cursor:text;outline:none;caret-color:var(--accent2);
    -webkit-user-select:text;user-select:text;align-items:flex-start;display:block;word-break:break-word}
  .sentence[contenteditable]:focus{border-color:var(--accent2);box-shadow:0 0 0 2px rgba(245,166,35,0.2)}
  .sentence.placeholder{color:#7d8590;font-style:italic}
  .sub-controls{display:flex;gap:8px;align-items:center;border-top:var(--sep);padding-top:6px}
  #clearBtn{background:#dc3545;color:white;border:1px solid #c82333}
  #clearBtn:hover{background:#c82333;border-color:#bd2130}
  .pred-words{border-top:var(--sep);padding-top:6px;overflow:hidden}
  .pred-phr{border-top:var(--sep);padding-top:6px;overflow:hidden;height:100%;display:flex;flex-direction:column;gap:6px;min-width:0}  /* [g154] min-width:0 — long phrase tiles inside no longer expand .pred-phr's required width */

  /* Keyword search bar - sits above phrase predictions */
  .keyword-search-bar{position:relative;z-index:5;border-top:var(--sep);padding-top:6px;overflow:hidden}

  .pred{display:grid;grid-template-columns:repeat(8,1fr);gap:6px;overflow:hidden}
  /* pred-row1-bar must clip overflowing children so the nav arrows never get pushed off */
  .pred-row1-bar{overflow:hidden}
  .pred-row{overflow:hidden;display:flex;flex-wrap:nowrap;gap:6px;align-items:center;min-height:36px;min-width:0}
  .pb{border:1px solid var(--border);background:var(--bg3);color:var(--text1);padding:var(--pill-pad);border-radius:999px;cursor:pointer;
      font-size:calc(var(--pill-font) * var(--tile-font-scale));text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
      transition:background .12s,color .12s,box-shadow .12s;
      max-width:min(180px,42vw);flex-shrink:0}
  .pb:hover{background:var(--accent);color:#fff;box-shadow:0 0 0 2px color-mix(in oklab, var(--accent) 35%, transparent)}
  .phr .pred{grid-template-columns:repeat(4,1fr)}
  .phr .pred-row{min-height:40px}
  /* Phrase buttons: allow text to wrap but cap width so long phrases can't stretch the row */
  .phr .pb{white-space:normal;line-height:1.15;padding:10px 12px;max-width:min(260px,55vw)}
  /* Third phrase row — same styling as phr .pred-row */
  .pred-row3{overflow:hidden;display:flex;flex-wrap:nowrap;gap:6px;align-items:center;min-height:40px;min-width:0}

  /* Soft-keyboard accommodation: when the visual viewport shrinks (mobile/tablet soft keyboard
     appears), compress the compose area so predictions stay visible above the keyboard */
  .compose.kbd-open .sentence{max-height:72px;min-height:48px}
  .compose.kbd-open .pred-row3{display:none}

  /* Modes */
  body[data-mode="FullBoard"] .main{display:grid}
  body[data-mode="Compose"] .main{display:grid}
  body[data-mode="Compose"] .left{display:none}
  body[data-mode="Compose"] .right{grid-column:1 / -1}
  body[data-mode="Announce"] .main{display:grid}

  /* Announce */
  body[data-mode="Announce"] .right{display:none}
  body[data-mode="Announce"] .left{grid-column:1 / -1;width:100%;margin:0 auto}
  body[data-mode="Announce"] .grid-perm{grid-template-columns:repeat(3,1fr)}
  body[data-mode="Announce"] .grid-phr .tile.small{font-size:1.12rem}

  /* Announce mode responsive */
  @media (max-width: 768px) {
    body[data-mode="Announce"] .left{max-height:none;overflow-y:auto}
    body[data-mode="Announce"] .grid-perm{grid-template-columns:repeat(2,1fr)}
  }

  /* [g60 housekeeping] Save Phrase button hide rules removed — the #savePhraseBtn
     element was deleted in g58, so these mode-conditional hide rules became dead.
     The orphan #savePhraseBtn styling block at line ~2203 is also removed in g60. */

  /* [g56 Session 53] Tablet mode — Full Board layout with keyword search +
     phrase predictions repositioned into a right column on the .compose grid.
     Text box, sub-controls, word predictions stay in the main (left) column;
     phrase rail moves right so the virtual keyboard can rise without
     obscuring it. Pure CSS overlay on shared DOM — no JS mode switch needed
     beyond the existing setMode() flow. ≤900px viewport collapses back to
     single column to avoid cramping (Speak-Easy targets tablets/iPads/PCs
     only — this is a safety fallback). The existing dot-pager on
     .pred-phr (wired in g56 Part A via fillPredRows) handles scrolling
     through 30+ keyword-match phrases inside the right rail. */
  body[data-mode="Tablet"] .main{display:grid}
  body[data-mode="Tablet"] .right .compose{
    grid-template-columns: 1fr minmax(280px, 360px);
    column-gap: 10px;
  }
  body[data-mode="Tablet"] .compose > .sentence,
  body[data-mode="Tablet"] .compose > .sub-controls,
  body[data-mode="Tablet"] .compose > .pred-words{
    grid-column: 1 / 2;
  }
  body[data-mode="Tablet"] .compose > .keyword-search-bar{
    grid-column: 2 / 3; grid-row: 1 / 2;
  }
  body[data-mode="Tablet"] .compose > .pred-phr{
    grid-column: 2 / 3; grid-row: 2 / -1;
    border-top: none; border-left: var(--sep);
    padding-top: 0; padding-left: 8px;
  }
  @media (max-width: 900px){
    body[data-mode="Tablet"] .right .compose{ grid-template-columns: 1fr; }
    body[data-mode="Tablet"] .compose > .keyword-search-bar,
    body[data-mode="Tablet"] .compose > .pred-phr{
      grid-column: 1 / 2; grid-row: auto;
      border-left: none; padding-left: 0;
    }
    body[data-mode="Tablet"] .compose > .pred-phr{
      border-top: var(--sep); padding-top: 6px;
    }
  }

  /* Modals (Library + Settings) */
  .backdrop{position:fixed;inset:0;background:rgba(0,0,0,.55);display:none;align-items:center;justify-content:center;z-index:900}
  .modal{background:var(--bg1);border:1px solid var(--border);border-radius:10px;padding:14px;min-width:320px;max-width:960px;box-shadow:var(--shadow);max-height:80dvh;overflow:auto}
  .lib{display:grid;grid-template-columns:240px 1fr;gap:10px}
  /* [g55 hot-fix] Tightened g54's min(62dvh,560px) → min(50dvh,440px) to stay within parent .modal's 80dvh budget and avoid the nested-scroll conflict on iPad. Same scrollbar-gutter + iOS momentum + counter pairing as g54; only the ceiling changed. Tablet mode in g56 will replace this surface entirely with a paginated rail. */
  .list{background:var(--bg2);border:1px solid var(--border);border-radius:10px;padding:6px;max-height:min(50dvh,440px);overflow:auto;scrollbar-gutter:stable;-webkit-overflow-scrolling:touch}
.cat{display:block;width:100%;text-align:left;background:var(--bg3);border:1px solid var(--border);border-radius:8px;padding:6px;margin:4px 0;cursor:pointer;color:var(--text2)}
  .cat.on{outline:2px solid var(--accent)}
  .phraseRow{display:flex;justify-content:space-between;align-items:center;background:var(--bg3);border:1px solid var(--border);border-radius:8px;padding:6px;margin:4px 0}
  .pill{background:#1f2630;border-radius:999px;padding:2px 8px;font-size:12px;color:#9fb0c3}

  .ws-box{border:1px solid var(--border);background:var(--bg2);border-radius:10px;padding:10px;margin-top:10px}
  .ws-list .ws-item{display:flex;justify-content:space-between;gap:8px;align-items:center;background:var(--bg3);border:1px solid var(--border);border-radius:8px;padding:6px;margin:4px 0}
  .ws-item .ws-meta{font-size:12px;color:var(--text2);margin-top:2px}

  /* Inline editor modal for tile edits - RESTORED FROM V14.19 */
  .mini-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.5);display:flex;align-items:center;justify-content:center;z-index:902}
  .mini-modal{background:var(--bg1);border:1px solid var(--border);border-radius:12px;box-shadow:var(--shadow);padding:12px;min-width:320px;max-width:480px}
  .mini-h{margin:0 0 8px;font:1rem;color:var(--text2)}
  .mini-row{display:flex;gap:8px;align-items:center}
  .mini-input{flex:1;background:var(--bg2);border:1px solid var(--border);border-radius:8px;padding:8px;color:var(--text1);font-size:1rem}
  .mini-actions{display:flex;gap:8px;justify-content:flex-end;margin-top:10px}
  .icon-del{background:transparent;border:1px solid var(--border);border-radius:8px;width:38px;height:38px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer}

/* ============================= */
/* V27 Settings Modal (NEW)      */
/* ============================= */

.v27-modal-backdrop {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;

  background: rgba(0,0,0,.55);
  z-index: 903; /* above jh + mini modals */
}

.v27-modal-dialog {
  background: var(--bg1);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow);

  padding: 16px;
  width: min(900px, 94vw);
  max-height: 85dvh;
  overflow: auto;

  color: var(--text1);
}

/* Allow JS-controlled hiding if needed */
.v27-modal-backdrop[aria-hidden="true"] {
  display: none;
}

/* ===== TUTORIAL SYSTEM STYLES ===== */
  .tutorial-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.4);
    display: none;
    align-items: center;
    justify-content: center;
    z-index: 9999;
    transition: all 0.3s ease;
  }
  .tutorial-overlay.open { display: flex; }
  
  .tutorial-overlay.position-top-left { align-items: flex-start; justify-content: flex-start; padding: 20px; }
  .tutorial-overlay.position-top-right { align-items: flex-start; justify-content: flex-end; padding: 20px; }
  .tutorial-overlay.position-bottom-left { align-items: flex-end; justify-content: flex-start; padding: 20px; }
  .tutorial-overlay.position-bottom-right { align-items: flex-end; justify-content: flex-end; padding: 20px; }
  .tutorial-overlay.position-center { align-items: center; justify-content: center; }
  
  .tutorial-card {
    background: rgba(31, 35, 40, 0.95);
    backdrop-filter: blur(10px);
    border: 2px solid #ff9800;
    border-radius: 16px;
    padding: 20px;
    max-width: 600px;
    max-height: 70dvh;
    overflow: auto;
    box-shadow: 0 20px 60px rgba(0,0,0,0.5);
    transition: all 0.3s ease;
  }
  
  [data-theme="light"] .tutorial-card { background: rgba(247, 248, 250, 0.95); }
  
  .tutorial-header { border-bottom: 1px solid rgba(255, 152, 0, 0.3); padding-bottom: 12px; margin-bottom: 16px; }
  .tutorial-title { font-size: 1.3rem; font-weight: 800; color: #ff9800; margin: 0; }
  .tutorial-progress { height: 6px; background: rgba(255, 152, 0, 0.2); border-radius: 3px; margin: 12px 0; overflow: hidden; }
  .tutorial-progress-fill { height: 100%; background: linear-gradient(90deg, #ff9800, #ffb74d); transition: width 0.3s ease; }
  
  .tutorial-content { line-height: 1.7; color: var(--text1); font-size: 0.95rem; }
  .tutorial-content h3 { color: #ff9800; margin-top: 0; font-size: 1.2rem; }
  .tutorial-content h4 { color: #ffb74d; margin-top: 16px; margin-bottom: 8px; font-size: 1.05rem; }
  .tutorial-content ul { margin: 8px 0 16px 20px; }
  .tutorial-content li { margin: 8px 0; line-height: 1.5; }
  .tutorial-content strong { color: #ffb74d; font-weight: 600; }
  
  .tutorial-controls { display: flex; justify-content: space-between; align-items: center; margin-top: 20px; padding-top: 12px; border-top: 1px solid rgba(255, 152, 0, 0.3); gap: 12px; flex-wrap: wrap; }
  .tutorial-nav { display: flex; gap: 8px; }
  .tutorial-nav .btn { background: rgba(255, 152, 0, 0.2); border: 1px solid #ff9800; color: #ff9800; }
  .tutorial-nav .btn:hover { background: rgba(255, 152, 0, 0.3); }
  .tutorial-nav .btn.primary { background: #ff9800; color: #fff; }
  .tutorial-nav .btn.primary:hover { background: #ffb74d; }
  
  .tutorial-options { display: flex; gap: 12px; align-items: center; color: var(--text2); }
  
  .tutorial-highlight {
    outline: 3px solid #ff9800 !important;
    outline-offset: 4px !important;
    animation: tutorial-pulse 2s infinite;
    position: relative;
    z-index: 9998;
  }
  
  @keyframes tutorial-pulse {
    0%, 100% { outline-color: #ff9800; outline-offset: 4px; }
    50% { outline-color: #ffb74d; outline-offset: 6px; }
  }
  
  .tutorial-skip {
    position: absolute;
    top: 12px;
    right: 12px;
    background: transparent;
    border: 1px solid rgba(255, 152, 0, 0.5);
    color: #ff9800;
    padding: 4px 8px;
    border-radius: 4px;
    font-size: 0.85rem;
    cursor: pointer;
  }
  
  .tutorial-skip:hover { border-color: #ff9800; background: rgba(255, 152, 0, 0.1); }
  
#startTutorial { background: #ff9800 !important; color: #fff !important; font-weight: bold; }
  #startTutorial:hover { background: #ffb74d !important; }

  /* ===== DEBUG PANEL / STATS MODAL STYLES ===== */
  .debug-panel {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: 100%;
    max-width: 520px;
    margin: 0 auto;
    background: rgba(31, 35, 40, 0.99);
    border: 1px solid var(--border);
    border-radius: 0;
    box-shadow: var(--shadow);
    z-index: 9500;
    display: none;
    flex-direction: column;
    overflow: hidden;
  }
  
  [data-theme="light"] .debug-panel {
    background: rgba(247, 248, 250, 0.98);
  }
  
  .debug-panel.open { display: flex; }
  
  /* voiceProfileModal CSS removed — merged into V27 Settings Voice tab */
  
  .debug-header {
    background: var(--bg3);
    border-bottom: 1px solid var(--border);
    padding: 8px 12px;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  
  .debug-title {
    font-weight: 800;
    font-size: 0.9rem;
    color: var(--accent-text); /* [g67 L11-3 §6] normal-size TEXT uses --accent-text for AA 4.5:1; --accent is fills/strokes only */
  }
  
  .debug-close {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text1);
    cursor: pointer;
    font-size: 1.4rem;
    padding: 0;
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    min-width: 44px;
    min-height: 44px;
  }
  
  .debug-close:hover {
    background: var(--bg2);
  }
  
  .debug-content {
    flex: 1;
    overflow-y: auto;
    padding: 12px;
    font-size: 0.85rem;
  }
  
  .debug-section {
    margin-bottom: 16px;
    padding-bottom: 16px;
    border-bottom: 1px solid color-mix(in oklab, var(--border) 50%, transparent);
  }
  
  .debug-section:last-child {
    border-bottom: none;
    margin-bottom: 0;
  }
  
  .debug-section-title {
    font-weight: 700;
    color: var(--accent-text); /* [g67 L11-3 §6] TEXT → --accent-text */
    margin-bottom: 8px;
    font-size: 0.9rem;
  }
  
  .debug-stat {
    display: flex;
    justify-content: space-between;
    padding: 4px 0;
    color: var(--text1);
  }
  
  .debug-stat-label {
    color: var(--text2);
  }
  
  .debug-stat-value {
    font-weight: 600;
    color: var(--accent-text); /* [g67 L11-3 §6] TEXT → --accent-text */
  }
  
  .debug-list {
    max-height: 300px;
    overflow-y: auto;
    background: var(--bg3);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 8px;
    margin-top: 6px;
  }
  
  /* Stat rows rendered by speak-easy-stats.js */
  .stat-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 4px 0;
    border-bottom: 1px solid color-mix(in oklab, var(--border) 40%, transparent);
    font-size: 0.82rem;
  }
  .stat-row:last-child { border-bottom: none; }
  .stat-word  { color: var(--text1); max-width: 75%; word-break: break-word; }
  .stat-count { font-weight: 700; color: var(--accent-text); white-space: nowrap; margin-left: 8px; } /* [g67 L11-3 §6] TEXT → --accent-text */
  .stat-empty { color: var(--text2); font-size: 0.82rem; font-style: italic; padding: 6px 0; }

  .debug-btn {
    background: var(--bg3);
    border: 1px solid var(--border);
    color: var(--text1);
    border-radius: 6px;
    padding: 6px 12px;
    cursor: pointer;
    font-size: 0.85rem;
    font-weight: 600;
    margin-right: 6px;
    margin-bottom: 6px;
  }
  
  .debug-btn:hover {
    background: var(--accent);
    color: #fff;
    border-color: var(--accent);
  }
  /* Voice Controls Panel CSS removed - merged into Settings */

/* Mute Icon Styles */
#muteIcon {
  position: relative;
  display: inline-block;
  font-size: 1.2rem;
}

#muteIcon.muted::after {
  content: '🔇';
  position: absolute;
  top: 0;
  left: 0;
}

#muteIcon.muted {
  color: #dc3545;
}

/* ═══════════════════════════════════════════════════════════════
   STRICT MATCHING INDICATOR
   ═══════════════════════════════════════════════════════════════ */
/* Strict Matching Indicator */
.strict-match-active {
  border-left: 4px solid #4caf50 !important;
  background: linear-gradient(90deg, rgba(76, 175, 80, 0.1) 0%, transparent 100%) !important;
}

.strict-match-indicator {
  position: absolute;
  top: -8px;
  right: 8px;
  background: #4caf50;
  color: white;
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 0.7rem;
  font-weight: 700;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s;
}

.strict-match-indicator.visible {
  opacity: 1;
}

/* ═══════════════════════════════════════════════════════════════
   MODAL VISIBILITY FIXES (merged from speak-easy-v27-modal-visibility.css)
   ═══════════════════════════════════════════════════════════════ */
/* =====================================================
   V27 SETTINGS MODAL - VISIBILITY STYLES (FIXED)
   
   FIXES:
   - Wider modal (900px instead of 800px)
   - Smaller tabs with no emoji wrapping
   - Button size support
   ===================================================== */

/* Modal Overlay */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.85);
  display: flex !important;
  align-items: center;
  justify-content: center;
  z-index: 20000;
  padding: 20px;
}

/* Modal Content Container - WIDER */
.modal-overlay .modal-content {
  background: var(--bg-primary, #1a1d21);
  border-radius: 16px;
  max-width: 900px; /* Changed from 800px */
  width: 100%;
  max-height: 90dvh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}

/* Modal Header */
.modal-overlay .modal-header {
  padding: 20px 24px;
  border-bottom: 1px solid var(--border-color, #333);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
}

.modal-overlay .modal-title {
  margin: 0;
  font-size: 1.5rem;
  color: var(--text-primary, #fff);
  font-weight: 600;
}

.modal-overlay .modal-close {
  background: none;
  border: none;
  font-size: 2rem;
  color: var(--text-primary, #fff);
  cursor: pointer;
  padding: 0;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color 0.2s;
}

.modal-overlay .modal-close:hover {
  color: #f6b347;
}

/* Tabs Container - SMALLER TABS */
.modal-overlay .tabs {
  display: flex;
  gap: 6px; /* Reduced from 8px */
  padding: 12px 16px; /* Reduced padding */
  border-bottom: 1px solid var(--border-color, #333);
  overflow-x: auto;
  flex-shrink: 0;
  background: var(--bg-secondary, #23272b);
  scrollbar-width: thin;
}

.modal-overlay .tabs::-webkit-scrollbar {
  height: 4px;
}

.modal-overlay .tabs::-webkit-scrollbar-track {
  background: var(--bg-secondary, #23272b);
}

.modal-overlay .tabs::-webkit-scrollbar-thumb {
  background: var(--border-color, #333);
  border-radius: 2px;
}

.modal-overlay .tab {
  padding: 6px 12px; /* Reduced from 8px 16px */
  border: 1px solid var(--border-color, #333);
  background: var(--bg-secondary, #23272b);
  color: var(--text-secondary, #888);
  border-radius: 6px; /* Slightly smaller radius */
  cursor: pointer;
  white-space: nowrap;
  font-size: 0.85rem; /* Slightly smaller */
  transition: all 0.2s;
  font-weight: 500;
  flex-shrink: 0;
}

.modal-overlay .tab:hover {
  background: var(--bg-tertiary, #2a2e33);
  color: var(--text-primary, #fff);
}

.modal-overlay .tab.active {
  background: #f6b347;
  color: #000;
  border-color: #f6b347;
  font-weight: 600;
}

/* Tab Panels Container */
.modal-overlay .tab-panels {
  flex: 1;
  overflow-y: auto;
  padding: 24px;
  color: var(--text-primary, #fff);
}

.modal-overlay .panel {
  display: none;
}

.modal-overlay .panel.active {
  display: block;
}

/* Setting Rows */
.modal-overlay .setting-row {
  display: flex;
  gap: 16px;
  margin-bottom: 16px;
  align-items: center;
}

.modal-overlay .setting-row label {
  flex: 1;
  color: var(--text-primary, #fff);
  font-weight: 500;
}

.modal-overlay .setting-input,
.modal-overlay .setting-slider {
  flex: 2;
}

.modal-overlay .setting-input {
  padding: 8px 12px;
  background: var(--bg-secondary, #23272b);
  color: var(--text-primary, #fff);
  border: 1px solid var(--border-color, #333);
  border-radius: 4px;
  font-size: 0.95rem;
}

.modal-overlay .setting-input:focus {
  outline: none;
  border-color: #f6b347;
}

.modal-overlay .setting-slider {
  cursor: pointer;
}

/* Buttons */
.modal-overlay .btn {
  padding: 12px 24px;
  background: #f6b347;
  color: #000;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  font-weight: 600;
  font-size: 0.95rem;
  transition: all 0.2s;
}

.modal-overlay .btn:hover {
  background: #f9c66d;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(246, 179, 71, 0.3);
}

.modal-overlay .btn:active {
  transform: translateY(0);
}

.modal-overlay .btn-danger {
  background: #dc3545;
  color: #fff;
}

.modal-overlay .btn-danger:hover {
  background: #c82333;
  box-shadow: 0 4px 12px rgba(220, 53, 69, 0.3);
}

/* Button Size Support - NEW */
/* Scoped to content area buttons only - excludes icon-btn, tab, key, and modal-close.
 * NOTE: These rules affect .tile (Quick Words/Phrases/Locked) and general .pb buttons.
 * The prediction chip restore block immediately below re-applies correct compact values
 * to word and phrase chips so they stay dense regardless of button-size setting. */
body[data-button-size="small"] .main .btn,
body[data-button-size="small"] .main .tile,
body[data-button-size="small"] .main .pb {
  font-size: 0.85rem !important;
  padding: 8px 16px !important;
}

body[data-button-size="medium"] .main .btn,
body[data-button-size="medium"] .main .tile,
body[data-button-size="medium"] .main .pb {
  font-size: 0.95rem !important;
  padding: 12px 24px !important;
}

body[data-button-size="large"] .main .btn,
body[data-button-size="large"] .main .tile,
body[data-button-size="large"] .main .pb {
  font-size: 1.1rem !important;
  padding: 16px 32px !important;
}

/* Prediction chips always stay compact — button-size setting must not inflate them.
 * This block restores authoritative prediction-chip values after the rules above. */
body[data-button-size] .pred-words .pb,
body[data-button-size] #predWordsRow1 .pb,
body[data-button-size] #predWordsRow2 .pb {
  padding: 4px 11px !important;
  font-size: 13px !important;
}

body[data-button-size] #predPhrasesRow1 .pb {
  padding: 7px 10px !important;
  font-size: 12px !important;
}

/* Dividers */
.modal-overlay hr {
  margin: 24px 0;
  border: none;
  border-top: 1px solid var(--border-color, #333);
}

/* Headings */
.modal-overlay h3 {
  margin: 0 0 20px 0;
  color: var(--text-primary, #fff);
  font-size: 1.3rem;
  font-weight: 600;
}

.modal-overlay h4 {
  color: var(--text-primary, #fff);
  margin: 16px 0 12px 0;
  font-size: 1.1rem;
  font-weight: 600;
}

.modal-overlay p {
  color: var(--text-secondary, #888);
  line-height: 1.6;
  margin-bottom: 12px;
}

/* Pack List */
.modal-overlay .pack-list {
  background: var(--bg-secondary, #23272b);
  border-radius: 8px;
  padding: 16px;
  margin-bottom: 24px;
}

.modal-overlay .pack-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px;
  background: var(--bg-tertiary, #2a2e33);
  border-radius: 4px;
  margin-bottom: 8px;
  color: var(--text-primary, #fff);
}

.modal-overlay .pack-item:last-child {
  margin-bottom: 0;
}

.modal-overlay .pack-status {
  color: #28a745;
  font-weight: 600;
  font-size: 0.9rem;
}

/* Warning Text */
.modal-overlay .warning-text {
  color: #dc3545;
  font-size: 0.9rem;
  margin-top: 8px;
  font-style: italic;
}

/* Lexicon Stats */
.modal-overlay .lexicon-stats {
  background: var(--bg-secondary, #23272b);
  padding: 16px;
  border-radius: 8px;
  margin-bottom: 16px;
  color: var(--text-primary, #fff);
}

.modal-overlay .lexicon-stats strong {
  color: #f6b347;
}

/* Placeholder Notice */
.modal-overlay .placeholder-notice {
  background: var(--bg-secondary, #23272b);
  border: 1px solid #f6b347;
  border-radius: 8px;
  padding: 20px;
  margin-top: 20px;
}

.modal-overlay .placeholder-notice strong {
  display: block;
  color: #f6b347;
  margin-bottom: 12px;
  font-size: 1.05rem;
}

.modal-overlay .placeholder-notice ul {
  margin: 0;
  padding-left: 20px;
  list-style-type: disc;
}

.modal-overlay .placeholder-notice li {
  color: var(--text-secondary, #888);
  margin-bottom: 8px;
}

/* Checkboxes */
.modal-overlay input[type="checkbox"] {
  width: 18px;
  height: 18px;
  cursor: pointer;
  margin-right: 8px;
}

.modal-overlay .setting-row label:has(input[type="checkbox"]) {
  display: flex;
  align-items: center;
  cursor: pointer;
}

/* Scrollbar for tab panels */
.modal-overlay .tab-panels::-webkit-scrollbar {
  width: 8px;
}

.modal-overlay .tab-panels::-webkit-scrollbar-track {
  background: var(--bg-secondary, #23272b);
}

.modal-overlay .tab-panels::-webkit-scrollbar-thumb {
  background: var(--border-color, #333);
  border-radius: 4px;
}

.modal-overlay .tab-panels::-webkit-scrollbar-thumb:hover {
  background: #555;
}

/* Responsive */
@media (max-width: 768px) {
  .modal-overlay {
    padding: 10px;
  }
  
  .modal-overlay .modal-content {
    max-height: 95dvh;
    max-width: 100%;
  }
  
  .modal-overlay .tabs {
    padding: 8px 12px;
    gap: 4px;
  }
  
  .modal-overlay .tab {
    padding: 6px 10px;
    font-size: 0.8rem;
  }
  
  .modal-overlay .tab-panels {
    padding: 16px;
  }
  
  .modal-overlay .setting-row {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
  }
  
  .modal-overlay .setting-input,
  .modal-overlay .setting-slider {
    width: 100%;
  }
}

/* ═══════════════════════════════════════════════════════════════
   PREDICTION CHIP LAYOUT
   Dead selectors (.prediction-button, #predictions, .pred-btn,
   .predictions-container, .prediction-area) removed 2026-04-09 —
   no matching elements in HTML or JS. Live rules retained below.
   ═══════════════════════════════════════════════════════════════ */

/* Word chips — auto-width so full word is always visible */
.pb {
  width: auto !important;
  min-width: 0 !important;
  max-width: none !important;
  white-space: nowrap !important;
  overflow: visible !important;
  text-overflow: clip !important;
  flex: 0 0 auto !important;
}

/* Prediction rows — horizontal flex, no wrap (measured pager handles paging) */
/* [g57 Session 54] Row3 added — fillPredRows() uses 3-row pages for phrase predictions. */
.pred,
#predWordsRow1,
#predWordsRow2,
#predPhrasesRow1,
#predPhrasesRow2,
#predPhrasesRow3 {
  display: flex !important;
  flex-wrap: nowrap !important;
  gap: 6px !important;
  overflow: visible !important;
  align-items: center !important;
}

/* ═══════════════════════════════════════════════════════════════
   ACCESSIBILITY IMPROVEMENTS
   ═══════════════════════════════════════════════════════════════ */

/* High contrast mode support */
@media (prefers-contrast: high) {
  .prediction-button,
  .pred-btn,
  #predictions button {
    border-width: 3px !important;
    font-weight: 600 !important;
  }
}

/* Reduced motion support */
@media (prefers-reduced-motion: reduce) {
  .prediction-button,
  .pred-btn,
  #predictions button {
    transition: none !important;
    transform: none !important;
  }
  
  .prediction-button:hover,
  .pred-btn:hover,
  #predictions button:hover {
    transform: none !important;
  }
}

/* Focus visible for keyboard navigation */
.prediction-button:focus-visible,
.pred-btn:focus-visible,
#predictions button:focus-visible {
  outline: 3px solid #0066cc !important;
  outline-offset: 2px !important;
}

/* ═══════════════════════════════════════════════════════════════
   SWITCH ACCESS OPTIMIZATION
   ═══════════════════════════════════════════════════════════════ */

/* Larger touch targets for switch users */
body.switch-access .prediction-button,
body.switch-access .pred-btn,
body.switch-access #predictions button {
  min-width: 100px !important;
  padding: 16px 20px !important;
  font-size: 18px !important;
}

/* ═══════════════════════════════════════════════════════════════
   UTILITY CLASSES
   ═══════════════════════════════════════════════════════════════ */

/* Force full visibility (emergency override) */
.prediction-full-width {
  width: 100% !important;
  max-width: 100% !important;
}

/* Compact mode (if needed for very small screens) */
.predictions-compact .prediction-button {
  min-width: 40px !important;
  padding: 6px 10px !important;
  font-size: 13px !important;
}

/* ═══════════════════════════════════════════════════════════════
   TESTING STYLES (Remove after confirming fix works)
   ═══════════════════════════════════════════════════════════════ */

/* Uncomment to see button boundaries during testing */
/*
.prediction-button,
.pred-btn,
#predictions button {
  outline: 2px dashed red !important;
  outline-offset: 2px !important;
}
*/

/* ═══════════════════════════════════════════════════════════════
   PREDICTIVE NAV ARROWS  (prev / next alongside dots)
   ═══════════════════════════════════════════════════════════════ */
/* ── AUTHORITATIVE pred-dot rule ─────────────────────────────────────────────
 * Must be top-level (not inside a media query) so it applies at all screen
 * sizes including desktop. Previously trapped inside @media(max-width:480px)
 * which meant it never applied on desktop — dots rendered as full-size buttons.
 * Edit here only.
 * ─────────────────────────────────────────────────────────────────────────── */
.pred-dot {
  width: 5px !important;
  height: 5px !important;
  min-width: 0 !important;
  min-height: 0 !important;
  padding: 0 !important;
  border-radius: 50% !important;
  border: none !important;
  cursor: pointer;
  background: rgba(255,255,255,.22);
  transition: background .2s, transform .15s;
  flex-shrink: 0;
  line-height: 1;
  display: block !important;
}
.pred-dot.active { background: var(--accent, #f6c177) !important; transform: scale(1.35); }
.pred-dot:hover  { background: rgba(255,255,255,.5) !important; }

/* ── AUTHORITATIVE pred-nav-btn rule ─────────────────────────────────────────
 * Compact arrows for word/phrase prediction row paging.
 * Edit here — do not add override blocks elsewhere.
 * Coarse (touch) devices get slightly larger tap targets but still compact.
 * ─────────────────────────────────────────────────────────────────────────── */
.pred-nav{display:flex;align-items:center;gap:2px;flex-shrink:0}
.pred-nav-btn{
  width:20px!important;min-width:0!important;height:20px!important;min-height:0!important;
  padding:0!important;border-radius:3px!important;
  border:1px solid rgba(255,255,255,.18)!important;
  background:rgba(255,255,255,.07)!important;
  color:var(--text2)!important;font-size:13px!important;line-height:1!important;cursor:pointer;
  flex-shrink:0;display:flex!important;align-items:center!important;justify-content:center!important;
  transition:background .15s,color .15s;touch-action:manipulation;
}
.pred-nav-btn:hover{background:rgba(255,255,255,.2)!important;color:var(--text1)!important}
.pred-nav-btn:disabled{opacity:.28;cursor:default}
@media(pointer:coarse){
  .pred-nav-btn{width:26px!important;height:26px!important;min-height:0!important;font-size:15px!important}
}

/* ═══════════════════════════════════════════════════════════════
   KEYNOTE TAB — FULL PANEL LAYOUT
   ═══════════════════════════════════════════════════════════════ */
body[data-mode="Keynote"] .main{display:none}
.keynote-panel{
  display:none;flex-direction:column;flex:1;overflow:hidden;
}
body[data-mode="Keynote"] .keynote-panel{
  display:flex;flex:1;overflow-y:auto;
}

/* Toolbar */
.kn-toolbar{
  display:flex;gap:8px;padding:8px 12px;
  border-bottom:var(--sep);background:var(--bg2);
  flex-wrap:wrap;align-items:center;flex-shrink:0;
  position:sticky;top:0;z-index:10;
}
.kn-toolbar .btn{font-size:.85rem;padding:6px 14px;white-space:nowrap}

/* Navigation hint bar */
.kn-nav-hint{
  display:flex;flex-wrap:wrap;align-items:center;gap:4px 10px;
  padding:6px 14px;
  font-size:.75rem;color:rgba(246,193,119,.7);
  background:rgba(246,193,119,.05);
  border-bottom:1px solid rgba(246,193,119,.1);
  line-height:1.4;
}
.kn-nav-hint strong{color:rgba(246,193,119,.9)}
.kn-nav-hint-sep{color:rgba(246,193,119,.25);font-size:.8rem}

/* Compose area */
.kn-compose{
  display:flex;flex-direction:column;gap:8px;
  padding:10px 12px;flex:1;
}
.kn-fields{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.kn-field-wrap{display:flex;flex-direction:column;gap:3px}
.kn-field-wrap label{
  font-size:.7rem;color:var(--text2);font-weight:700;
  text-transform:uppercase;letter-spacing:.04em;
}
.kn-field{
  background:var(--bg3);border:1px solid var(--border);
  border-radius:8px;padding:7px 10px;color:var(--text1);
  font-size:.9rem;width:100%;outline:none;transition:border-color .15s;
}
.kn-field:focus{border-color:var(--accent)}
.kn-field-numeric{width:80px}
.kn-textarea{
  width:100%;min-height:250px;
  background:var(--bg3);border:1px solid var(--border);
  border-radius:10px;padding:12px;color:var(--text1);
  font-size:1rem;line-height:1.7;resize:vertical;
  outline:none;font-family:inherit;transition:border-color .15s;
}
.kn-textarea:focus{border-color:var(--accent)}
.kn-char-hint{font-size:.72rem;color:var(--text2);text-align:right;margin-top:-4px}

/* Group view */
.kn-group-view{
  border-top:2px solid var(--accent);
  padding:10px 12px;
  background:rgba(255,183,77,.03);
  flex-shrink:0;
}
.kn-group-header{
  /* [g67 L11-3 §6] header TEXT → --accent-text (AA 4.5:1); border-left below keeps --accent (stroke, 3:1) */
  font-size:.8rem;color:var(--accent-text);font-weight:700;
  margin-bottom:10px;padding:5px 10px;
  background:rgba(255,183,77,.07);border-radius:6px;
  border-left:3px solid var(--accent);
  word-break:break-word;
}
.kn-block-row{
  display:flex;align-items:flex-start;gap:8px;
  padding:8px 0;border-bottom:var(--sep);
}
.kn-block-row:last-of-type{border-bottom:none}
.kn-block-num{
  flex-shrink:0;width:26px;font-size:.78rem;
  color:var(--text2);font-weight:700;padding-top:3px;text-align:right;
}
.kn-block-preview{
  flex:1;font-size:.88rem;color:var(--text1);
  line-height:1.5;word-break:break-word;
}
.kn-block-actions{display:flex;gap:4px;flex-shrink:0}
.kn-block-actions .btn{
  font-size:.75rem;padding:4px 8px;min-width:0;white-space:nowrap;
}
.kn-group-footer{
  display:flex;gap:8px;margin-top:10px;
  padding-top:8px;border-top:var(--sep);flex-wrap:wrap;
}

/* Library modal */
.kn-lib-modal{
  position:fixed;inset:0;background:rgba(0,0,0,.72);
  z-index:900;display:none;
  align-items:center;justify-content:center;padding:16px;
}
.kn-lib-inner{
  background:var(--bg2);border-radius:var(--radius);
  border:1px solid var(--border);width:100%;max-width:580px;
  max-height:88dvh;display:flex;flex-direction:column;
  overflow:hidden;box-shadow:var(--shadow);
}
.kn-lib-head{
  display:flex;align-items:center;gap:8px;
  padding:12px 16px;border-bottom:var(--sep);flex-shrink:0;
}
.kn-lib-head h4{margin:0;color:var(--accent-text);flex:1;font-size:1rem} /* [g67 L11-3 §6] heading TEXT → --accent-text */
.kn-lib-search-row{
  display:flex;gap:6px;padding:10px 14px;
  border-bottom:var(--sep);flex-shrink:0;align-items:center;
}
.kn-lib-search-input{
  flex:1;background:var(--bg3);border:1px solid var(--border);
  border-radius:8px;padding:7px 10px;color:var(--text1);
  font-size:.9rem;outline:none;
}
.kn-lib-search-input:focus{border-color:var(--accent)}
.kn-lib-results{flex:1;overflow-y:auto;padding:6px 10px}
.kn-lib-event,.kn-lib-title,.kn-lib-addr,.kn-lib-row{
  width:100%;display:flex;align-items:center;
  justify-content:space-between;text-align:left;
  background:none;border:none;
  border-bottom:1px solid rgba(255,255,255,.05);
  padding:9px 8px;color:var(--text1);font-size:.88rem;
  cursor:pointer;border-radius:6px;transition:background .15s;gap:8px;
}
.kn-lib-event:hover,.kn-lib-title:hover,
.kn-lib-addr:hover,.kn-lib-row:hover{background:rgba(255,255,255,.06)}
.kn-lib-expand{padding-left:16px}
.kn-lib-expand2{padding-left:32px}
.kn-lib-ev-count{font-size:.74rem;color:var(--text2);white-space:nowrap;flex-shrink:0}
.kn-lib-row{color:var(--accent-text);font-size:.84rem} /* [g67 L11-3 §6] row TEXT → --accent-text */
.kn-lib-row span{word-break:break-word}
.kn-lib-empty{
  padding:20px;text-align:center;color:var(--text2);
  font-style:italic;font-size:.88rem;
}

/* Presenter overlay */
.kn-teleprompter{
  position:fixed;inset:0;background:#0d0d0d;
  z-index:1000;display:none;flex-direction:column;
}
.kn-tele-controls-top{
  display:flex;align-items:center;justify-content:space-between;
  gap:12px;padding:10px 16px;
  background:rgba(255,255,255,.05);
  border-bottom:1px solid rgba(255,255,255,.1);
  flex-shrink:0;
}
.kn-tele-title{
  font-size:.78rem;color:rgba(255,183,77,.75);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  flex:1;min-width:0;
}
.kn-tele-scroll{flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch}
.kn-tele-text{
  padding:44px 10% 60px;color:#f0f0f0;
  font-size:1.8rem;line-height:1.95;
  white-space:pre-wrap;
}
/* Click-to-position sentence spans */
.kn-sentence{
  cursor:pointer;
  border-radius:4px;
  transition:background .15s;
  padding:2px 0;
}
.kn-sentence:hover{
  background:rgba(255,255,255,.12);
}
.kn-sentence--active{
  background:rgba(255,220,80,.18);
  color:#ffe98a;
}
.kn-tele-controls-bottom{
  display:flex;flex-direction:column;align-items:center;
  gap:8px;padding:10px 16px;
  background:rgba(255,255,255,.05);
  border-top:1px solid rgba(255,255,255,.1);
  flex-shrink:0;
}
.kn-tele-nav-row{display:flex;align-items:center;gap:14px}
.kn-tele-speak-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;justify-content:center}
/* Combined nav+speak row — Prev | counter | Next | SPEAK | (Pause) | (Stop) | Auto-next */
.kn-tele-nav-speak-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;justify-content:center}
.kn-tele-btn{
  background:rgba(255,255,255,.1)!important;
  border:1px solid rgba(255,255,255,.2)!important;
  color:#f0f0f0!important;border-radius:8px!important;
  padding:10px 20px!important;font-size:.9rem!important;
  cursor:pointer;transition:background .15s;
}
.kn-tele-btn:hover{background:rgba(255,255,255,.18)!important}
.kn-tele-nav-btn{
  background:rgba(255,255,255,.1)!important;
  border:1px solid rgba(255,255,255,.2)!important;
  color:#f0f0f0!important;border-radius:8px!important;
  padding:10px 24px!important;font-size:1rem!important;
  cursor:pointer;transition:background .15s;
}
.kn-tele-nav-btn:disabled{opacity:.28;cursor:default}
.kn-tele-nav-btn:not(:disabled):hover{background:rgba(255,255,255,.18)!important}
.kn-tele-counter{
  color:rgba(255,255,255,.45);font-size:.9rem;
  min-width:60px;text-align:center;
}
.kn-tele-speak-btn{
  background:var(--accent)!important;
  border:none!important;color:#fff!important;
  border-radius:10px!important;
  padding:14px 44px!important;font-size:1.1rem!important;font-weight:600!important;
  cursor:pointer;transition:opacity .15s;letter-spacing:.03em;
}
.kn-tele-speak-btn:hover{opacity:.86}
.kn-tele-stop-btn{
  background:rgba(220,60,60,.2)!important;
  border-color:rgba(220,60,60,.45)!important;
  color:#ff7070!important;
}
.kn-tele-stop-btn:hover{background:rgba(220,60,60,.35)!important}
.kn-auto-lbl{
  color:rgba(255,255,255,.6);font-size:.85rem;
  display:flex;align-items:center;gap:6px;cursor:pointer;white-space:nowrap;
}
.kn-auto-lbl input{cursor:pointer;accent-color:var(--accent);width:16px;height:16px}
/* Pause button */
.kn-tele-pause-btn{
  background:rgba(255,183,77,.15)!important;
  border-color:rgba(255,183,77,.4)!important;
  color:#ffb74d!important;
}
.kn-tele-pause-btn:hover{background:rgba(255,183,77,.28)!important}
/* Home / launcher link */
.kn-home-link{display:flex;align-items:center;flex-shrink:0;opacity:.7;transition:opacity .15s;text-decoration:none}
.kn-home-link:hover{opacity:1}
.kn-home-logo{height:28px;width:auto;border-radius:5px}
/* Tone presets row */
.kn-tele-tone-row{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:center;
  padding-bottom:8px;border-bottom:1px solid rgba(255,255,255,.08);
  width:100%;
}
.kn-tone-label{color:rgba(255,255,255,.4);font-size:.75rem;white-space:nowrap;flex-shrink:0}
.kn-tone-btn{
  background:rgba(255,255,255,.07)!important;
  border:1px solid rgba(255,255,255,.15)!important;
  color:rgba(255,255,255,.65)!important;
  border-radius:6px!important;padding:5px 11px!important;font-size:.8rem!important;
  cursor:pointer;transition:all .15s;flex-shrink:0;
}
.kn-tone-btn:hover{background:rgba(255,255,255,.14)!important;color:#fff!important}
.kn-tone-btn.active{
  background:rgba(255,183,77,.2)!important;
  border-color:#ffb74d!important;color:#ffb74d!important;
}
/* Pace + Pitch slider row */
.kn-tele-slider-row{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:center;
  padding-top:8px;padding-bottom:10px;border-bottom:1px solid rgba(255,255,255,.08);
  width:100%;
}
.kn-slider-label{color:rgba(255,255,255,.4);font-size:.75rem;white-space:nowrap;flex-shrink:0}
.kn-slider-label--gap{margin-left:18px}
.kn-tele-slider{
  width:140px;accent-color:#ffb74d;cursor:pointer;flex-shrink:0;
}
.kn-slider-val{
  color:rgba(255,255,255,.55);font-size:.78rem;
  min-width:42px;text-align:left;font-variant-numeric:tabular-nums;
}
/* Full screen enhancements */
:fullscreen .kn-tele-text,
:-webkit-full-screen .kn-tele-text{font-size:2.4rem;line-height:1.95;padding:60px 12% 80px}
:fullscreen .kn-tele-speak-btn,
:-webkit-full-screen .kn-tele-speak-btn{padding:20px 64px!important;font-size:1.4rem!important}
:fullscreen .kn-tele-nav-btn,
:-webkit-full-screen .kn-tele-nav-btn{padding:16px 36px!important;font-size:1.1rem!important}
:fullscreen .kn-tele-pause-btn,
:-webkit-full-screen .kn-tele-pause-btn{padding:16px 28px!important;font-size:1.05rem!important}
:fullscreen .kn-tone-btn,
:-webkit-full-screen .kn-tone-btn{padding:8px 16px!important;font-size:.9rem!important}
:fullscreen .kn-home-logo,
:-webkit-full-screen .kn-home-logo{height:34px}
@media(max-width:768px){
  .kn-tele-text{font-size:1.3rem;padding:28px 20px 40px}
  .kn-fields{grid-template-columns:1fr 1fr}
  .kn-block-actions{flex-wrap:wrap}
  @media(pointer:coarse){
    .kn-tele-speak-btn{padding:18px 44px!important;font-size:1.15rem!important}
    .kn-tele-nav-btn{padding:14px 28px!important}
  }
}

/* ═══════════════════════════════════════════════════════════════
   VOCAL SOUNDS — trigger button, modal, tiles
   ═══════════════════════════════════════════════════════════════ */

/* Sounds icon-btn active state (pulses when a sound is playing) */
#soundsBtn.ringing{animation:sounds-ring .5s ease}
@keyframes sounds-ring{
  0%{transform:scale(1)}25%{transform:scale(1.18)}75%{transform:scale(.95)}100%{transform:scale(1)}
}

/* Modal overlay */
.sounds-modal{
  position:fixed;inset:0;
  background:rgba(0,0,0,.62);
  z-index:900;
  display:flex;align-items:flex-end;justify-content:center;
  opacity:0;pointer-events:none;
  transition:opacity .2s;
}
.sounds-modal.open{opacity:1;pointer-events:all}

/* Modal inner (bottom sheet style) */
.sounds-inner{
  width:100%;max-width:640px;
  background:var(--bg2,#1e1e2a);
  border-radius:18px 18px 0 0;
  border:1px solid rgba(255,255,255,.1);
  border-bottom:none;
  padding:16px 16px 24px;
  transform:translateY(100%);
  transition:transform .25s cubic-bezier(.4,0,.2,1);
  max-height:90dvh;overflow-y:auto;
}
.sounds-modal.open .sounds-inner{transform:translateY(0)}

/* Header */
.sounds-header{
  display:flex;align-items:center;justify-content:space-between;
  margin-bottom:6px;
}
.sounds-title{
  font-size:1rem;font-weight:600;color:#fff;
}
.sounds-close-btn{
  background:rgba(255,255,255,.1)!important;
  border:1px solid rgba(255,255,255,.15)!important;
  color:var(--text2)!important;
  border-radius:50%!important;
  width:32px!important;height:32px!important;
  padding:0!important;font-size:.85rem!important;
  cursor:pointer;
}
.sounds-close-btn:hover{background:rgba(255,255,255,.2)!important;color:#fff!important}

/* Hint text */
.sounds-hint{
  font-size:.75rem;color:var(--text2);margin:0 0 10px;
}

/* Category filter bar */
.sounds-cat-bar{
  display:flex;gap:6px;flex-wrap:wrap;margin-bottom:12px;
}
.sounds-cat-btn{
  background:rgba(255,255,255,.07)!important;
  border:1px solid rgba(255,255,255,.14)!important;
  color:rgba(255,255,255,.6)!important;
  border-radius:20px!important;
  padding:4px 12px!important;font-size:.75rem!important;
  cursor:pointer;transition:all .15s;
}
.sounds-cat-btn:hover{background:rgba(255,255,255,.14)!important;color:#fff!important}
.sounds-cat-btn.active{
  background:rgba(255,183,77,.2)!important;
  border-color:#ffb74d!important;
  color:#ffb74d!important;
}

/* Sounds grid */
.sounds-grid{
  display:grid;
  grid-template-columns:repeat(4,1fr);
  gap:10px;
}

/* Individual tile */
.sounds-tile{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:5px;padding:14px 6px;
  background:rgba(255,255,255,.07)!important;
  border:1px solid rgba(255,255,255,.12)!important;
  border-radius:12px!important;
  cursor:pointer;
  transition:background .12s,transform .1s,border-color .12s;
  min-height:80px;
}
.sounds-tile:hover{
  background:rgba(255,255,255,.14)!important;
  border-color:rgba(255,255,255,.25)!important;
}
.sounds-tile:active{transform:scale(.93)}
.sounds-tile.speaking{
  background:rgba(255,183,77,.2)!important;
  border-color:#ffb74d!important;
  animation:sounds-pulse 0.7s ease infinite alternate;
}
@keyframes sounds-pulse{
  from{box-shadow:0 0 0 0 rgba(255,183,77,.3)}
  to{box-shadow:0 0 0 6px rgba(255,183,77,.0)}
}
.sounds-emoji{font-size:1.8rem;line-height:1;display:block}
.sounds-label{
  font-size:.72rem;color:rgba(255,255,255,.7);
  text-align:center;line-height:1.2;
}

/* Responsive */
@media(max-width:480px){
  .sounds-grid{grid-template-columns:repeat(3,1fr)}
  .sounds-inner{padding:14px 12px 20px}
}
@media(pointer:coarse){
  .sounds-tile{min-height:88px;padding:16px 8px}
  .sounds-emoji{font-size:2rem}
}

/* Synthesised-sound badge on tile */
.sounds-badge{
  position:absolute;top:5px;right:6px;
  font-size:.65rem;opacity:.55;
}
.sounds-tile{position:relative}


/* ═══════════════════════════════════════════════════════════════
   FULL BOARD REDESIGN v2 — JHACAL DARK NAVY  (2026-03-18)
   Faithfully ported from full-board-layout-mockup.html v0.4
   ═══════════════════════════════════════════════════════════════ */

/* ── Updated design tokens ── */
:root {
  --bg1:#1a1a2e;
  --bg2:#16213e;
  --bg3:#0f3460;
  --text1:#e0e0e0;
  --text2:#888;
  --border:#2a3a5a;
  --accent:#f5a623;          /* JHACAL orange — kept for pager dots, etc. */
  --accent1:#e94560;         /* red  — speak button */
  --accent2:#f5a623;         /* orange — match highlight, Complete label */
  --accent3:#1a7fbf;         /* blue  — SVO / more-words row */
  --bg-editor:#2a3a2a;       /* dark green — sentence editor */
  --qword-bg: #1e2440;
  --qword-btn:#263060;
  --qword-hover:#3040a0;
  --qphrase-bg:#201e30;
  --qphrase-btn:#302850;
  --qphrase-hover:#504080;
  --locked-bg:#1e2d1e;
  --locked-btn:#2a4a2a;
  --locked-hover:#3a6a3a;
  --predict-bg:#1a2030;
  --predict-btn:#22304a;
  --predict-hover:#2a4060;
  --word-predict-bg:#161a26;
  --word-chip-bg:#222a3a;
  --word-chip-border:#333;
  --word-chip2-bg:#1e2a3a;
  --word-chip2-border:#2a3a4a;
  --radius:8px;
  --radius-sm:5px;
}

/* ── Global background to JHACAL deep navy ── */
html, body {
  background: #111 !important;
}

/* ── App container ── */
.app {
  background: var(--bg1);
}

/* ── Header ── */
.header-top {
  background: #0d1b2a !important;
  border-bottom: 1px solid var(--border) !important;
}

/* ── Launch button — orange JHACAL style ── */
.header-top .btn,
a.btn[href*="launch"],
button#launchBtn,
.btn[data-action="launch"] {
  background: var(--accent2) !important;
  color: #000 !important;
  border: none !important;
  font-weight: 700 !important;
  border-radius: var(--radius-sm) !important;
}

/* ── Nav tabs — uppercase pill style matching mockup ── */
.tabs-bar,
nav.tabs {
  background: var(--bg2) !important;
  border-bottom: 1px solid var(--border) !important;
}

.tab-link, .tab-btn, nav .tab {
  font-size: 11px !important;
  font-weight: 600 !important;
  letter-spacing: 0.5px !important;
  text-transform: uppercase !important;
  color: var(--text2) !important;
  border-bottom: 2px solid transparent !important;
  padding: 8px 15px !important;
  background: transparent !important;
  border-radius: 0 !important;
}

.tab-link.active, .tab-btn.active, nav .tab.active {
  color: var(--text1) !important;
  border-bottom-color: var(--accent1) !important;
}

/* ── Main two-col grid ── */
.main {
  background: var(--bg1);
  gap: 0 !important;
  border-radius: 0 !important;
}

.left, .right {
  background: transparent !important;
  border: none !important;
  border-radius: 0 !important;
  padding: 0 !important;
}

/* Left col gets a right border, full height */
.left {
  border-right: 1px solid var(--border) !important;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overflow-x: hidden;
}

/* ── Section strip base — remove old pill header style ── */
.section {
  padding: 7px !important;
  border-bottom: 1px solid var(--border) !important;
  border-radius: 0 !important;
  flex-shrink: 0;
}

/* Section headers — small uppercase label, no pill background */
.section h4,
.sectionRow h4 {
  font-size: 10px !important;
  font-weight: 700 !important;
  letter-spacing: 1.2px !important;
  color: var(--text2) !important;
  text-transform: uppercase !important;
  background: transparent !important;
  border: none !important;
  border-radius: 0 !important;
  padding: 2px 3px 5px !important;
  text-align: left !important;
}

/* ── Quick Words section ── */
.section-qwords {
  background: var(--qword-bg);
}

/* Quick Word tiles — rounded rect, blue-navy tint */
.grid-quick .tile,
#quickGrid .tile {
  background: var(--qword-btn) !important;
  border: 1px solid #334 !important;
  color: var(--text1) !important;
  border-radius: var(--radius-sm) !important;
  font-size: 13px !important;
  font-weight: 500 !important;
  padding: 9px 5px !important;
  min-height: 40px !important;
  text-align: center !important;
  box-shadow: none !important;
}

.grid-quick .tile:hover,
#quickGrid .tile:hover {
  background: var(--qword-hover) !important;
  color: #fff !important;
}

/* ── Quick Phrases section ── */
.section-qphrases {
  background: var(--qphrase-bg);
}

/* Quick Phrase tiles — wider list style, purple-navy tint */
.grid-phr .tile,
#phrGrid .tile {
  background: var(--qphrase-btn) !important;
  border: 1px solid #3a3060 !important;
  color: var(--text1) !important;
  border-radius: var(--radius-sm) !important;
  font-size: 12px !important;
  font-weight: 400 !important;
  padding: 8px 9px !important;
  min-height: 38px !important;
  text-align: left !important;
  line-height: 1.3 !important;
  box-shadow: none !important;
  white-space: normal !important;
}

.grid-phr .tile:hover,
#phrGrid .tile:hover {
  background: var(--qphrase-hover) !important;
}

/* ── Locked section ── */
.section-locked {
  background: var(--locked-bg) !important;
  margin-top: auto;
  border-top: 1px solid var(--border);
  border-bottom: none !important;
}

/* Locked tiles — green-navy tint, slightly larger */
.grid-perm .tile,
#permGrid .tile {
  background: var(--locked-btn) !important;
  border: 1px solid #3a5a3a !important;
  color: var(--text1) !important;
  border-radius: var(--radius-sm) !important;
  font-size: 14px !important;
  font-weight: 600 !important;
  padding: 10px 7px !important;
  min-height: 44px !important;
  text-align: center !important;
  box-shadow: none !important;
}

.grid-perm .tile:hover,
#permGrid .tile:hover {
  background: var(--locked-hover) !important;
}

/* ── Locked reveal label ── */
.locked-reveal-label {
  display: none;
  background: #1a2e1a;
  border-top: 1px solid #3a5a3a;
  padding: 7px 10px;
  font-size: 11px;
  color: #7ab87a;
  cursor: pointer;
  text-align: center;
  flex-shrink: 0;
  letter-spacing: 0.3px;
  transition: background 0.15s;
  position: sticky;
  bottom: 0;
}

.locked-reveal-label:hover {
  background: #223e22;
  color: #9ad89a;
}

body.keyboard-open .locked-reveal-label {
  display: block;
}

/* ── Right col: compose zone ── */
.compose {
  width: 100% !important;
  margin: 0 !important;
  background: var(--bg2);
  padding: 0 !important;
}

/* Sentence editor */
/* V27.4 fix: was `font-size: 15px !important` — overrode the slider variable at every
   viewport because this block appears after the earlier .sentence rule AND uses !important.
   Now scales with --se-compose-font-scale like the other .sentence rules do. */
.sentence {
  background: var(--bg-editor) !important;
  border: 1px solid #3a5a3a !important;
  border-radius: var(--radius-sm) !important;
  color: var(--text1) !important;
  font-size: calc(15px * var(--se-compose-font-scale, 1)) !important;
  padding: 9px 11px !important;
  caret-color: var(--accent2) !important;
}

.sentence[contenteditable]:focus {
  border-color: #5a8a5a !important;
  box-shadow: none !important;
}

.sentence.placeholder {
  color: #555 !important;
}

/* Sub-controls row */
.sub-controls {
  padding: 7px 9px !important;
  background: var(--bg2) !important;
  border-top: 1px solid var(--border) !important;
}

/* [Batch 38 g98 2026-04-24 · Q10 / Item F] Speak + Clear converted to
   icon-only earthy-palette buttons matching Mobile's Zone 4 cluster.
   Ids preserved (#speakBtn = earthy green #556B2F, #clearBtn = earthy
   sienna #A0522D). Order in index.html: Speak then Clear (Q10). */

/* Shared icon-button container */
.se-compose-iconbtn {
  width: 44px !important;
  min-width: 44px !important;
  height: 44px !important;
  padding: 0 !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  border: 1px solid rgba(0,0,0,0.35) !important;
  border-radius: var(--radius-sm) !important;
  cursor: pointer !important;
  transition: background-color 120ms ease, border-color 120ms ease,
              transform 80ms ease, box-shadow 120ms ease !important;
}
.se-compose-iconbtn:active { transform: scale(0.96) !important; }
.se-compose-iconbtn:focus-visible {
  outline: 2px solid #6B8E23 !important;
  outline-offset: 2px !important;
}

/* Speak — earthy dark olive */
.se-compose-iconbtn--speak {
  background: #556B2F !important;
  border-color: #455923 !important;
  box-shadow: 0 1px 4px rgba(85, 107, 47, 0.40) !important;
}
.se-compose-iconbtn--speak:hover {
  background: #4a5f28 !important;
  border-color: #3b4c1e !important;
}
.se-compose-iconbtn--speak:active {
  background: #455923 !important;
  box-shadow: 0 1px 2px rgba(85, 107, 47, 0.5) inset !important;
}

/* Clear — earthy sienna */
.se-compose-iconbtn--clear {
  background: #A0522D !important;
  border-color: #834025 !important;
  box-shadow: 0 1px 4px rgba(160, 82, 45, 0.35) !important;
}
.se-compose-iconbtn--clear:hover {
  background: #8d4425 !important;
  border-color: #73371e !important;
}
.se-compose-iconbtn--clear:active {
  background: #834025 !important;
  box-shadow: 0 1px 2px rgba(160, 82, 45, 0.5) inset !important;
}

/* Icon glyphs — pure CSS unicode, no icon font */
.se-compose-ico {
  display: inline-block;
  width: 22px;
  height: 22px;
  line-height: 22px;
  text-align: center;
  font-family: -apple-system, "Segoe UI Symbol", "Noto Sans Symbols 2",
               "Apple Color Emoji", "Segoe UI Emoji", system-ui, sans-serif;
  font-size: 20px;
  font-weight: 700;
  color: #fff;
  pointer-events: none;
  user-select: none;
}
.se-compose-ico--speak::before { content: "\1F5E3"; /* 🗣 speaking head */ }
.se-compose-ico--clear::before { content: "\2715"; /* ✕ */ font-weight: 800; }

/* [g60 housekeeping] #savePhraseBtn styling block removed — element was
   deleted in g58, see the matching hide-rules removal at ~line 487. */

/* ── Word prediction zone ── */
.pred-words {
  background: var(--word-predict-bg) !important;
  border-top: 1px solid var(--border) !important;
  padding: 0 !important;
  overflow: hidden;
  display: flex !important;
  flex-direction: column !important;
}

/* ── AUTHORITATIVE Row 1 bar and Row 2 wrap layout ───────────────────────────
 * Padding set here. Do not add padding overrides elsewhere.
 * ─────────────────────────────────────────────────────────────────────────── */
.pred-row1-bar {
  padding: 4px 8px !important;
  border-bottom: 1px solid #1e2436 !important;
  overflow: hidden !important;
  display: flex !important;
  align-items: center !important;
  gap: 5px !important;
}

.pred-row2-wrap {
  display: flex !important;
  align-items: center !important;
  gap: 5px !important;
  padding: 3px 8px !important;
  border-left: none !important;
  margin-top: 0 !important;
}

/* Pred-rows inside word zone: no forced min-height — let chips define height */
.pred-words .pred-row,
.pred-row1-bar .pred-row,
.pred-row2-wrap .pred-row {
  min-height: 0 !important;
  height: auto !important;
}

/* Row label badges */
.pred-row-label {
  font-size: 9px !important;
  font-weight: 700 !important;
  letter-spacing: 0.8px !important;
  text-transform: uppercase !important;
  white-space: nowrap !important;
  flex-shrink: 0 !important;
  padding: 0 4px 0 0 !important;
  border: none !important;
  background: transparent !important;
  border-radius: 0 !important;
}

.row1-label { color: var(--accent2) !important; }
.row2-label { color: #6a8aaa !important; }

/* ── AUTHORITATIVE word chip rule ────────────────────────────────────────────
 * These selectors cover Row 1 completion chips and Row 2 SVO next-word chips.
 * ALL visual properties for word chips are defined HERE and nowhere else.
 * Do not add padding/font-size/border-radius/line-height overrides anywhere
 * else in this file — edit this block directly when changes are needed.
 * Matches mockup .word-chip exactly: padding:4px 11px, font:13px, radius:20px
 * ─────────────────────────────────────────────────────────────────────────── */
.pred-words .pb,
#predWordsRow1 .pb,
#predWordsRow2 .pb {
  background: var(--word-chip-bg) !important;
  border: 1px solid var(--word-chip-border) !important;
  color: var(--text1) !important;
  padding: 4px 11px !important;
  border-radius: 20px !important;
  font-size: 13px !important;
  line-height: 1.2 !important;
  min-height: 0 !important;
  min-width: 0 !important;
  box-sizing: border-box !important;
  max-width: none !important;
  white-space: nowrap !important;
}

.pred-words .pb:hover,
#predWordsRow1 .pb:hover {
  background: #2a3a5a !important;
  border-color: var(--accent) !important;
}

/* Row 2 chips — slightly different blue tint */
#predWordsRow2 .pb {
  background: var(--word-chip2-bg) !important;
  border-color: var(--word-chip2-border) !important;
  color: #b0c8e0 !important;
}

#predWordsRow2 .pb:hover {
  background: #283a50 !important;
  border-color: #4a7aaa !important;
}

/* ── Keyword search bar ── */
.keyword-search-bar {
  background: var(--bg2) !important;
  border-top: 1px solid var(--border) !important;
  padding: 6px 9px !important;
}

#keywordSearch {
  background: #1e2840 !important;
  border: 1px solid var(--border) !important;
  border-radius: var(--radius-sm) !important;
  color: var(--text1) !important;
  padding: 6px 9px !important;
  font-size: 13px !important;
}

#keywordSearch:focus {
  border-color: var(--accent1) !important;
  outline: none !important;
}

#clearKeyword {
  background: #3a3a3a !important;
  border: none !important;
  color: var(--text2) !important;
  border-radius: var(--radius-sm) !important;
  padding: 6px 9px !important;
  font-size: 12px !important;
}
#clearKeyword:hover { background: #555 !important; color: var(--text1) !important; }

/* ── Phrase prediction zone ── */
/* [g57 Session 54] Visual skin only; layout properties come from the baseline
   .pred-phr rule at ~line 442 (flex-direction:column, overflow:hidden, gap:6px).
   min-height raised to 140px so the 3-row fillPredRows() pager has headroom to
   show ~10–12 packed phrase chips per page on Full Board. flex:1 1 auto lets
   .pred-phr consume remaining compose-column height when available, while still
   guaranteeing the 140px floor. */
.pred-phr {
  background: var(--predict-bg) !important;
  border-top: 1px solid var(--border) !important;
  padding: 6px 7px !important;
  gap: 6px !important;
  min-height: 140px !important;
  flex: 1 1 auto !important;
}

/* ── AUTHORITATIVE phrase button rule ────────────────────────────────────────
 * [g57 Session 54] Trimmed to colour/border/radius only. Layout (width, display,
 * white-space, line-height, padding, max-width) comes from the baseline
 * .pb rule at ~line 451 and the .phr .pb override at ~line 459, both of which
 * set the horizontal-pack-friendly sizing needed by the fillPredRows() pager.
 * Previously this block forced width:100% + display:block + white-space:normal,
 * which defeated horizontal packing — the symptom Pete flagged in g56 (14
 * keyword matches paginated 1-per-page). Edit the baseline rules at ~line 451
 * and ~line 459 for layout changes; edit THIS block only for colour changes.
 * ─────────────────────────────────────────────────────────────────────────── */
.pred-phr .pb,
.phr-row .pb,
#predPhrasesRow1 .pb,
#predPhrasesRow2 .pb,
#predPhrasesRow3 .pb {
  background: var(--predict-btn) !important;
  border: 1px solid #2a3848 !important;
  color: var(--text1) !important;
  border-radius: var(--radius-sm) !important;
}

.pred-phr .pb:hover,
.phr-row .pb:hover {
  background: var(--predict-hover) !important;
  border-color: var(--accent1) !important;
}

/* [g57 Session 54] Vertical-list override removed. Phrase rows are now horizontal
   (flex-direction:row) to match the fillPredRows() measured paginator that was
   wired in g56 Part A. Baseline rules at ~line 450 (.pred-row) and ~line 1322
   (#predPhrasesRow1/2) set horizontal flex-nowrap for all three phrase rows;
   no override needed here. Previously this block forced flex-direction:column
   with align-items:stretch, causing chips to stack full-width and breaking the
   pager's horizontal packing. */

/* ── Match highlight system ── */
.match-hl {
  color: var(--accent2);
  font-weight: 700;
}

/* ── Keyboard-open reflow ── */
body.keyboard-open .pred-phr {
  max-height: 130px;
  overflow-y: auto;
}

body.keyboard-open .pred-row1-bar,
body.keyboard-open .pred-row2-wrap {
  padding-top: 3px !important;
  padding-bottom: 3px !important;
}

/* [L12-7 g34 Deploy B.2] Sticky-pin the prediction rows to the bottom of the
   visible (non-keyboard) viewport when the soft keyboard is open.
   Rationale: Deploy A (vh→dvh) had no effect on iOS/iPadOS because iOS treats
   the keyboard as an overlay — dvh does not shrink. The 'keyboard-open' class
   IS applied by speak-easy-app.js initSoftKeyboardAdapt() via visualViewport,
   so we ride that signal here instead. Sticky positioning keeps the rows
   above the keyboard fold without relying on viewport unit behaviour.
   z-index 5 beats surrounding tiles but stays below modals (z-index 1000+). */
body.keyboard-open .pred-row1-bar,
body.keyboard-open .pred-row2-wrap,
body.keyboard-open .pred-phr {
  position: sticky;
  bottom: 0;
  background: var(--bg2, #141821);
  z-index: 5;
  box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.35);
}

/* ── Hide row 2 wrap when row 2 has no buttons (JS will add .empty) ── */
.pred-row2-wrap.is-empty {
  display: none;
}

/* ── Phrase grid: single column (full-width list like mockup) ── */
.section-qphrases .grid-phr,
.section-qphrases #phrGrid {
  grid-template-columns: 1fr !important;
}

/* ── Quick words grid: 3 col ── */
.section-qwords .grid-quick,
.section-qwords #quickGrid {
  grid-template-columns: repeat(3, 1fr) !important;
}

/* ── Locked grid: 2 col ── */
.section-locked .grid-perm,
.section-locked #permGrid {
  grid-template-columns: repeat(2, 1fr) !important;
}

/* ── Tile font: sans-serif to match mockup ── */
.grid-quick .tile,
.grid-phr .tile,
.grid-perm .tile {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
}

/* ── Tile hover: no box-shadow, just background colour change ── */
.tile:hover {
  box-shadow: none !important;
}

/* ═══════════════════════════════════════════════════════════════
   FULL BOARD FIXES v3  (2026-03-18)
   1. Locked section: normal flow, never pushed off-screen
   2. Row 2 word chips: always visible, hide only when truly empty
   3. Nav dots/arrows: compact size matching mockup
   4. Phrase list: proper vertical scroll, compact rows
   ═══════════════════════════════════════════════════════════════ */

/* ── 1. Locked section — normal flow at bottom of left col ──────── */
/* Remove margin-top:auto which was pushing it off-screen.
   Left column scrolls, so locked is always reachable by scrolling. */
.section-locked {
  margin-top: 0 !important;
  border-top: 1px solid var(--border) !important;
  background: var(--locked-bg) !important;
  border-bottom: none !important;
  flex-shrink: 0;
}

/* ── 2. Row 2 word prediction wrap — keep visible ───────────────── */
/* Only hide when truly empty AND keyboard is not open */
.pred-row2-wrap.is-empty {
  display: flex !important;   /* override the display:none — keep label visible */
  opacity: 0.35;               /* dim it when empty so user knows no predictions */
}

/* ── 3. Pager dots and nav arrows ────────────────────────────────── */
/* .pred-nav-btn is authoritative in the main layout block above.
 * .pred-dot is authoritative at top level (search for "AUTHORITATIVE pred-dot rule").
 * No overrides needed here. */

/* .pred-dot size — set in AUTHORITATIVE top-level block (search "AUTHORITATIVE pred-dot rule"). */

/* Left-col pager dots (Quick Words / Quick Phrases pagers) */
.pager .dot {
  width: 5px !important;
  height: 5px !important;
}

/* ── AUTHORITATIVE pager nav arrows (left col Quick Words / Phrases pagers) ──
 * Edit here. Do not add override blocks elsewhere.
 * ─────────────────────────────────────────────────────────────────────────── */
.pager .btn,
.sectionRow .pager button {
  width: 18px !important;
  height: 18px !important;
  min-width: 0 !important;
  min-height: 0 !important;
  padding: 0 !important;
  font-size: 11px !important;
  line-height: 18px !important;
  border-radius: 3px !important;
  background: rgba(255,255,255,.08) !important;
  border: 1px solid rgba(255,255,255,.15) !important;
  color: var(--text2) !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
}

.pager .btn:hover,
.sectionRow .pager button:hover {
  background: var(--bg-card-hover, #1a4a80) !important;
  color: var(--text1) !important;
}

/* [g57 Session 54] Pre-g56 vertical-scrollable-list renderer block removed.
   The three rules it contained all defeated the fillPredRows() horizontal pager
   that g56 Part A wired in:
     - `.pred-phr { flex-direction:column; overflow:hidden }` — duplicated the
       baseline at ~line 442; redundant and with different values.
     - `#predPhrasesRow1 { flex-direction:column; overflow-y:auto }` — forced
       Row1 to stack chips vertically and scroll, making the pager irrelevant.
     - `#predPhrasesRow2, #predPhrasesRow3 { display:none }` — hid 2/3 of the
       available rows the pager was generating content for, leaving only ~1
       phrase visible per page on every keyword-match list.
   Row-level hover styling was also redundant — .pred-phr .pb:hover at ~line
   2378 already covers all three rows (Row1/2/3 are descendants of .pred-phr). */

/* phrase nav — now hidden since we use scroll, but keep for keyword mode */
.pred-phr .pred-row1-bar {
  display: flex !important;
  align-items: center !important;
  gap: 4px !important;
  flex-shrink: 0 !important;
  padding: 0 0 4px 0 !important;
  border-bottom: none !important;
  overflow: visible !important;
}

/* ═══════════════════════════════════════════════════════════════
   FULL BOARD DENSITY FIX v4  (2026-03-18)
   - Reduce tile min-height and padding to match mockup density
   - Fix Launch button to match mockup orange pill
   - Fix nav dots/arrows still too large
   ═══════════════════════════════════════════════════════════════ */

/* ── Tighten global tile size tokens ─────────────────────────── */
:root {
  --tile-min-h: 36px;       /* was 54px — match mockup ~9px top+bottom padding */
  --tile-min-h-sm: 30px;    /* was 40px */
  --tile-font: 0.82rem;     /* was 1.05rem — mockup uses 13px ≈ 0.81rem */
  --tile-font-sm: 0.75rem;  /* was 0.92rem */
  --pill-pad: 4px 11px;     /* was 7px 9px — word chip matches mockup 4px 11px */
  --pill-font: 0.81rem;     /* was 0.78rem — mockup uses 13px */
}

/* ── Tile padding override (base .tile rule has its own padding) ─ */
.tile {
  padding: 7px 6px !important;
  min-height: var(--tile-min-h) !important;
  font-size: var(--tile-font) !important;
  font-weight: 600 !important;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
  border-radius: var(--radius-sm) !important;
  line-height: 1.2 !important;
}

.tile.small {
  padding: 5px 6px !important;
  min-height: var(--tile-min-h-sm) !important;
  font-size: var(--tile-font-sm) !important;
}

/* Quick phrase tiles: full-width, left-aligned, allow wrap */
.section-qphrases .tile {
  white-space: normal !important;
  text-align: left !important;
  justify-content: flex-start !important;
  padding: 7px 9px !important;
}

/* ── Section padding tighter ─────────────────────────────────── */
.section {
  padding: 5px 6px !important;
}

.section h4,
.sectionRow h4 {
  padding: 1px 2px 4px !important;
  margin: 0 !important;
}

.sectionRow {
  margin: 0 0 3px !important;
}

/* Grid gaps tighter */
.grid {
  gap: 4px !important;
}

/* ── Launch button — orange pill matching mockup ─────────────── */
#btnLaunchPage {
  background: var(--accent2) !important;
  color: #000 !important;
  border: none !important;
  border-radius: 4px !important;
  padding: 4px 11px !important;
  font-size: 11px !important;
  font-weight: 700 !important;
  cursor: pointer !important;
}

#btnLaunchPage:hover {
  background: #d4911f !important;
  color: #000 !important;
}

/* Nav dots/arrows — all authoritative rules are in their definitions above.
 * .pager .btn: FULL BOARD REDESIGN v2 section
 * .pred-nav-btn: main layout block
 * .pred-dot: top-level block (search "AUTHORITATIVE pred-dot rule")
 * No overrides needed here. */

/* .pred-dot size — set in AUTHORITATIVE top-level block (search "AUTHORITATIVE pred-dot rule"). */

/* All word chip, pred-row, and phrase button sizing rules have been
 * consolidated into their authoritative blocks in the FULL BOARD REDESIGN v2
 * section above. No overrides needed here — those blocks are the source of
 * truth. Do not add padding/font-size/line-height rules here for these
 * selectors; edit the authoritative blocks directly. */

/* ===== Send-to-Teams confirmation toast (V27.3 Teams Integration) ===== */
.se-teams-toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--bg2);
  color: var(--text1);
  padding: 10px 16px;
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent2);
  border-radius: var(--radius);
  font-size: 14px;
  z-index: 99999;
  box-shadow: var(--shadow);
  max-width: 80vw;
  text-align: center;
}

/* ===== Fuzzy-match prediction chips (V27.4 Typing & Spelling) =====
   Edit-distance-1 corrections surfaced by getPredictions() fuzzy fallback.
   Visual tell: leading "?" in accent colour + italic body, so the user can
   distinguish a correction ("did you mean") from a confident completion. */
.pb.fuzzy {
  font-style: italic;
  border-color: var(--accent2);
}
.pb.fuzzy::before {
  content: "?";
  font-style: normal;
  font-weight: 700;
  color: var(--accent2);
  margin-right: 4px;
  opacity: 0.85;
}
.pb.fuzzy:hover {
  background: var(--accent2);
  color: #fff;
}
.pb.fuzzy:hover::before {
  color: #fff;
  opacity: 1;
}

/* [g68 L10-2 Phase 3] HC token bridge — Speak-Easy local navy palette
   flips to shared HC hex values when body.jhacal-high-contrast is active.
   Zero !important; pure cascade. --accent/--accent1/--accent2/--accent3
   all collapse to the high-vis yellow so brand-distinction is sacrificed
   for readability (consistent with jhacal-design-tokens.css HC block). */
body.jhacal-high-contrast{
  --bg1:#000;
  --bg2:#111;
  --bg3:#1a1a1a;
  --text1:#fff;
  --text2:#fff;
  --border:#fff;
  --accent:#ffeb3b;
  --accent1:#ff6b7a;       /* red → HC danger red */
  --accent2:#ffeb3b;
  --accent3:#ffeb3b;
  --bg-editor:#111;
}


/* ============================================================
   [Batch 40 g112 2026-04-24] Speak-Easy mode-color differentiation.
   Each tab tints the .sentence editor border, focus ring, and the active
   tab's underline. Same JHACAL earthy palette as Mobile zone colors.
   Glanceable mode awareness; reinforces suite cohesion across apps.
   ============================================================ */

:root {
  --se-mode-color-fullboard: #f6c177;   /* gold — canonical home view */
  --se-mode-color-compose:   #4A6480;   /* slate blue — writing/thinking */
  --se-mode-color-announce:  #6B7847;   /* sage green — Quick Speak / rapid action */
  --se-mode-color-tablet:    #C5A572;   /* warm tan — tablet variation */
  --se-mode-color-keynote:   #7A3B2E;   /* deep maroon — gravitas / important */
}

/* Sentence editor border tint per mode */
body[data-mode="FullBoard"] .sentence { border-color: var(--se-mode-color-fullboard) !important; }
body[data-mode="Compose"]   .sentence { border-color: var(--se-mode-color-compose)   !important; }
body[data-mode="Announce"]  .sentence { border-color: var(--se-mode-color-announce)  !important; }
body[data-mode="Tablet"]    .sentence { border-color: var(--se-mode-color-tablet)    !important; }
body[data-mode="Keynote"]   .sentence { border-color: var(--se-mode-color-keynote)   !important; }

/* Focus ring picks up the same color */
body[data-mode="FullBoard"] .sentence[contenteditable]:focus { box-shadow: 0 0 0 2px color-mix(in oklab, var(--se-mode-color-fullboard) 30%, transparent) !important; }
body[data-mode="Compose"]   .sentence[contenteditable]:focus { box-shadow: 0 0 0 2px color-mix(in oklab, var(--se-mode-color-compose)   30%, transparent) !important; }
body[data-mode="Announce"]  .sentence[contenteditable]:focus { box-shadow: 0 0 0 2px color-mix(in oklab, var(--se-mode-color-announce)  30%, transparent) !important; }
body[data-mode="Tablet"]    .sentence[contenteditable]:focus { box-shadow: 0 0 0 2px color-mix(in oklab, var(--se-mode-color-tablet)    30%, transparent) !important; }
body[data-mode="Keynote"]   .sentence[contenteditable]:focus { box-shadow: 0 0 0 2px color-mix(in oklab, var(--se-mode-color-keynote)   30%, transparent) !important; }

/* Active tab gets a colored underline matching the mode */
body[data-mode="FullBoard"] .tab.active { box-shadow: inset 0 -3px 0 0 var(--se-mode-color-fullboard); }
body[data-mode="Compose"]   .tab.active { box-shadow: inset 0 -3px 0 0 var(--se-mode-color-compose); }
body[data-mode="Announce"]  .tab.active { box-shadow: inset 0 -3px 0 0 var(--se-mode-color-announce); }
body[data-mode="Tablet"]    .tab.active { box-shadow: inset 0 -3px 0 0 var(--se-mode-color-tablet); }
body[data-mode="Keynote"]   .tab.active { box-shadow: inset 0 -3px 0 0 var(--se-mode-color-keynote); }

/* [g120] Focus border-colour per mode -- previously the focus state fell
   through to a greenish #5a8a5a from a higher-specificity .sentence:focus
   override at line ~2183, ignoring the mode tint. Add the mode colour to
   the focus state at the same specificity level as the override. */
body[data-mode="FullBoard"] .sentence[contenteditable]:focus { border-color: var(--se-mode-color-fullboard) !important; }
body[data-mode="Compose"]   .sentence[contenteditable]:focus { border-color: var(--se-mode-color-compose)   !important; }
body[data-mode="Announce"]  .sentence[contenteditable]:focus { border-color: var(--se-mode-color-announce)  !important; }
body[data-mode="Tablet"]    .sentence[contenteditable]:focus { border-color: var(--se-mode-color-tablet)    !important; }
body[data-mode="Keynote"]   .sentence[contenteditable]:focus { border-color: var(--se-mode-color-keynote)   !important; }

/* [g120] Subtle header accent line per mode -- 2px coloured strip at the
   bottom of .header so the active mode is visible even when the sentence
   editor is out of view. Uses border-bottom because .header already has
   a 1px border. Pete's directive 2026-04-26: "an optional subtle accent
   line under the header." */
body[data-mode="FullBoard"] .header { border-bottom: 2px solid var(--se-mode-color-fullboard); }
body[data-mode="Compose"]   .header { border-bottom: 2px solid var(--se-mode-color-compose); }
body[data-mode="Announce"]  .header { border-bottom: 2px solid var(--se-mode-color-announce); }
body[data-mode="Tablet"]    .header { border-bottom: 2px solid var(--se-mode-color-tablet); }
body[data-mode="Keynote"]   .header { border-bottom: 2px solid var(--se-mode-color-keynote); }


/* ============================================================
   [Batch 40 g112 2026-04-24] Speak-Easy screen-jump fix.
   Mode tabs (Full Board / Compose / Quick Speak / Tablet) used to
   show/hide .left or .right via display:none, causing the .main grid
   template to recompute and the layout to snap. Stable approach:
   transition grid-template-columns smoothly between modes; collapsed
   columns retain their grid slot at width 0. Smooth CSS transition
   replaces the snap. Compose-mode column width 0/1fr, Announce mode
   1fr/0, etc. Pre-existing @media (max-width:900px) single-column
   stacking is unchanged — phone/narrow-tablet behaviour preserved.
   ============================================================ */

@media (min-width: 901px) {
  .main {
    transition: grid-template-columns 180ms ease-out;
  }

  /* Override the legacy `.left { display: none }` / `.right { display: none }`
     with column-collapse + content-hide. The grid keeps both slots; the
     hidden column compresses to 0 with overflow clipped. */
  /* [g120] Allow grid tracks to fully collapse: by default grid items have
     min-width:auto which prevents shrinking below content size. Without these
     the `0 1fr` and `1fr 0` templates would refuse to fully collapse the
     hidden column, producing the snap Pete reported. */
  .main > .left, .main > .right {
    min-width: 0;
    min-height: 0;
  }

  body[data-mode="Compose"] .main {
    grid-template-columns: 0 1fr;
  }
  body[data-mode="Compose"] .left {
    display: flex !important;          /* override existing display:none */
    visibility: hidden;
    pointer-events: none;
    overflow: hidden;
    width: 0;
    padding: 0 !important;             /* no residual padding-width during collapse */
    border: 0 !important;
  }
  body[data-mode="Compose"] .right {
    grid-column: auto !important;      /* override grid-column: 1 / -1 */
  }

  body[data-mode="Announce"] .main {
    grid-template-columns: 1fr 0;
  }
  body[data-mode="Announce"] .right {
    display: flex !important;          /* override existing display:none */
    visibility: hidden;
    pointer-events: none;
    overflow: hidden;
    width: 0;
    padding: 0 !important;
    border: 0 !important;
  }
  body[data-mode="Announce"] .left {
    grid-column: auto !important;      /* override grid-column: 1 / -1 */
  }

  /* [g122] g120 .compose pin removed -- the new viewport-based base rule
     (.compose at line ~448) gives consistent width across all modes
     without parent-tracking. Brace below closes the @media (min-width:901px)
     screen-jump-fix block. */
}
