/* Components: the pieces the app draws over and over, named once.

   This is where a helper's look lives once the helper stops writing a style
   string. Room-specific styling does not belong here — that goes to the room's
   own sheet as each room is converted (STYLES-PLAN.md, Steps 3 onward). */

/* ---------- the small label (the house face since Bug 47; it was monospace) ----------
   public/lib/helpers.js mono(). Structure here, values from the call site.

   THE INLINE EXCEPTION, WORKED. Two of these are genuinely per-call data: a
   label's letterspacing and its colour. They ride as scoped custom properties
   on the element rather than as declarations, which is the kind of inline
   CLAUDE.md admits — data-driven, documented at the helper that writes it.
   What is NOT per-call is the treatment itself, and that lives here.

   SIZE STOPPED BEING PER-CALL. It used to read --monotype-size, which is why
   324 call sites each named their own: 6, 6.5, 7, 7.5, 8, 8.5, 9 — and mono()
   clamps at 9, so 306 of them were the same 9px wearing eight different
   spellings. A label's size is a step of the scale, not a per-label decision.
   It reads the token now, and the band a call site asked for arrives through
   the modifier class below. mono() still writes --monotype-size and nothing
   reads it: retiring it would rewrite the markup of every screen in the app,
   which is a separate and much noisier commit than this one. */
.monotype{
  font-family:inherit;
  font-size:var(--t-label);
  letter-spacing:var(--monotype-ls);
  color:var(--monotype-color);
}
/* ---------- the chip ----------
   public/lib/helpers.js chip(). The small pill that is either the chosen one or
   one of the others: same three properties either way, only the values change,
   and every value is already a token on the element. Nothing rides inline.
   .chip-on must stay below .chip — same weight, so order is what decides. */
.chip{
  border:var(--bd) solid var(--edge);
  background:var(--inset);
  color:var(--muted);
}
.chip-on{
  border-color:var(--accent);
  background:var(--accent);
  color:var(--onAccent);
}

/* ---------- the light there ----------
   Four swatches previewing a destination's theme, at the door, on the mission
   board and in the scene. Each swatch carries the destination's theme NAME and
   reads that block's tokens, so the preview is the destination rather than a
   copy of it.

   --swatch-edge is the trick worth reading. The row is in YOUR theme and
   resolves --edge there; the swatches then change theme underneath it. A
   custom property inherits the value it resolved to, not the expression that
   produced it, so the border stays in the room you are standing in while the
   fill comes from the room you are going to. */
.swatches{display:flex;--swatch-edge:var(--edge);}
.swatches-sm{gap:3px;}
.swatch{border:var(--bd) solid var(--swatch-edge);}
.swatches-sm .swatch{width:9px;height:9px;border-radius:2px;}
/* The fills. Settings names them from parts (rooms/settings.js: swatch-${s}), so a scan for whole class names missed
   them and the September 26 cleanup took them out: every look's row showed four empty boxes (live walk, October 9). */
.swatch-setA{background:var(--setA);}
.swatch-accent{background:var(--accent);}
.swatch-panel{background:var(--panel);}
.swatch-bg{background:var(--bg);}

/* ---------- the house prefs ----------
   The gear in the nav opens this sheet. Zoom and the look live here; sound
   does not. The look rows are built from tokens.css (themeRack), so this file
   styles a list whose length it does not know.

   The row swatches use the same standing-in trick as the door above: a row
   offering a theme carries that theme's name, so it previews the real block. */
.prefs{width:100%; max-width:400px;}
.prefs-zoom{display:flex; gap:var(--s2);}
.prefs-zoom-step{flex:1; padding:var(--s4) var(--s3); border-radius:var(--r-sm); text-align:center; font-weight:var(--w-semi);}
.prefs-looks{display:flex; flex-direction:column; gap:2px;}
.prefs-looks .theme-opt{width:100%;}
.theme-opt{display:flex; align-items:center; gap:10px; padding:calc(8px * var(--space-k)) 9px; border-radius:var(--r-sm); color:var(--ink3);}
.theme-opt:hover{background:var(--sel);}
.theme-opt.on{background:var(--sel); color:var(--accent);}

