:root { --rail-w: 240px; }

#appRail {
  position: fixed; top: 0; left: 0; bottom: 0; width: var(--rail-w);
  background: #14130F; border-right: 1px solid rgba(240,232,216,0.08);
  display: flex; flex-direction: column; z-index: 500;
  overflow-y: auto; padding: 1.2rem 0;
}
body.light-theme #appRail { background: #FBF7F0; border-right-color: rgba(26,20,16,0.10); }

/* font-size is 1.05rem, not the Fraunces default 1.15rem: the wordmark should
   not out-shout the thing you actually click. */
.rail-brand {
  font-family: 'Fraunces', serif; font-weight: 900; font-size: 1.05rem;
  letter-spacing: -0.02em; color: var(--amber); padding: 0 1.3rem 1.4rem;
}
.rail-brand span { color: #F0E8D8; }
body.light-theme .rail-brand span { color: #1A1410; }

.rail-group { margin-bottom: 1.6rem; }
.rail-group-label {
  font-family: 'Archivo', sans-serif; font-size: 0.68rem; letter-spacing: 2.4px;
  font-weight: 600; text-transform: uppercase; color: #8A7B67;
  padding: 0 1.3rem 0.6rem;
}
body.light-theme .rail-group-label { color: #6B5B47; }

/* Sized for a mouse, not a spec sheet: 46px of height clears the 44px target
   most pointer-accuracy guidance settles on, and the label carries the row
   rather than the 2px active border doing all the work. */
.rail-item {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  width: 100%; min-height: 46px; background: transparent; border: 0; cursor: pointer;
  font-family: 'Archivo', sans-serif; font-size: 1.02rem; font-weight: 500;
  letter-spacing: -0.01em; color: #C4A882;
  padding: 0.6rem 1.3rem; text-align: left; border-left: 3px solid transparent;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.rail-item:hover { background: rgba(232,162,61,0.10); color: #F0E8D8; }
.rail-item.active {
  color: var(--amber); border-left-color: var(--amber);
  background: rgba(232,162,61,0.13); font-weight: 700;
}
body.light-theme .rail-item { color: #6B5B47; }
body.light-theme .rail-item:hover { color: #1A1410; background: rgba(232,162,61,0.14); }
body.light-theme .rail-item.active { color: #A66A14; background: rgba(232,162,61,0.18); }

.rail-badge:empty { display: none; }
.rail-badge {
  background: var(--amber); color: #1A1410; font-size: 0.65rem; font-weight: 700;
  border-radius: 999px; padding: 0.05rem 0.42rem; min-width: 1.1rem; text-align: center;
}

@media (min-width: 1024px) {
  body { padding-left: var(--rail-w); }
}

#appTopBar {
  position: fixed; top: 0; left: 0; right: 0; height: 52px;
  display: none; align-items: center; gap: .8rem; padding: 0 1rem;
  background: rgba(20,19,15,0.92); backdrop-filter: blur(12px);
  border-bottom: 1px solid rgba(240,232,216,0.08); z-index: 550;
}
body.light-theme #appTopBar { background: rgba(251,247,240,0.92); border-bottom-color: rgba(26,20,16,0.10); }
.topbar-btn { background: transparent; border: 0; color: var(--amber); font-size: 1.3rem; cursor: pointer; padding: 0 .2rem; }
.topbar-title { font-family: 'Fraunces', serif; font-weight: 700; font-size: 1rem; color: #F0E8D8; }
body.light-theme .topbar-title { color: #1A1410; }

#railScrim {
  position: fixed; inset: 0; background: rgba(0,0,0,0.55);
  z-index: 490; display: none;
}

@media (max-width: 1023px) {
  #appTopBar { display: flex; }
  body { padding-left: 0; padding-top: 52px; }
  #appRail { transform: translateX(-100%); transition: transform .22s ease; }
  body.rail-open #appRail { transform: translateX(0); }
  body.rail-open #railScrim { display: block; }
}

.topbar-add { margin-left: auto; font-size: 1.4rem; }
@media (min-width: 1024px) {
  #appTopBar { display: flex; left: var(--rail-w); }
  #appTopBar .topbar-btn:first-child { display: none; }
  body { padding-top: 52px; }
}

/* ===== Agent panel (Task 10) — appended last on purpose: the #appTopBar and
   #agentPanel rules here are equal-specificity with earlier blocks and are
   resolved by source order. ===== */

#agentPanel {
  position: fixed; top: 52px; right: 0; bottom: 0; width: 340px;
  background: #14130F; border-left: 1px solid rgba(240,232,216,0.08);
  z-index: 520; display: flex; flex-direction: column;
  transform: translateX(100%); visibility: hidden;
  transition: transform .22s ease, visibility .22s ease;
}
body.light-theme #agentPanel { background: #FBF7F0; border-left-color: rgba(26,20,16,0.10); }
body.agent-open #agentPanel { transform: translateX(0); visibility: visible; }

.agent-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: .9rem 1rem; border-bottom: 1px solid var(--glass-border);
  font-family: 'Archivo', sans-serif; font-size: .7rem;
  letter-spacing: 2px; text-transform: uppercase; color: #8A7B67;
}
body.light-theme .agent-head { color: #6B5B47; }

.agent-body {
  flex: 1; min-height: 0; overflow-y: auto; padding: 1rem;
  display: flex; flex-direction: column;
}

/* The chat markup moved here verbatim, ids and classes intact, so
   setEventsView() still strips .active off it as one of the .ev-panel set —
   which under .ev-panel{display:none} would hide the chat. Drive its layout
   from #agentPanel instead. The !important overrides beat the element's own
   inline height clamp, which was sized for a full-width module tab. */
.agent-body #evDiscoverPanel {
  display: flex; flex-direction: column; flex: 1; min-height: 0;
}
.agent-body .discover-wrap {
  padding: 0; margin: 0; flex: 1;
  height: auto !important; min-height: 0 !important; max-height: none !important;
}

/* Group the agent toggle with the + button at the right end of the bar.
   .topbar-add already claims margin-left:auto; two autos would split the gap. */
.topbar-agent { margin-left: auto; font-size: 1.1rem; }
.topbar-agent + .topbar-add { margin-left: 0; }

@media (min-width: 1024px) {
  body.agent-open { padding-right: 340px; }
  /* The top bar is position:fixed, so body padding does not reflow it. Without
     this its buttons stay pinned to the viewport edge, floating over the panel
     column instead of lining up with the content that just shrank. */
  body.agent-open #appTopBar { right: 340px; }
}
@media (max-width: 1023px) {
  #agentPanel { width: 100%; }
}

/* The pill predates the top bar and sits at z-index 50 under it, which hides the
   only Sign out control in the app. Drop it below the bar and above the content. */
.user-pill { z-index: 560; top: calc(52px + 0.6rem); }
@media (max-width: 600px) {
  .user-pill { top: calc(52px + 0.4rem); }
}

/* Moved out of the retired landing view into the top bar. */
#appTopBar .theme-toggle { position: static; margin: 0; }

/* viewport-fit=cover lets the app draw under the notch and home indicator, so
   the fixed chrome has to inset itself or it renders underneath them. */
#appTopBar {
  padding-top: env(safe-area-inset-top, 0px);
  height: calc(52px + env(safe-area-inset-top, 0px));
}
#appRail { padding-top: calc(1.2rem + env(safe-area-inset-top, 0px)); }
@media (max-width: 1023px) {
  body { padding-top: calc(52px + env(safe-area-inset-top, 0px)); }
}
@media (min-width: 1024px) {
  body { padding-top: calc(52px + env(safe-area-inset-top, 0px)); }
}
.user-pill { top: calc(52px + 0.6rem + env(safe-area-inset-top, 0px)); }
#agentPanel { top: calc(52px + env(safe-area-inset-top, 0px)); padding-bottom: env(safe-area-inset-bottom, 0px); }

/* ---------------------------------------------------------------------------
   Compact module headers.

   The original hero was designed for a landing page you arrived at from a tile
   grid: 3rem of padding above a title scaling to 3.8rem. With a rail on the left
   and a top bar that already names the current module, that is roughly 230px of
   screen spent restating something you just clicked — before any content shows.
   On a phone it was most of the first screen.

   Appended after the inline <style> block (index.html:16-856), which css/shell.css
   follows at line 857, so these equal-specificity rules win on source order.
   Sizes and layout only — no colours are changed, so no light-theme counterparts
   are needed; the existing --bone / --sand / --amber vars still do that work.
   --------------------------------------------------------------------------- */

.back-bar { padding: 0.6rem 1.5rem; }

.module-hero {
  text-align: left;
  padding: 0.9rem 1.5rem 0.7rem;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.55rem;
}

/* Title first, the "Module 01" label demoted to a chip beside it. */
.module-title {
  order: 1;
  font-size: clamp(1.35rem, 3.2vw, 1.75rem);
  line-height: 1.15;
}
.module-label {
  order: 2;
  margin-bottom: 0;
  font-size: 0.56rem;
  letter-spacing: 3px;
  opacity: 0.7;
}
.module-subtitle {
  order: 3;
  flex-basis: 100%;
  font-size: 0.82rem;
  margin-top: 0.05rem;
  opacity: 0.85;
}

/* On a phone the subtitle is pure flavour and costs a line of a short screen. */
@media (max-width: 600px) {
  .module-hero { padding: 0.7rem 1rem 0.55rem; }
  .back-bar { padding: 0.5rem 1rem; }
  .module-subtitle { display: none; }
}

/* ---------------------------------------------------------------------------
   Three headers were stacking: the top bar naming the module, a .back-bar
   holding nothing but a QWENCHED wordmark the rail already shows, and the hero
   naming the module again. The .back-bar is a vestige of the old "back to hub"
   navigation — its button was removed when the rail replaced it, leaving an
   empty branded strip.

   The hero stays, trimmed to just its title. It is doing one useful job now:
   the .user-pill is position:fixed at the top right, so if module content began
   immediately under the top bar, the pill would sit on top of it — on Pipeline,
   directly over "+ ADD EVENT". The hero's empty right-hand side is what the pill
   floats over harmlessly. Moving the pill into the top bar would let the hero go
   entirely; that is a markup change for later.
   --------------------------------------------------------------------------- */

.back-bar { display: none; }

.module-hero {
  padding: 0.75rem 1.5rem 0.5rem;
}

/* "MODULE 09" is legacy numbering from the tile grid — the rail groups modules
   now, so the number indexes nothing. The subtitle is flavour. Both cost a line. */
.module-label,
.module-subtitle { display: none; }

@media (max-width: 600px) {
  .module-hero { padding: 0.6rem 1rem 0.45rem; }
}

/* ---------------------------------------------------------------------------
   The event size legend was a full-width pill — background, border, 0.7rem of
   padding and a 1.2rem margin — spending roughly 60px of vertical space on a
   three-item key you read once and then stop seeing. It is a footnote, so it
   now looks like one: no box, smaller type, tight margin.
   --------------------------------------------------------------------------- */
.ev-legend {
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  gap: 0.85rem;
  margin-bottom: 0.45rem;
  font-size: 0.66rem;
  opacity: 0.85;
}
.ev-legend-item { gap: 4px; }
.ev-legend-sub { font-size: 0.6rem; margin-left: 2px; }
.ev-dot { width: 8px; height: 8px; border-radius: 2px; }

/* Close the gap the legend used to hold open above it. */
.ev-controls, .events-wrap > .ev-legend { margin-top: 0; }

/* ---------------------------------------------------------------------------
   Scrollbars — overlay, not furniture
   ---------------------------------------------------------------------------
   The hub stacks several independent scroll regions (the rail, the module body,
   the event card, the task form, and ~25 more in the inline styles). Each one
   draws its own scrollbar, and unstyled that means a chunky opaque track per
   region — on macOS with "always show scrollbars" the app reads as a set of
   nested 2008 iframes.

   The fix is not fewer scroll regions, which is a layout change. It is making
   the scrollbar stop claiming layout width and stop being opaque: a thin
   translucent thumb over a transparent track, so a scroll region announces
   itself only while it has overflow, and recedes otherwise.

   Both syntaxes are needed and they are not interchangeable. `scrollbar-width`
   / `scrollbar-color` is the standard property, honoured by Firefox and by
   Chrome 121+. `::-webkit-scrollbar` is the older pseudo-element and is what
   Safari — including iOS, where this is installed as a PWA — actually obeys.
   Safari ignores the standard property entirely, so dropping the webkit block
   would leave the phone looking exactly as it does now.

   This lives at the end of shell.css deliberately. shell.css loads after the
   inline <style>, so at equal specificity these win on source order — the same
   rule that governs every other override in this file.
   --------------------------------------------------------------------------- */

* {
  scrollbar-width: thin;
  scrollbar-color: rgba(240, 232, 216, 0.22) transparent;
}
body.light-theme * {
  scrollbar-color: rgba(26, 20, 16, 0.22) transparent;
}

*::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

/* Transparent, not a colour. A tinted track is the single thing that makes a
   scroll region look like a bordered panel rather than a surface that happens
   to scroll. */
*::-webkit-scrollbar-track {
  background: transparent;
}

/* border rather than margin: a transparent border inset by background-clip is
   the only way to give a webkit thumb breathing room without it painting to
   the full 8px gutter. */
*::-webkit-scrollbar-thumb {
  background-color: rgba(240, 232, 216, 0.22);
  border-radius: 8px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover {
  background-color: rgba(240, 232, 216, 0.38);
}
body.light-theme *::-webkit-scrollbar-thumb {
  background-color: rgba(26, 20, 16, 0.22);
}
body.light-theme *::-webkit-scrollbar-thumb:hover {
  background-color: rgba(26, 20, 16, 0.38);
}

/* The corner where a vertical and horizontal bar meet renders as an opaque
   light square in Safari if left alone — small, but it is exactly the kind of
   grey artefact this whole block exists to remove. */
*::-webkit-scrollbar-corner {
  background: transparent;
}

/* The rail is a fixed-height list of ten or so items. It scrolls only on a
   short viewport, and a visible bar there just narrows the labels. Chrome and
   Safari take the pseudo-element; `scrollbar-width: none` covers Firefox. */
#appRail {
  scrollbar-width: none;
}
#appRail::-webkit-scrollbar {
  width: 0;
  height: 0;
}

/* ---------------------------------------------------------------------------
   Collapsible rail groups
   ---------------------------------------------------------------------------
   Run is eight modules used standing at the cart, not deciding what to apply
   for. Shut by default, it hands roughly a third of the rail back to Plan and
   More — which is where the work that needs a decision lives.

   The label becomes a real <button> when the group collapses, so it is
   keyboard-reachable and announces its state. `all: unset` is not used: it
   would drop the inherited font stack and reintroduce a browser default, so
   the button's own chrome is removed by hand and the label rule above still
   applies to it via the shared class.

   Hidden with display:none rather than max-height, deliberately. A height
   animation on a list whose length varies has to guess a maximum, and guessing
   short silently clips the last item — which here would be Capture quietly
   vanishing from the rail with nothing to indicate it existed.
   --------------------------------------------------------------------------- */

.rail-group-toggle {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%; background: none; border: 0; cursor: pointer;
  text-align: left; font: inherit;
  /* Matches .rail-group-label's padding, plus a little top room so the larger
     tap target does not crowd the group above it. */
  padding: 0.15rem 1.3rem 0.6rem;
}
.rail-group-toggle:hover { color: #C4A882; }
body.light-theme .rail-group-toggle:hover { color: #1A1410; }

/* A caret rather than a chevron glyph: it inherits the text colour, costs no
   markup, and rotating it is the whole animation. */
.rail-group-caret {
  transition: transform 0.18s ease;
  font-size: 0.95rem; line-height: 1; opacity: 0.75;
}
.rail-group-open > .rail-group-toggle .rail-group-caret { transform: rotate(90deg); }

.rail-group-collapsible > .rail-group-items { display: none; }
.rail-group-collapsible.rail-group-open > .rail-group-items { display: block; }

/* A shut group needs less room beneath it than an open one — otherwise
   collapsing Run leaves a gap the size of the list that used to be there. */
.rail-group-collapsible:not(.rail-group-open) { margin-bottom: 0.9rem; }

@media (prefers-reduced-motion: reduce) {
  .rail-group-caret { transition: none; }
}

/* ---------------------------------------------------------------------------
   Mobile scrolling — stop the bounce
   ---------------------------------------------------------------------------
   Two separate causes, both only visible on a phone.

   1. SCROLL CHAINING. The hub has eight independent scroll containers — the
      rail, the module body, the event card, the task form, the duplicate check,
      the password reset sheet, the receipt sheet. Only the event card ever set
      `overscroll-behavior`. On iOS, when a nested scroller hits its end the
      gesture continues into whatever is behind it, so the page under an open
      sheet starts moving mid-swipe and the whole thing appears to slide around.
      `contain` keeps the gesture inside the box it started in. It does NOT
      disable scrolling anywhere; it stops one scroll becoming two.

   2. 100vh. On iOS Safari the viewport unit includes the strip behind the
      address bar, which appears and disappears as you scroll, so a `100vh`
      element changes height mid-gesture and the content jumps. `dvh` is the
      dynamic equivalent and tracks the visible area. The `vh` line stays first
      as the fallback for anything that does not know `dvh`.

   Applied here rather than in each file because shell.css loads after the
   inline <style> and after every other stylesheet, so at equal specificity
   these win on source order — the same rule that governs the rest of this file.
   --------------------------------------------------------------------------- */



body {
  min-height: 100vh;
  min-height: 100dvh;
}

/* EVERY scroll container, via the universal selector — deliberately.
   My first attempt at this listed eleven class names and only three of them
   existed; the rest were plausible inventions, so the rule would have applied
   itself to nothing while looking correct in the stylesheet. A named list has to
   be right today AND stay right as modules are added, and there are now
   fourteen of them written by different hands.

   `overscroll-behavior` only does anything on an element that actually scrolls —
   it is inert everywhere else — so a universal rule is not the blunt instrument
   it looks like. It changes exactly the boxes it needs to and nothing else. */
* {
  overscroll-behavior: contain;
}

/* Momentum scrolling, on the containers known to be long enough to need it.
   Default on current iOS, but an installed PWA can land on an older engine and
   these scroll stiffly without it. */
#appRail,
.agent-body,
.ev-form-body,
.dup-card-body,
.capture-raw {
  -webkit-overflow-scrolling: touch;
}

/* The rail is a fixed overlay on a phone. When it is open the page behind must
   not scroll at all — otherwise closing it returns you somewhere you did not
   choose to be, which reads as the app losing your place. */
@media (max-width: 1023px) {
  body.rail-open {
    overflow: hidden;
  }
}

/* After the universal rule, so it wins: the document itself gets `none` rather
   than `contain`, which additionally stops the whole page rubber-banding past
   its own ends. In an installed PWA that bounce reads as the app coming away
   from the top of the screen. */
html {
  overscroll-behavior-y: none;
}
