/* Writing Assistant · app shell: grid, top bar, doc rail, main column, assistant panel, sheets, focus mode.
   docs/09-VISUAL-SPEC.md §5 (layout) and §9 (responsive). Theme/state hooks live on .wa-app data-attributes:
     data-rail="open|collapsed"   data-panel="open|closed"   data-focus="on|off"   data-viewer="member|guest"
   Theme / font / size hooks live on <html>: data-theme, data-page-font, data-page-size. */

@layer components {

  /* ───────────────────────── Grid ───────────────────────── */
  .wa-app {
    --_rail: var(--rail-w);
    --_panel: 0px;
    position: relative;
    display: grid;
    grid-template-columns: var(--_rail) minmax(0, 1fr) var(--_panel);
    grid-template-rows: var(--topbar-h) minmax(0, 1fr);
    grid-template-areas:
      "rail top  panel"
      "rail main panel";
    height: calc(100dvh - var(--nav-h));
    min-height: 480px;
    background: var(--canvas);
    transition: grid-template-columns var(--t-slow) var(--ease-out);
    isolation: isolate;
  }
  .wa-app:is([data-panel="open"], [data-panel="peek"]) { --_panel: var(--panel-w); }
  .wa-app[data-rail="collapsed"] { --_rail: 0px; }

  /* ───────────────────────── Top bar ───────────────────────── */
  .wa-topbar {
    grid-area: top;
    z-index: var(--z-sticky);
    display: flex; align-items: center; gap: var(--sp-2);
    min-width: 0;
    padding: 0 var(--sp-3) 0 var(--sp-3);
    background: var(--canvas);
    border-bottom: var(--sp-px) solid transparent;
    transition: border-color var(--t-med) var(--ease-out), opacity var(--t-med) var(--ease-out);
  }
  .wa-topbar[data-scrolled="true"] { border-bottom-color: var(--border); }
  .wa-topbar__start { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; flex: 1 1 auto; }
  .wa-topbar__end { display: flex; align-items: center; gap: var(--sp-2); flex: none; }
  .wa-topbar__sep { width: var(--sp-px); height: var(--sp-5); background: var(--border); flex: none; }

  .wa-crumbs {
    display: flex; align-items: center; gap: var(--sp-1); min-width: 0;
    font-size: var(--fs-label); line-height: var(--lh-label); color: var(--text-3);
  }
  .wa-crumbs__root { flex: none; padding: var(--sp-half) var(--sp-1); border-radius: var(--r-sm); min-height: var(--sp-6); display: inline-flex; align-items: center; }
  .wa-crumbs__root:hover { color: var(--text); background: var(--surface-3); }
  .wa-crumbs__slash { flex: none; color: var(--text-3); }
  .wa-crumbs__doc {
    min-width: 0; color: var(--text); font-weight: var(--fw-medium);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }

  /* Save state: text + icon, never colour alone. role="status" so each change is announced. */
  .wa-save {
    display: inline-flex; align-items: center; gap: var(--sp-1);
    flex: none; min-height: var(--sp-6); padding: 0 var(--sp-2);
    border-radius: var(--r-pill);
    font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--text-3);
    white-space: nowrap;
  }
  .wa-save .wa-i { width: var(--sp-3); height: var(--sp-3); }
  .wa-save[data-state="saving"] .wa-save__dot {
    width: 6px; height: 6px; border-radius: 50%; background: var(--text-3);
    animation: wa-pulse 1.2s var(--ease-in-out) infinite;
  }
  .wa-save[data-state="offline"],
  .wa-save[data-state="error"] { color: var(--warning); background: var(--warning-tint); }
  .wa-save[data-state="conflict"] { color: var(--warning); background: var(--warning-tint); }

  .wa-trial {
    display: inline-flex; align-items: center; gap: var(--sp-2);
    min-height: var(--ctl-md); padding: 0 var(--sp-3);
    border-radius: var(--r-pill); background: var(--accent-tint);
    color: var(--text); font-size: var(--fs-label); line-height: var(--lh-label); white-space: nowrap;
  }
  .wa-trial__pips { display: inline-flex; gap: var(--sp-1); }
  .wa-trial__pip { width: 8px; height: 8px; border-radius: 50%; border: 1.5px solid var(--accent); }
  .wa-trial__pip[data-used="true"] { background: transparent; border-color: var(--border-control); }
  .wa-trial__pip[data-used="false"] { background: var(--accent); }

  /* ───────────────────────── Doc rail ───────────────────────── */
  .wa-rail {
    grid-area: rail;
    position: relative;   /* containing block: its overflow:hidden must clip absolutely-positioned children too */
    display: flex; flex-direction: column;
    min-width: 0; overflow: hidden;
    background: var(--surface-1);
    border-right: var(--sp-px) solid var(--border);
  }
  .wa-app[data-rail="collapsed"] .wa-rail { visibility: hidden; border-right-width: 0; }
  .wa-rail__inner { width: calc(var(--rail-w) - var(--sp-px)); display: flex; flex-direction: column; height: 100%; min-height: 0; }
  .wa-rail__head {
    display: flex; align-items: center; gap: var(--sp-2);
    height: var(--topbar-h); padding: 0 var(--sp-2) 0 var(--sp-4); flex: none;
  }
  .wa-brand { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; flex: 1; font-weight: var(--fw-bold); font-size: var(--fs-body); }
  .wa-rail__search { padding: 0 var(--sp-3) var(--sp-2); flex: none; }
  .wa-rail__list { flex: 1 1 auto; min-height: 0; padding: var(--sp-1) var(--sp-2) var(--sp-3); }
  .wa-rail__group {
    display: flex; align-items: center; justify-content: space-between;
    padding: var(--sp-3) var(--sp-2) var(--sp-1);
    font-size: var(--fs-meta); line-height: var(--lh-meta); font-weight: var(--fw-bold);
    letter-spacing: var(--ls-caps); text-transform: uppercase; color: var(--text-3);
  }
  .wa-rail__empty { padding: var(--sp-6) var(--sp-3); color: var(--text-3); font-size: var(--fs-label); line-height: var(--lh-label); text-align: center; }

  .wa-docrow {
    position: relative;
    display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: var(--sp-1);
    width: 100%; min-height: var(--sp-12);
    padding: var(--sp-2) var(--sp-1) var(--sp-2) var(--sp-3);
    border-radius: var(--r-md);
    color: var(--text-2);
    transition: background-color var(--t-fast) var(--ease-out);
  }
  .wa-docrow:hover { background: var(--surface-3); color: var(--text); }
  .wa-docrow[aria-current="page"] { background: var(--surface-3); color: var(--text); }
  .wa-docrow[aria-current="page"]::before {
    content: ""; position: absolute; left: 0; top: var(--sp-3); bottom: var(--sp-3);
    width: var(--sp-half); border-radius: var(--r-pill); background: var(--accent);
  }
  .wa-docrow__open { display: flex; flex-direction: column; gap: var(--sp-half); min-width: 0; text-align: left; border-radius: var(--r-sm); }
  .wa-docrow__open::after { content: ""; position: absolute; inset: 0; border-radius: var(--r-md); }   /* whole row is the target */
  .wa-docrow__title {
    font-size: var(--fs-label); line-height: var(--lh-label); font-weight: var(--fw-medium);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .wa-docrow__meta { font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--text-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .wa-docrow__more { position: relative; z-index: 1; opacity: 0; transition: opacity var(--t-fast); }
  .wa-docrow:hover .wa-docrow__more, .wa-docrow:focus-within .wa-docrow__more, .wa-docrow[aria-current="page"] .wa-docrow__more { opacity: 1; }
  .wa-docrow mark { background: var(--mark); color: var(--text); border-radius: 2px; }

  .wa-rail__foot {
    flex: none; display: flex; flex-direction: column; gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4) var(--sp-3);
    border-top: var(--sp-px) solid var(--border);
  }
  .wa-rail__tools { display: flex; align-items: center; gap: var(--sp-1); margin: 0 calc(var(--sp-2) * -1); }

  /* Usage meter (rail foot + panel). Real numbers are server-rendered on first paint (05 §1.5 "0/10" bug). */
  .wa-meter { display: flex; flex-direction: column; gap: var(--sp-2); }
  .wa-meter__row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-2); font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--text-3); }
  .wa-meter__row strong { color: var(--text); font-weight: var(--fw-bold); }
  .wa-meter__track { height: 4px; border-radius: var(--r-pill); background: var(--surface-3); overflow: hidden; }
  .wa-meter__fill { height: 100%; width: var(--_pct, 0%); border-radius: inherit; background: var(--accent); transition: width var(--t-slow) var(--ease-out); }
  .wa-meter[data-level="low"] .wa-meter__fill { background: var(--warning); }
  .wa-meter[data-level="out"] .wa-meter__fill { background: var(--warning); }
  .wa-meter__link { color: var(--accent); font-weight: var(--fw-medium); display: inline-flex; align-items: center; min-height: var(--sp-6); }
  .wa-meter__link:hover { text-decoration: underline; text-underline-offset: 3px; }

  /* ───────────────────────── Main column ───────────────────────── */
  .wa-main {
    grid-area: main;
    position: relative;
    display: grid;
    grid-template-rows: auto auto minmax(0, 1fr) var(--status-h);
    min-width: 0; min-height: 0;
    background: var(--canvas);
  }
  .wa-scroller {
    position: relative;
    min-height: 0;
    overflow-y: auto; overflow-x: hidden;
    scrollbar-gutter: stable both-edges;   /* keeps the page centred on the same axis as the status line (critic r1 m1) */
    overscroll-behavior: contain;
    scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent;
    scroll-padding-block: var(--sp-16) calc(var(--fade-h) + var(--sp-8));   /* caret / find jumps never land under the fade */
  }
  /* The status line is a SOLID canvas band (--status-h) and the text dissolves into it through a --fade-h overlay that
     reaches full canvas exactly at the band's top edge, so the line the scroller cuts is invisible (0% ink), never
     half-inked next to UI text (critic r1 M1). A real element, not a mask: a mask would trap the fixed AI bars. */
  .wa-fade {
    position: absolute; left: 0; right: 0; bottom: var(--status-h); height: var(--fade-h);
    background: linear-gradient(to bottom, transparent, var(--canvas));
    pointer-events: none; z-index: var(--z-page-float);
  }
  /* Floating layer for the selection bar, slash menu, per-change popover: outside the scroller so a phone can
     dock them with position:fixed; positioned by JS from the anchor's rect. */
  .wa-floatlayer { position: absolute; inset: 0; z-index: var(--z-bar); pointer-events: none; }
  .wa-floatlayer > * { pointer-events: auto; }

  /* Aligned to the page column: its width is computed in the PAGE font (ch), then its text is set in the UI font. */
  .wa-statusline {
    display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
    width: 100%; max-width: calc(var(--measure) + 2 * var(--page-pad-x)); height: var(--status-h);
    margin: 0 auto; padding: 0 var(--page-pad-x);          /* the SAME content box as .wa-page (critic r1 m1) */
    background: var(--canvas);
    font-family: var(--font-page); font-size: calc(var(--page-fs) * var(--page-scale, 1)); font-weight: var(--fw-page);   /* ch depends on weight: match the page exactly */
    line-height: var(--lh-meta); color: var(--text-3);
  }
  .wa-statusline > * { font-family: var(--font-ui); font-size: var(--fs-meta); line-height: var(--lh-meta); font-weight: var(--fw-regular); }
  .wa-statusline__stats { display: flex; align-items: center; gap: var(--sp-1); min-width: 0; white-space: nowrap; }
  .wa-statusline__hint { display: inline-flex; align-items: center; gap: var(--sp-2); color: var(--text-2); }
  .wa-statusline > .wa-statusline__btn { margin-right: calc(var(--sp-2) * -1); }
  .wa-statusline__btn {
    display: inline-flex; align-items: center; gap: var(--sp-2);
    min-height: var(--ctl-sm); padding: 0 var(--sp-2); border-radius: var(--r-sm);
    color: var(--text-3); white-space: nowrap;
  }
  .wa-statusline__btn:hover { background: var(--surface-3); color: var(--text); }
  .wa-dot-sep { color: var(--text-3); }

  .wa-goalring { width: 16px; height: 16px; flex: none; transform: rotate(-90deg); }
  .wa-goalring__track { stroke: var(--border-control); }
  .wa-goalring__fill { stroke: var(--accent); stroke-dasharray: 100; stroke-dashoffset: calc(100 - var(--_goal, 0)); transition: stroke-dashoffset var(--t-slow) var(--ease-out); }

  /* ───────────────────────── Assistant panel ───────────────────────── */
  .wa-panel {
    grid-area: panel;
    position: relative;
    display: flex; flex-direction: column;
    min-width: 0; min-height: 0; overflow: hidden;
    background: var(--surface-1);
    border-left: var(--sp-px) solid var(--border);
  }
  .wa-app[data-panel="closed"] .wa-panel { visibility: hidden; border-left-width: 0; }
  .wa-panel__inner { width: calc(var(--panel-w) - var(--sp-px)); display: flex; flex-direction: column; height: 100%; min-height: 0; }
  .wa-panel__head {
    display: flex; align-items: center; gap: var(--sp-2);
    height: var(--topbar-h); padding: 0 var(--sp-2) 0 var(--sp-4); flex: none;
  }
  .wa-panel__title { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--sp-2); font-weight: var(--fw-bold); font-size: var(--fs-body); }
  .wa-panel__title .wa-i { color: var(--accent); }
  .wa-panel__body { flex: 1 1 auto; min-height: 0; padding: var(--sp-2) var(--sp-4) var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-4); }
  .wa-panel__foot { flex: none; padding: var(--sp-3) var(--sp-4) var(--sp-4); border-top: var(--sp-px) solid var(--border); background: var(--surface-1); }
  .wa-grabber { display: none; }

  /* ───────────────────────── Focus mode ───────────────────────── */
  .wa-app[data-focus="on"] { --_rail: 0px; --_panel: 0px; }
  .wa-app[data-focus="on"] .wa-rail,
  .wa-app[data-focus="on"] .wa-panel { visibility: hidden; }
  /* Focus mode: the top bar row stays reserved (nothing reflows) but is empty except "Exit focus", which sits in that
     row, so it can never touch the title (critic r1 m8). */
  .wa-app[data-focus="on"] .wa-topbar { visibility: hidden; }
  .wa-focus-exit {
    position: absolute; top: calc((var(--topbar-h) - var(--ctl-md)) / 2); right: var(--gutter); z-index: var(--z-sticky);
  }
  .wa-app:not([data-focus="on"]) .wa-focus-exit { display: none; }
  /* While a result is under review the review bar carries the save moment: the top-bar Save steps aside, so there is
     ONE filled button on screen (critic r2 M-5). */
  .wa-app[data-reviewing="true"] .wa-guestsave { display: none; }

  /* ───────────────────────── Scrim (drawer / sheet < 1024) ───────────────────────── */
  .wa-scrim {
    position: fixed; inset: var(--nav-h) 0 0 0; z-index: var(--z-scrim);
    background: var(--scrim);
    opacity: 0; visibility: hidden;
    transition: opacity var(--t-slow) var(--ease-out), visibility var(--t-slow);
  }

  /* The top-bar documents button is only needed when the rail is not showing */
  @media (min-width: 1280px) { .wa-app[data-rail="open"] .wa-railbtn { display: none; } }
  @media (min-width: 1024px) and (max-width: 1279.98px) { .wa-app[data-rail="open"][data-panel="closed"] .wa-railbtn { display: none; } }
  /* usage is shown once: while the panel (with its pill) is open, the rail meter steps aside (critic r1 m14) */
  .wa-app:is([data-panel="open"], [data-panel="peek"]) .wa-rail .wa-meter { display: none; }

  /* ═════════════════════════ Responsive ═════════════════════════ */

  /* 1280: rail + page + panel all fit. Below it the panel wins: opening the assistant collapses the rail. */
  @media (max-width: 1279.98px) {
    .wa-app:is([data-panel="open"], [data-panel="peek"]) { --_rail: 0px; }
    .wa-app:is([data-panel="open"], [data-panel="peek"]) .wa-rail { visibility: hidden; border-right-width: 0; }
  }

  /* < 1024: the rail becomes a left drawer; the assistant becomes a bottom sheet that leaves the text visible. */
  @media (max-width: 1023.98px) {
    .wa-app, .wa-app[data-panel], .wa-app[data-rail="open"] { --_rail: 0px; --_panel: 0px; }

    .wa-rail {
      position: fixed; z-index: var(--z-sheet);
      top: var(--nav-h); bottom: 0; left: 0;
      width: min(320px, 86vw);
      box-shadow: var(--e-3);
      transform: translateX(-100%);
      transition: transform var(--t-slow) var(--ease-out), visibility var(--t-slow);
    }
    .wa-rail__inner { width: 100%; }
    .wa-app[data-rail="open"] .wa-rail { transform: none; visibility: visible; }
    .wa-app[data-rail="collapsed"] .wa-rail { visibility: hidden; }

    .wa-panel {
      position: fixed; z-index: var(--z-sheet);
      left: 0; right: 0; bottom: 0;
      height: min(62dvh, 640px);
      border-left: 0; border-top: var(--sp-px) solid var(--border-strong);
      border-radius: var(--r-xl) var(--r-xl) 0 0;
      box-shadow: var(--e-3);
      transform: translateY(100%);
      transition: transform var(--t-slow) var(--ease-out), visibility var(--t-slow);
    }
    .wa-panel__inner { width: 100%; }
    .wa-app:is([data-panel="open"], [data-panel="peek"]) .wa-panel { transform: none; visibility: visible; }
    /* PEEK: when an EDIT result lands, the sheet drops to a peek so the change and its review bar stay reachable
       (critic r1 M7). The docked review bar sits on top of it via --dock-bottom. */
    .wa-app[data-panel="peek"] { --dock-bottom: var(--peek-h); }
    .wa-app[data-panel="peek"] .wa-panel { height: var(--peek-h); }
    .wa-app[data-panel="peek"] .wa-panel__foot { display: none; }
    /* the docked review bar sits FLUSH on the peek sheet: one stack, no sliver of sliced text between (critic r2 m-7) */
    .wa-app[data-panel="peek"][data-reviewing="true"] .wa-panel { border-radius: 0; border-top-color: var(--border); }
    .wa-grabber {
      display: block; width: var(--sp-10); height: 4px; margin: var(--sp-2) auto 0;
      border-radius: var(--r-pill); background: var(--border-control); flex: none;
    }
    .wa-panel__head { height: var(--sp-12); }

    .wa-app[data-rail="open"] .wa-scrim { opacity: 1; visibility: visible; }
    /* the assistant sheet does NOT dim the page: the writer must still read the text they are asking about */

  }

  @media (max-width: 767.98px) {
    /* phone top bar: the page gutter on both sides, 8px between 44px targets (critic r1 M2) */
    .wa-topbar { padding: 0 var(--gutter); gap: var(--sp-2); }
    .wa-topbar__start, .wa-topbar__end { gap: var(--sp-2); }
    /* (0,2,0) so it beats .wa-btn--ghost (0,1,0), which loads later in the same layer (critic r2 M-2, a real cascade bug) */
    .wa-topbar .wa-assist-toggle { border-color: transparent; border-width: 0; background: var(--accent-tint); min-width: var(--target); min-height: var(--target); padding: 0; }
    .wa-app[data-viewer="guest"] .wa-save { display: none; }
    /* phone + a docked review bar: the status band steps aside, so the text keeps ≥ 55% of the viewport (ruling 5) */
    .wa-app[data-reviewing="true"] .wa-main { grid-template-rows: auto auto minmax(0, 1fr) 0; }
    .wa-app[data-reviewing="true"] .wa-statusline, .wa-app[data-reviewing="true"] .wa-fade { visibility: hidden; }
    .wa-crumbs__root, .wa-crumbs__slash { display: none; }
    .wa-crumbs__doc { font-size: var(--fs-body); }
    .wa-save__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
    .wa-save { padding: 0; min-width: var(--target); justify-content: center; }
    .wa-panel { height: min(58dvh, 560px); }
    .wa-statusline { padding: 0 var(--page-pad-x); }
  }

  @keyframes wa-pulse { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
}