/* ---------- the nav bar and the stale-brief strip ----------
   public/rooms/partials.js. slot()'s font-size stays inline: it is the
   size of a letter in a hole, not a step of the type scale. */
.nav{position:sticky; top:0; z-index:6; display:flex; flex-wrap:wrap; align-items:center;
  gap:10px 18px; padding:14px 18px 12px; background:var(--chrome);
  backdrop-filter:blur(20px); border-bottom:var(--bd) solid var(--edge);}
.stale{display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:10px 13px; border:var(--bd) dashed var(--accent); border-radius:var(--r-md);
  background:var(--sel);}

/* ---------- one button ----------

   Step 4 box 2. Every button in the app was hand-styled where it stood: 257 of
   them across 15 files, declaring border-radius 134 times in 23 flavours,
   border 110 times, padding in 40. Surveyed before this was written, and the
   variants below are the shapes that survey actually found:

     95  no inline style at all      -> .btn on its own
     94  1px border, no fill         -> .btn (that IS the house button)
     29  text only, no border, no bg -> .btn-quiet
     16  accent fill                 -> .btn-primary
     14  tinted fill plus a border   -> .btn-tinted
      8  everything else

   Sizes come from the same survey: square icon buttons clustered hard at 34px
   with 32 and 38 either side, so there is one icon size and two modifiers, not
   nine. Everything reads the kit tokens, so a change to the scale reaches every
   button rather than 257 style attributes.

   A room adopts these as it is converted (Step 5). Adding the classes changes
   nothing on its own.

   THE TYPE STEP WAS ONE LOW, AND THIS IS WHY — worth reading before trusting
   any other number that came out of a survey of written attributes.

   This button was surveyed BEFORE the one type scale landed, so the survey
   counted what the rooms had TYPED. A room that wrote `font-size:14px` did
   not render at 14: a remapper used to send a written 14 to --t-body, which
   is 15. The survey saw the string "14" everywhere and named
   --t-small, the token whose VALUE is 14. It read the attribute instead of the
   bridge, which is the one thing CLAUDE.md says never to do, and the kit ended
   up a step below the app it was measured from.

   Measured in the running app before this was changed: of the 417 sans-labelled
   buttons not yet wearing .btn, 183 render at 15px, 97 at 14, 49 at 18, 29 at
   13 and 17 at 16. Fifteen is the plurality, and inside the Council it is 158
   of 279. The mono-label buttons are not in this at all — mono() owns their
   size, and no mono button wears .btn anywhere in the app.

   So all three steps move up one, together, because all three were read off the
   same attributes. What that moved, named rather than discovered later:

     · the Council's four tabs, its two panel buttons and the dialog's Cancel
       and Yes go 14px to 15px, and a pixel taller. Those tabs are the exact
       labels slice one of the Council shrank from 15 to 13; they came back at
       14 when the standard landed and this is what puts them back.
     · .btn-lg reaches exactly two text buttons — the scene transport's
       Play/Pause and "Choose advisors from the Library" — 15px to 16px.
     · .btn-sm reaches NO text at all: every .btn-sm in the app is a
       .btn-icon.btn-sm square. Its size moves on paper only.

   line-height:1 is deliberately NOT touched. It is right for a button, whose
   box should be padding-driven rather than text-metric-driven. But it is the
   other half of adopting this class and a converting room must know it: 283 of
   those bare buttons sit at line-height 22.5, the page's 1.5, so .btn takes
   about seven pixels of height out of them. A room puts that back as padding in
   its OWN sheet, the way the Council put three declarations back on .field.
   A class must never change a size. */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--s2);
  padding:var(--s4) var(--s5); border:var(--bd) solid var(--edge); border-radius:var(--r-md);
  background:transparent; color:var(--muted); font-size:var(--t-body); line-height:1;
  white-space:nowrap; transition:color var(--mo-fast), background var(--mo-fast), border-color var(--mo-fast);
}
.btn:hover{color:var(--text); border-color:var(--ink4);}
.btn[disabled],.btn[aria-disabled="true"]{opacity:.5; cursor:default;}
.btn[disabled]:hover,.btn[aria-disabled="true"]:hover{color:var(--muted); border-color:var(--edge);}

/* the fills */
.btn-primary{background:var(--accent); border-color:var(--accent); color:var(--onAccent); font-weight:var(--w-semi);}
.btn-primary:hover{color:var(--onAccent); border-color:var(--accent); filter:brightness(1.08);}
.btn-tinted{background:var(--sel);}
/* a text weight, not a fill: the confirm in a dialog is tinted like its
   neighbours and speaks at full strength. */
.btn-strong{color:var(--text); font-weight:var(--w-semi);}
.btn-strong:hover{color:var(--text);}
.btn-quiet{border-color:transparent; background:transparent;}
.btn-quiet:hover{border-color:transparent; background:var(--sel); color:var(--text);}

/* the states a button carries itself, rather than a room deciding in a string.
   btn-on is the app's existing on-state to the letter: accent edge, accent
   label, no fill. A room that wants a fill as well adds btn-tinted. */
.btn-on{border-color:var(--accent); color:var(--accent);}
.btn-on:hover{border-color:var(--accent); color:var(--accent);}
.btn-danger{color:var(--accent);}

/* size first, then shape: an icon button is a fixed square and must be able to
   drop the padding a size modifier gives it, which only works if it is
   declared after. */
.btn-sm{padding:var(--s2) var(--s4); font-size:var(--t-small);}
.btn-lg{padding:var(--s5) var(--s6); font-size:var(--t-lead);}
.btn-icon{width:34px; height:34px; padding:0; flex:none;}
.btn-icon.btn-sm{width:32px; height:32px;}
.btn-icon.btn-lg{width:38px; height:38px;}
.btn-wide{width:100%;}

/* ---------- one panel ----------

   Step 4 box 3. Surveyed like the buttons: 144 surfaces across the rooms,
   declaring border 17 ways, radius 17 ways, padding 36 ways. The shapes the
   survey found are the variants; .panel is the one still in use:

     39  a --panel fill with a 1px edge   -> .panel

   Radius follows the same clustering: 13, 14 and 15 are one thing (--r-lg) and
   17 and 20 are the bigger thing a modal wants (--r-xl, on .panel-lg). */
.panel{padding:var(--s7); border:var(--bd) solid var(--edge); border-radius:var(--r-lg); background:var(--panel);}
.panel-lg{padding:var(--s8); border-radius:var(--r-xl);}
.panel-float{box-shadow:var(--sh-modal);}
.panel-col{display:flex; flex-direction:column; gap:var(--s5);}

/* ---------- one input ----------

   96 of them: 45 input, 34 textarea, 17 select, and 87 carried an inline style.
   They agreed on more than the buttons did — 50 of 64 borders were already
   1px solid var(--edge), 40 of 62 fills were --inset — so this is mostly
   writing down what they already were. Radius 10, 11 and 12 become --r-md.

   The reading sizes are the one real split: a one-line field sits at body size
   and a textarea people write paragraphs into sat at 15, so that is .field-lg
   rather than a second class. */
.field{width:100%; padding:var(--s4) var(--s5); border:var(--bd) solid var(--edge); border-radius:var(--r-md);
  background:var(--inset); color:var(--ink2); font-size:var(--t-body); line-height:var(--lh-body);
  transition:border-color var(--mo-fast);}
.field:focus{border-color:var(--accent); color:var(--text);}
.field::placeholder{color:var(--muted); opacity:.6; font-style:italic;}
.field-lg{font-size:var(--t-lead);}
.field-sm{padding:var(--s2) var(--s4); font-size:var(--t-small);}
.field-tall{min-height:96px; resize:vertical;}

/* The one display voice for a house room's primary title and its authored
   section heads. Both are opt-in: card names, projects, tools and dialogs keep
   the working face. The house-stage scope makes these rules stronger than a
   room's legacy title weight without !important or another font declaration. */
.house-stage .house-room-title,.house-stage .council-title{font-family:var(--font-trajan);font-weight:var(--w-med);letter-spacing:.015em;}

/* ---------- the modal scrim ----------
   .modal-scrim holds a window drawn as markup (the credit, bug report and Titan windows). The shell's questions are
   the window standard's own (lib/dialog.js, packages/platform-ui/window-standard.mjs). */
/* A modal is a floating window, not a veil. The scrim paints nothing and passes pointers through, so the page stays
   live behind it, while its child, the window itself, catches its own. Every window wears data-drag, which Escape reads
   to find the topmost one (lib/dispatch.js), and closes on its X or on Escape, which presses it. Every window follows
   the one window standard (packages/platform-ui/window-standard.mjs): no blackout, moved by its title bar
   (data-window, data-window-bar), one X top right, unsaved work asks first. */
.modal-scrim{position:fixed; inset:0; z-index:95; display:flex; align-items:center; justify-content:center;
  padding:var(--s7); pointer-events:none; animation:fadeUp .25s ease both;}
.modal-scrim>*{pointer-events:auto;}
/* Over the Appearance window the scrim is lifted to the top layer as a popover (lib/top-layer.js); this undoes the
   browser's own popover box so it stays the same clear, full-screen scrim. */
.modal-scrim:popover-open{width:auto; height:auto; margin:0; border:0; background:none; color:inherit; overflow:visible;}
.voice-gem{display:inline-flex; align-items:center; color:var(--accent);}
/* The solid red a removal's confirming button is filled with, white words on it, the same in every theme (--danger
   turns pink at night, too pale under white). White on it is 5.6 to 1; house-style-check holds it at 4.5 or better.
   It sits here, not in tokens.css, until that sheet's planned cut (docs/SEAMS.md) makes room. */
:root{--danger-fill:#c42b2b;}

/* ---------- the listening window ----------
   rooms/modals/listen.js draws it; actions/listen.js is its behaviour. A
   floating panel holding one <audio> (carried across
   repaints by data-keep) and the recording's chapters as a scrollable rail. */
.listen{width:100%; max-width:520px; position:relative; overflow:hidden;}
/* the card's own painting behind the window, under a veil of the panel's own
   colour — a layer over the picture, never a filter on it. Everything else in
   the window rides above the pair. */
.listen>*{position:relative; z-index:2;}

/* ---------- the side nav ----------
   Sections down the left, the open one filling the rest. rooms/partials.js
   sideNav() builds the rail; a caller wraps the pair in .sidenav-page.

   It carried the Council's name until 2026-08-20 (`[data-council-settings]`,
   `.assistant-settings-nav`, `.settings-nav-item`) because that is the room it
   was born in. The Time Machine wanted the same shape, and the choice was a
   second spelling of one pattern or a rename. This is the rename.

   An item's second line is what it is currently set to, which is the whole
   argument for a rail over a row of tabs: a long form reads at a glance
   without opening any of it. */
.sidenav-page{display:grid; grid-template-columns:172px minmax(0,1fr);
  gap:var(--s7); align-items:start;}
.sidenav{display:flex; flex-direction:column; gap:var(--s1);}
.sidenav-item{display:flex; flex-direction:column; gap:1px; padding:var(--s4) var(--s5);
  text-align:left; border-radius:var(--r-md); color:var(--muted);
  transition:background var(--mo-fast), color var(--mo-fast);}
.sidenav-item:hover{background:var(--sel);}
.sidenav-item-on{background:var(--sel); color:var(--accent);}
.sidenav-item-name{font-size:var(--t-body); font-weight:var(--w-semi);}

@media (max-width:1100px){
  .sidenav-page{grid-template-columns:1fr;}
  .sidenav{flex-direction:row; overflow-x:auto; gap:var(--s2); padding-bottom:2px;}
  .sidenav-item{flex:none;}
}

/* ---------- THE ASSISTANT'S CONTROL BAR ----------
   Under the box, because the box is at the top: talk to her, choose whether
   she answers aloud, and clear the conversation. Clear empties the TRANSCRIPT
   and never her memory — memory is wiped on purpose, with warnings, from her
   own card (Story System/THE-ASSISTANT.md §5). */
.house-ann-bar{display:flex;align-items:center;gap:var(--s2);padding:0 var(--ann-pad) var(--ann-gap);}
.house-ann-btn{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;
  padding:0;border:var(--bd) solid var(--edge);border-radius:var(--r-round);background:var(--inset);
  color:var(--muted);cursor:pointer;}
.house-ann-btn:hover{color:var(--ink);border-color:var(--accent-line);}
.house-ann-btn.on{color:var(--accent);border-color:var(--accent);}
.house-ann-clear{padding:3px 9px;border:var(--bd) solid var(--edge);border-radius:var(--r-pill);
  background:none;color:var(--muted);font:inherit;font-size:var(--t-tiny);cursor:pointer;}
.house-ann-clear:hover{color:var(--ink);border-color:var(--accent-line);}
/* THE DIG CHIP (plans/ANN-MEMORY.md; the lane brief, 2026-08-23): one quiet
   press on her latest answer when deeper memory is on offer. .house-ann-clear's
   own dress — same pill, same rest state — but on its OWN line under the
   words it follows rather than crowding them, and in the accent because it
   is an offer rather than a housekeeping verb. No price named on the chip
   itself: nothing in this build can honestly name what a dig costs yet. */
.house-ann-dig{display:block;margin-top:6px;padding:3px 9px;border:var(--bd) solid var(--edge);
  border-radius:var(--r-pill);background:none;color:var(--accent);font:inherit;font-size:var(--t-tiny);cursor:pointer;}
.house-ann-dig:hover{color:var(--ink);border-color:var(--accent-line);background:var(--sel);}
/* THE MESSAGES NEED AIR (Mark, 2026-08-21). The gap between messages does it
   without moving the column off the edge every other row in the panel sits on.
   Her answers run on the panel as plain text with no box (Mark, October 30,
   2026; chat-plain-answers-check); only the person's own words keep a bubble, solid --raised in every theme. */
.house-ann-top .house-ann-log{gap:calc(var(--s4) * var(--space-k));padding-bottom:var(--s6);}
.house-ann-top .house-ann-you{padding:var(--s3) var(--s4);}

.pic{max-width:min(92vw,940px); max-height:94vh; overflow-y:auto; gap:13px;}

/* Ann reads the same report while her conversation stays beside it. */
.ann-report-view{height:100%;min-height:300px;display:flex;flex-direction:column}
.ann-report-view>.titan-pane{flex:1;min-height:0;width:100%}
.md-table-scroll{max-width:100%;overflow-x:auto;margin:1em 0}
.md-table{width:100%;border-collapse:collapse;font-size:inherit}
.md-table th,.md-table td{padding:calc(8px * var(--space-k)) 12px;border:1px solid var(--edge);vertical-align:top;min-width:8em}
.md-table th{background:var(--sel);font-weight:600}
.md-table .md-align-left{text-align:left}.md-table .md-align-center{text-align:center}.md-table .md-align-right{text-align:right}
.md-task-item{list-style:none}
input.md-task-box{display:inline-block;width:14px;min-width:14px;max-width:14px;height:14px;margin:0 .4em 0 0;padding:0;vertical-align:middle}
